Vue-cli 项目迁移至 Rspack 实践

原项目基于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',
    },
  },
};
相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax