当前位置: 首页 > news >正文

vue-element-admin 迁移到 rsbuild v1

本文旨在尽量兼容现有开发环境的情况下,将 vue-cli 4 迁移至 rsbuild v1。

vue-element-admin 迁移到 rsbuild v1

最近接触到一个老旧项目,使用的是 vue-element-admin,习惯了 vite 和 rspack 这类 Rust 构建工具,webpack 作为老牌构建工具开发体验实在是一言难尽,本文将直接从 fork 的 vue-element-admin 仓库开始,将项目迁移到 rsbuild v1。

为什么是 rsbuild v1 而不是 v2?

为了确保开发及构建环境不会存在大的变动(说白了减少升级带来的负担),采用 rsbuild v1.4(node>=16.10.0),因为 v1.5 需要 node 18 及以上,而目前此项目使用的 node14 在 jenkins 上进行的构建,node 14 升级到 Node18 会有很多的兼容性问题,而升级到 16 则基本可以平滑升级。详见 rsbuild 环境

如果觉得文章过长,也可以直接查看 vue-element-admin-rsbuild 的 commit 记录查看变更差异。

环境准备

  • 升级 node 版本 node>=16.10.0
  • 遵循 vue cli 迁移 开始操作

迁移步骤

基本遵循官方文档的迁移步骤,但是官方迁移的教程太简陋了,因此会增加大量需要注意的说明

未标注版本号的依赖可以直接安装,标注版本的则必须安装对应版本

安装依赖

移除 vue-cli 依赖

npm remove @vue/cli-service @vue/cli-plugin-babel @vue/cli-plugin-eslint core-js

安装 rssbuild 依赖。

  • @rsbuild/core 必须锁定 1.4.16 版本,这是最后一个支持 node16 的版本
  • @rsbuild/plugin-vue2 必须锁定 1.0.6 版本,这是最后一个支持 rsbuild v1 的版本。
npm i @rsbuild/core@1.4.16 @rsbuild/plugin-vue2@1.0.6 -DE

升级 vue 版本至 2.7.16,因为 rsbuild 的 vue2 插件仅支持 2.7.0 及以上版本。

npm i vue@2.7.16 vue-template-compiler@2.7.16 -E

安装 vue2 jsx 插件 babel 插件。vue-element-admin 使用了 vue2 jsx 语法,而解析 jsx 需要 babel 插件。

npm i @rsbuild/plugin-vue2-jsx @rsbuild/plugin-babel@1.2.1 -DE

安装 sass 插件,因为 vue-element-admin 使用了 sass 语法

npm i @rsbuild/plugin-sass -D

安装 node polyfill 插件。原因是 webpack 5 之前默认 polyfill Node 内置,而 HeaderSearch、Sidebar 等组件多处使用。

npm i @rsbuild/plugin-node-polyfill -D

配置 rsbuild

根目录新增 rsbuild.config.mjs 文件,将安装的 rsbuild 插件集成到配置里。

由于 vue-element-admin 使用了很多 commonjs 语法,为了减少改动,package.json 不添加 type: module,相应的,rsbuild.config 要以 mjs 结尾。

import { pluginBabel } from "@rsbuild/plugin-babel";
import { pluginVue2 } from "@rsbuild/plugin-vue2";
import { pluginVue2Jsx } from "@rsbuild/plugin-vue2-jsx";
import { pluginSass } from "@rsbuild/plugin-sass";
import { pluginNodePolyfill } from "@rsbuild/plugin-node-polyfill";export default {plugins: [pluginBabel({include: /\.(?:jsx|tsx)$/,}),pluginVue2(),pluginVue2Jsx(),pluginSass(),pluginNodePolyfill(),],
};

迁移 vue cli 配置

环境变量

vue-cli 环境变量默认以 VUE_APP_ 开头在代码中使用,使用 rsbuild 的 loadEnv 配置项进行兼容即可。

