原项目基于vue-cli+ webpack5 + vue2.7开发,随着项目开发代码累加,打包时间不可避免的增加,开发环境启动耗时比较漫长,需要一个高性能的构建工具。 Rspack是基于Rust的构建引擎,兼容webpack大部分功能,可以以极低的成本替换vue-cli+ webpack5。
安装
直接在原项目于安装@rspack/cli
css
npm i @rspack/cli
配置文件
Rspack 默认通过 rspack.config.js
来配置打包行为,我们可以在项目根目录下创建一个 rspack.config.js
文件。
lua
const path = require('path');
module.exports = {
entry: {
main: './src/main.ts',
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
Rspack拥有与 webpack 相似的配置项,涉及的配置项有:
- vue-loader
- typescript
- vue2 jsx 兼容
- sass/less,prependData注入
- worker-loader
- DefinePlugin
- ProvidePlugin
- HtmlWebpackPlugin or HtmlRspackPlugin
- resolve 中的 alias、extensions
- devServer
vue编译配置
Rspack 已经完成对 Vue2(使用 vue-loader@15)的兼容,需要引入 VueLoaderPlugin,将定义过的其它规则复制并应用到 .vue
文件里相应语言的块。例如有一条匹配 /.js$/
的规则,那么它会应用到 .vue
文件里的 <script>
块。
解析单文件组件用到 vue-style-loader,需要关闭原生 css(experiments.css)支持。 sass-loader、less-loader的配置是和webpack兼容的。
Typescript 可以用内置的 swc-loader 支持。
Rspack 开箱支持worker-loader,若原来有配置需要移除。
css
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
entry: {
main: './src/main.ts',
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// 注意,为了绝大多数功能的可用性,请确保该选项为 `true`
experimentalInlineMatchResource: true,
},
},
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
type: 'javascript/auto',
},
{
test: /\.sass$/,
use: [
{
loader: 'sass-loader',
options: {
// ...
},
},
],
type: 'css/auto', // 如果你需要将 '*.module.(sass|scss)' 视为 CSS Module 那么将 'type' 设置为 'css/auto' 否则设置为 'css'
},
{
test: /\.ts$/, // 如果需要在 Vue SFC 里使用 Typescript, 请添加该规则
loader: 'builtin:swc-loader',
options: {
sourceMap: true,
jsc: {
parser: {
syntax: 'typescript',
},
},
},
type: 'javascript/auto',
},
],
},
experiments: {
css: false,
},
plugins: [new VueLoaderPlugin()],
};
vu2 jsx 处理
vue-cli使用@vue/babel-preset-app 匹配全部vue/js文件解析jsx,在vue-cli工程里的vue/js文件都可以写jsx。 Rspack里需要为vue sfc文件加上lang="jsx"去匹配loader。js文件里如果写了jsx则需要根据实际情况修改test字段去匹配。
yaml
module.exports = {
module: {
rules: [
{
test: /\.[jt]sx$/,
use: [
{
loader: 'babel-loader',
options: {
presets:[
[
'@babel/preset-typescript',
{ isTSX: true, allExtensions: true }
],
[
'@babel/preset-jsx',
{ compositionAPI: true }
]
]
},
},
],
},
],
},
};
资源模块
和webpack5一样指定资源类型,用内置的模块处理,不需额外的loader,资源类型有:
asset/resource
发送一个单独的文件并导出 URL。之前通过使用file-loader
实现。asset/inline
导出一个资源的 data URI。之前通过使用url-loader
实现。asset/source
导出资源的源代码。之前通过使用raw-loader
实现。asset
在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用url-loader
,并且配置资源体积限制实现。
bash
module.exports = {
module:{
rules:[
{
test: /\.(svg|png|jpe?g|gif|webp|woff2?|eot|ttf)$/i,
type: 'asset/resource',
},
]
}
};
resolve
resolve alias 需要vue-cli支持和自己加的别名都加上。
- vue$指定vue产物版本,否则使用import和require引入的vue就是不同的产物文件,element-ui就是require('vue')
- css中的静态资源引用支持'~/src/assets',但是Rspack是不识别的,如果项目中有这种写法,需要加上别名
- extendsions 加上常见的文件扩展名
css
resolve:{
alias:{
vue$:'vue/dist/vue.runtime.js',
'@':path.resolve(__dirname,'./src'),
'~/src/assets':path.resolve(__dirname,'./src/assets')
},
extendsions:[
'.tsx',
'.ts',
'.jsx',
'.js',
'.vue',
'.json'
]
},
HtmlWebpackPlugin
创建html可以使用HtmlRspackPlugin,也支持HtmlWebpackPlugin,这里复制vue-cli的配置HtmlWebpackPlugin:
arduino
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [new HtmlWebpackPlugin({
filename:'index.html',
scriptLoading:'defer',
template:path.resolve(__dirname, 'plulic/index.html'),
templateParameters:{} // 传给html的变量
})],
};
DefinePlugin
DefinePlugin
允许在 编译时 将你代码中的变量替换为其他值或表达式。
ini
const rspack = require('@rspack/core');
module.exports = {
plugins: [
new rspack.DefinePlugin({
'process.env.NODE_ENV': "'development'",
}),
],
};
devServer
devServer 的配置和webpack一样
css
devServer: {
port:'8000',
proxy: {
'/api': 'http://localhost:3000',
},
},
完整配置
css
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/main.ts',
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// 注意,为了绝大多数功能的可用性,请确保该选项为 `true`
experimentalInlineMatchResource: true,
},
},
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
type: 'javascript/auto',
},
{
test: /\.sass$/,
use: [
{
loader: 'sass-loader',
options: {
// ...
},
},
],
type: 'css/auto', // 如果你需要将 '*.module.(sass|scss)' 视为 CSS Module 那么将 'type' 设置为 'css/auto' 否则设置为 'css'
},
{
test: /\.ts$/, // 如果需要在 Vue SFC 里使用 Typescript, 请添加该规则
loader: 'builtin:swc-loader',
options: {
sourceMap: true,
jsc: {
parser: {
syntax: 'typescript',
},
},
},
type: 'javascript/auto',
},
{
test: /\.[t]sx$/,
use: [
{
loader: 'babel-loader',
options: {
presets:[
[
'@babel/preset-typescript',
{ isTSX: true, allExtensions: true }
],
[ '@babel/preset-jsx', { compositionAPI: true } ]
]
},
},
],
},
{
test: /\.(svg|png|jpe?g|gif|webp|woff2?|eot|ttf)$/i,
type: 'asset/resource',
},
],
},
resolve:{
alias:{
vue$:'vue/dist/vue.runtime.js',
'@':path.resolve(__dirname,'./src')
},
extendsions:[
'.tsx',
'.ts',
'.jsx',
'.js',
'.vue',
'.json'
],
fallback:{
fs:false
}
},
experiments: {
css: false,
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename:'index.html',
scriptLoading:'defer',
template:path.resolve(__dirname, 'plulic/index.html'),
templateParameters:{} // 传给html的变量
}),
new rspack.DefinePlugin({
'process.env.NODE_ENV': "'development'",
}),
],
devServer: {
port:'8000',
proxy: {
'/api': 'http://localhost:3000',
},
},
};