Vue2迁移Rsbuild详细步骤
作者:前端伟哥
背景
遇到的瓶颈
公司项目基于 VueCLI 3,存在启动慢(约 30 秒)、热重载慢、构建慢以及对高版本 Node 支持不友好等问题,需要切换 Node 16版本才能启动。
Rsbuild 简单介绍
- Rsbuild于 2024.09.10 发布
v1.0.1正式版,而且提的 issue 也很快得到解决。 - Rsbuild是基于 Rspack 的一个构建工具,一个高性能集成工具,几乎零配置就可以构建项目。
- Rspack可以解决vite开发期间的页面加载速度慢,开发环境、生产环境构建机制不一致的问题。
- Webpack 生态兼容性,Rspack 可以兼容 Webpack 的大部分插件。
具体步骤
1.根据官方提供的简易指南完成迁移。
// rsbuild.config.js
const { defineConfig } = require('@rsbuild/core');
const { pluginVue2 } = require('@rsbuild/plugin-vue2');
export default defineConfig({
html: {
template: './public/index.html',
},
plugins: [pluginVue2()],
source: {
// 指定入口文件
entry: {
index: './src/main.js',
},
},
});
2.修订别名和路径简写
在项目中,通常会使用 @/xxx 的形式来引入模块,这里要配置 alias 能力。
// rsbuild.config.js
const { defineConfig } = require('@rsbuild/core');
const path = require('path');
export default defineConfig({
source: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
});
3.安装并支持 Babel、JSX、Less、SCSS
// rsbuild.config.js
const { defineConfig } = require('@rsbuild/core');
const { pluginLess } = require('@rsbuild/plugin-less');
const { pluginSass } = require('@rsbuild/plugin-sass');
const { pluginBabel } = require('@rsbuild/plugin-babel');
const { pluginVue2Jsx } = require('@rsbuild/plugin-vue2-jsx');
export default defineConfig({
plugins: [
...,
pluginBabel({
include: /\.(?:jsx|tsx)$/,
// exclude: /[\\/]node_modules[\\/]/,
}),
pluginVue2Jsx(),
pluginLess({
lessLoaderOptions: {
lessOptions: {
javascriptEnabled: true,
math: 'always',
},
},
}),
pluginSass(),
],
});
在使用 JSX 时,需要为 <script> 标签指定 lang 属性,可以全局将 <script> 替换成 <script lang="jsx">。
<script lang="jsx">
export default {
render() {
return <div>123</div>;
},
};
或者使用脚本扫一遍 scr 目录下使用 JSX 的 vue 文件。
import { readFile, writeFile } from 'fs/promises';
import { globby } from 'globby';
import ts from 'typescript';
async function run() {
const paths = await globby('src', {
expandDirectories: {
extensions: ['vue'],
},
});
for (const path of paths) {
const file = await readFile(path, { encoding: 'utf8' });
const contentArr = file.split('\n');
const start = contentArr.findIndex((item) => item.includes('<script>'));
const end = contentArr.findIndex((item) => item.includes('</script>'));
if (start === -1) continue;
const scriptContent = contentArr.slice(start + 1, end).join('\n');
const result = ts.transpileModule(scriptContent, {
compilerOptions: { module: ts.ModuleKind.ESNext, jsx: 'react' },
});
if (result.outputText.includes('React.createElement')) {
await writeFile(path, file.replace('<script>', '<script lang="jsx">'), { encoding: 'utf8' });
}
}
}
run();
rsbuild 内置的是 LESS 4,style 必须指定 scoped 属性,需要将 /deep/ 替换为 ::v-deep,可以全局替换。
<style src="./style.less" lang="less" scoped></style>
// style.less
//.drawer /deep/.ant-drawer-body{
// padding: 0 24px !important;
//}
.drawer ::v-deep .ant-drawer-body{
padding: 0 24px !important;
}
4.CLI参数
rsbuild 的 cli 会拦截不认识的参数,因此像vue-cli-service serve --oem=xxx这样的命令在 rsbuild 下会报错,我们需要这样传入自定义的命令行参数rsbuild dev -- --oem=xxx。
5.环境变量
rsbuild 默认只会注入PUBLIC_开头的环境变量,为了兼容Vue CLI的行为,以及读取其他自定义的环境变量,需要使用loadEnv载入VUE_APP_开头的环境变量并通过source.define配置。
// rsbuild.config.js
const { defineConfig, loadEnv } = require('@rsbuild/core');
const { publicVars: vueEnvs } = loadEnv({ prefixes: ['VUE_APP_'] });
export default defineConfig({
source: {
define: {
...vueEnvs,
'process.env': {
// ...process.env,
OEM: JSON.stringify(argv.oem)
},
},
},
});
6.HTML 模板变量
将<%= BASE_URL %>替换为<%= assetPrefix %>/,注意要在末尾加上斜杠。其余变量可以使用html.templateParameters来设置
// rsbuild.config.js
const { defineConfig } = require('@rsbuild/core');
const { version } = require('./package.json');
export default defineConfig({
html: {
template: './public/index.html',
templateParameters: {
version,
title: process.env.VUE_APP_SYSTEM_NAME
},
},
});
7.开启 HTTPS 服务
const { defineConfig } = require('@rsbuild/core');
const { pluginBasicSsl } = require('@rsbuild/plugin-basic-ssl');
module.exports = defineConfig({
plugins: [
...,
pluginBasicSsl(),
],
server: {
port: 8080,
proxy: {
'/api': {
target: 'http://10.1.1.139:19090',
secure: false, // 设置支持https协议的代理
pathRewrite: {
'^/api': '',
},
// onProxyRes(proxyRes) {
// if (proxyRes.headers['set-cookie']) {
// proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((v) => {
// return v.replace('Path=/edr', 'Path=/');
// });
// }
// },
},
},
},
});
8.将 vue 组件 Compiler 写法修改为 render 写法。
在使用 ant-design 1.x 时,自定义图标时,文档里的写法是 Compiler 方式,同时 vue.config.js 需要配置runtimeCompiler: true,在 rsbuild 里不支持这种写法,需要改成 render 写法。
const ProtectiveLogSvg = {
template: `<svg t="1666607819931" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="52249" width="200" height="200"><path d="M512 64c0 0-44.416 111.936-328.448 111.936l0 458.88C183.552 816.192 512 960 512 960s328.448-143.808 328.448-325.184l0-458.88C555.392 175.936 512 64 512 64zM510.656 494.656 224.768 494.656 224.768 217.984c223.936 0 277.504-79.488 285.952-95.168L510.72 494.656zM799.232 619.456c0 158.528-286.784 284.224-287.232 284.416L512 494.656l287.232 0L799.232 619.456z" p-id="52250"></path></svg>`,
};
const ProtectiveLogIcon = {
template: `
<a-icon :component="ProtectiveLogSvg" />
`,
data() {
return {
ProtectiveLogSvg,
};
},
};
替换为:
const ProtectiveLogSvg = {
name: 'ProtectiveLogSvg',
functional: true,
render() {
return (
<svg
t="1666607819931"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="52249">
<path
d="M512 64c0 0-44.416 111.936-328.448 111.936l0 458.88C183.552 816.192 512 960 512 960s328.448-143.808 328.448-325.184l0-458.88C555.392 175.936 512 64 512 64zM510.656 494.656 224.768 494.656 224.768 217.984c223.936 0 277.504-79.488 285.952-95.168L510.72 494.656zM799.232 619.456c0 158.528-286.784 284.224-287.232 284.416L512 494.656l287.232 0L799.232 619.456z"
p-id="52250"></path>
</svg>
);
},
};
const ProtectiveLogIcon = {
name: 'ProtectiveLogIcon',
functional: true,
render(h) {
return h('a-icon', { props: { component: ProtectiveLogSvg } });
},
};
9.移除不必要的文件
- vue.config.js
- babel.config.js
迁移下来打包编译的速度从 30s 到 6s 提升了大概 5 倍,而热重载基本更改后就生效。最后如果有什么错误之处欢迎指出。
完整配置
const { defineConfig, loadEnv } = require('@rsbuild/core');
const { pluginVue2 } = require('@rsbuild/plugin-vue2');
const { pluginBabel } = require('@rsbuild/plugin-babel');
const { pluginVue2Jsx } = require('@rsbuild/plugin-vue2-jsx');
const { pluginLess } = require('@rsbuild/plugin-less');
const { pluginSass } = require('@rsbuild/plugin-sass');
const { pluginBasicSsl } = require('@rsbuild/plugin-basic-ssl');
const path = require('path');
const { version } = require('./package.json');
const { publicVars: vueEnvs } = loadEnv({ prefixes: ['VUE_APP_'] });
module.exports = defineConfig({
html: {
template: './public/index.html',
templateParameters: {
version,
title: process.env.VUE_APP_SYSTEM_NAME,
},
},
plugins: [
pluginBasicSsl(),
pluginVue2(),
pluginBabel({
include: /\.(?:jsx|tsx)$/,
// exclude: /[\\/]node_modules[\\/]/,
}),
pluginVue2Jsx(),
pluginLess({
lessLoaderOptions: {
lessOptions: {
javascriptEnabled: true,
math: 'always',
},
},
}),
pluginSass(),
],
source: {
define: {
...vueEnvs,
'process.env': {
// ...process.env,
},
},
entry: {
index: './src/main.js',
},
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
server: {
port: 8080,
proxy: {
'/api': {
target: 'http://10.1.1.139:19090',
secure: false, // 设置支持https协议的代理
pathRewrite: {
'^/api': '',
},
// onProxyRes(proxyRes) {
// if (proxyRes.headers['set-cookie']) {
// proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((v) => {
// return v.replace('Path=/edr', 'Path=/');
// });
// }
// },
},
},
},
});
以上就是Vue2迁移Rsbuild详细步骤的详细内容,更多关于Vue2迁移Rsbuild的资料请关注脚本之家其它相关文章!