// https://v1.rsbuild.rs/zh/guide/advanced/env-vars#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%89%8D%E7%BC%80
const { publicVars } = loadEnv({ prefixes: ["VUE_APP_"] });export default defineConfig({source: {// 指定入口文件entry: {index: "./src/main.js",},// 声明环境变量define: publicVars,},
});

html 模板

import defaultSettings from "./src/settings.js";
const name = defaultSettings.title || "vue Element Admin"; // page titleexport default defineConfig({html: {template: "./public/index.html",favicon: "./public/favicon.ico", // 这行可以不添加,因为 rsbuild 默认会从 public 下获取 favicontitle: name,// 如果 name 还在除了 <title> 标签外,请添加 templateParameters 配置// templateParameters: {//   name: "world",// },},
});

去掉两行,这两行可以通过 rsbuild 配置。

<title><%= webpackConfig.name %></title> 去掉,修改 <link rel="icon" href="<%= BASE_URL %>favicon.ico">

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><meta name="renderer" content="webkit" /><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="icon" href="<%= assetPrefix %>/favicon.ico" /></head><body><div id="app"></div><!-- 以下是一个非 <title> 标题使用了 webpackConfig.name 的例子: --><!-- 如果非标题也使用了 webpackConfig.name,请先添加 templateParameters 配置变量,然后将 webpackConfig.name 改为 name  --><!-- <noscript><strong>We're sorry but <%= name %> doesn't work properly without JavaScriptenabled. Please enable it to continue</strong></noscript> --><!-- built files will be auto injected --></body>
</html>

配置 devServer

vue cli devServer 对应 rsbuild 的 serverdevServer.overlay 对应的是 rsbuild 的 dev.client.overlay,默认启用错误时的内容提示,因此可以安全将 devServer.overlay 配置项移除

const port = process.env.port || process.env.npm_config_port || 9527; // dev portexport default defineConfig({server: {port: port,open: true,},
});

迁移 mock server

rsbuild 中没有直接对应 devServer.before 配置项,但是 rsbuild 提供了 setupMiddlewares 可以进行 mock 配置,详见 集成第三方服务端框架

根据官网的介绍,需要先安装 express,不能安装 express v5 版本。v5 需要 node>=18。

npm i express@4.22.2 -DE
import express from "express";
import mockServerMiddleware from "./mock/mock-server";export default defineConfig({dev: {setupMiddlewares: (middlewares) => {// 一定要在这里初始化,否则在打包时会执行到 mock-server 的 chokidar.watch() 导致进程无法退出const app = express();mockServerMiddleware(app); // mock-server.js 需要接收一个 appmiddlewares.unshift(app);},},
});

配置 alias

export default defineConfig({resolve: {alias: {"@": "./src",},},
});

构建配置

以 vue-element-admin 来说,以下配置都不需要,因为都是默认配置,如果。

export default defineConfig({output: {distPath: {root: "dist",}, // 对应 outputDir: 'dist',可删除,rsbuild 默认配置assetPrefix: "/", // 对应 publicPath: '/'// 对应 assetsDir 其实和 rsbuild 的默认 assets 输出一致,可以不用新增保持默认配置也行// https://v1.rsbuild.rs/zh/config/output/dist-path#outputdistpath// distPath: {//   js: 'static/js',//   css: 'static/css',//   image: 'static/img',//   font: 'static/fonts'// }// 对应 productionSourceMap,可不添加,保持 rsbuild 默认配置即可。// sourceMap: {//   js: process.env.NODE_ENV === 'development' ? 'cheap-module-source-map' : false,//   css: false// },},
});

chainWebpack

从 chainWebpack 从上往下配置慢慢过一遍。

preload 配置

对应 源码

export default defineConfig({performance: {preload: {type: "initial", // include: 'initial'exclude: [/\.map$/, /hot-update\.js/, /runtime\..*\.js$/], // fileBlacklist},},
});

prefetch

element vue admin 关闭了 prefetch,对应 源码

在 rsbuild 中,不需要添加和删除任何东西,因为 prefetch 在 rsbuild 中默认是关闭的。

SVG sprite-loader

对应 源码。

使用 rsbuild 的 tools.bundlerChain 即可,基本完全不用改动。

不能使用 tools.webpackChain,因为这个 api 看似是兼容 webpack 的,但其实是依赖 webpack 的, rsbuild 默认使用的是 rspack,此 api 不会生效,官方文档也没有对其相关的说明,仅作为 modern.js 内部的兼容使用。

import { resolve } from "node:path";export default defineConfig({tools: {bundlerChain: (chain) => {chain.module.rule("svg").exclude.add(resolve("src/icons")).end();chain.module.rule("svg-icons").test(/\.svg$/).include.add(resolve("src/icons")).end().use("svg-sprite-loader").loader("svg-sprite-loader").options({symbolId: "icon-[name]",});},},
});

runtime 的 js 文件内联

对应 源码

可以使用 rsbuild 的 output.inlineScripts 配置

export default defineConfig({output: {inlineScripts: {include: /runtime\..*\.js$/,},},
});

splitChunks

对应 源码

可使用 rsbuild 的 performance.splitChunks 配置

export default defineConfig({performance: {splitChunks: {strategy: "custom",splitChunks: {cacheGroups: {libs: {name: "chunk-libs",test: /[\\/]node_modules[\\/]/,priority: 10,chunks: "initial",},elementUI: {name: "chunk-elementUI",test: /[\\/]node_modules[\\/]_?element-ui/,priority: 20,},commons: {name: "chunk-commons",test: /src[\\/]components[\\/]/,minChunks: 3,priority: 5,reuseExistingChunk: true,},},},},},
});

runtimeChunk

对应 源码

这个在 rsbuild 没有直接对应的 api,但是 rspack 兼容 webpack,因此可以使用 rspack 的 api 进行配置。

export default defineConfig({tools: {rspack: (config) => {config.optimization.runtimeChunk = "single";},},
});

至此,配置迁移完毕,接下来进行运行测试。

运行测试

更新 script

移除 vue-cli 对应的脚本命令,新增 rsbuild 命令

{"serve": "rsbuild dev","build:prod": "rsbuild build","build:stage": "vue-cli-service build --env-mode staging","preview": "rsbuild preview"
}

移除无用依赖

由于使用 rsbuild 部分依赖 vue-cli 的依赖或者 webpack 的 loader 依赖可以安全移除。

如果你不移除以下依赖,这些依赖在安装时会将 webpack@4 版本带入项目,而 rsbuild 兼容的是 webpack@5,运行会报错的。

npm remove html-webpack-plugin script-ext-html-webpack-plugin @vue/cli-plugin-unit-jest sass-loader

移除后,大概率需要删除 package-lock.json 和 node_modules 重新安装依赖。仅删除 node_modules 可能存在部分遗留的依赖引用

删除 .babelrc 中的 @vue/cli-plugin-babel 配置,因为此依赖已经被移除了,由 rsbuild 进行 babel 转义

运行项目并排查代码报错

运行 npm run serve 启动项目,可能会出现如下错误:

0620260620021103360

这个看起来像是 jsx 语法 Babel 插件没识别到,手动在报错文件的 script 添加 lang="jsx" 就解决了。

下一个报错:

0620260620021517385

这个错误是将 sass 的 :export 样式作为 js 进行使用,而正常情况下,这种应用方式只允许 css module 使用。

如果你直接将对应文件改成 .module.scss 结尾并更新相关导入,其实会发现是有问题的。因为 element-variables.scss 引入了 element-ui 的样式,而且也使用了 :export 语法,css module 会将 element-ui 的样式进行 scope,导致 element-ui 的样式失效

element-variables.scss 拆分:

0620260620145150933

// _theme-vars.scss
$--color-primary: #1890ff;// element-variables.scss 删除 :export 部分,导入 _theme-vars.scss,其它保持不变
@import "./theme-vars";// element-variables.module.scss
@import "./theme-vars";:export {theme: $--color-primary;
}

element-ui 的样式搞定了,还有一个 Sidebar 组件中使用了 variable.scss 作为 js,这个 css 可以安全的改为 .module.scss 后缀并更新导入即可,因为不涉及 css 样式,是纯 scss 变量,不影响。

此时运行项目,应该没有报错了。

其它可能出现的代码报错

由于当前迁移是完全使用 vue-element-admin 源码迁移,但实际项目可能对其进行各种扩展改造,因此不一定会遇到什么问题,这些报错基本都属于代码层写法问题,通过 ai 可以很方便进行定位解决。此处列举几个常见的报错。

后端路由数据动态注册前端路由

常规后台管理系统,前端路由通过后端返回的数据进行动态注册

// 动态 require 路由,伪代码
item.component = (resolve) =>require([`@/views${item.path ? item.path : ""}`], resolve);// 需改为
item.component = () => import(`@/views${item.path ? item.path : ""}`);

深度选择器

>>> 这种写法在 sass 预处理器中可能不被支持,需替换为正常 vue 写法 ::v-deep(已废弃但可用,会有警告) 或 /deep/:deep()(推荐)

css 警告如果工作量较大,可以忽略,也可以交给 ai 来批量处理。

吐槽

老实说,vue-element-admin 在 20 年那时候确实惊艳,但是放到现在就有点破产了,而且这篇文章其实没什么受众。

如果一个公司愿意用原本的技术栈不变始终码代码,那大概率也不会关心开发体验问题,主打一个能跑就行,这部分人也基本不会选择冒险进行构建工具升级迁移的,所以这篇迁移教程定位其实挺尴尬的,基本属于白写。

http://www.jsqmd.com/news/1049487/

相关文章:

  • 3分钟掌握B站缓存视频转换:m4s-converter终极使用教程
  • 劳力士官方授权售后维修中心正式辟谣|2026年6月最新发布:亨得利全国正规售后服务门店+真实消费者对话记录 - 亨得利官方维修中心
  • 微信聊天记录永久保存完整指南:免费工具让数据真正属于你
  • 权威官方公告!萧邦官方售后维修服务网点,售后咨询电话与官方门店完整地址查询 - 速递信息
  • Steam成就管理引擎:高性能游戏数据处理架构深度解析
  • 告别手动分层:用AI智能工具将单张图片秒变专业PSD文件
  • 如何创建文心一言认可的百度百科关键词条?百家号文章快速被 AI 引用的核心技巧 - 速递信息
  • 2026西安钻石首饰回收指南:七家门店4C标准复检与品牌钻饰估价全记录 - 薛定谔的梨花猫
  • 终极Windows风扇智能控制:FanControl专业深度解析指南
  • 把日子过成自己喜欢的样子
  • SGNavigationProgress源码解读:从SGProgressView到分类实现的完整架构
  • 深圳南山葡萄牙语培训哪家值得推荐 - 速递信息
  • XcodeGen终极指南:告别Xcode项目文件合并冲突的终极解决方案
  • 深圳汉语培训哪个好 - 速递信息
  • 嵌入式GUI开发:emWin控件API设计哲学与CHECKBOX、DROPDOWN实战详解
  • 2026 AI应用生存地图:工作流切片法实战指南
  • 2026无锡黄金回收城市榜单:以奢响佳为代表的S+评级门店具备11项透明资质 - 商业信息快查
  • 添价收 2026 西安全域收包 长安未央均可预约上门取件 - 薛定谔的梨花猫
  • 如何将数字文本转换为逼真手写体:开源工具 text-to-handwriting 的完整指南
  • 用 AI 导出鸭极速导出内容,AI 输出无乱码,排版整洁一键落地
  • 深圳福田越南语培训哪个机构专业 - 速递信息
  • 终极React Fiber入门:理解React 16核心架构的革命性算法
  • 2026郑州婚纱照选购全攻略|主流品牌分级测评避坑大全 - charlieruizvin
  • 微漫app数据库架构详解:Hive本地存储与数据同步的完整实现方案
  • 2026读懂广州企业合规避坑要点|执业律师专业解读,本地律师事务所服务选型参考 - 速递信息
  • Octopi完整教程:如何优雅管理Arch Linux软件包的终极指南
  • 外墙防水常见问题解答(2026最新专家版) - 速递信息
  • 2026南宁奢侈品回收行业白皮书:名牌包闲置落灰贬值!本地门店回收,当场全款结算不拖沓 - 讯息早知道
  • 【实战】多模型编程时代已至:Codex+Claude+Gemini 组合拳实战,让 AI 替你写代码
  • 5p022网络入侵检测系统(django)1(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_可以扫码