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',
    },
  },
};
相关推荐
提子拌饭1335 分钟前
个人月事记录表应用 - 鸿蒙PC Electron框架完整实现指南
前端·javascript·华为·electron·前端框架·开源·鸿蒙系统
超人气王12 分钟前
新手学前端JS浅拷贝和深拷贝:对象复制竟然是个“替身文学”?
javascript·面试
YHL13 分钟前
📚 JS执行机制(执行上下文 + 调用栈 + 编译流程)
前端·javascript
不简说18 分钟前
这次真香!sv-print 可视化打印设计器更新:插件脚手架、Excel 导出、弹窗 API 三连发
前端·javascript·前端框架
无聊的老谢23 分钟前
Web GIS 最佳实践:Vue 集成 Leaflet/OpenLayers 实现基站海量点位渲染
前端·javascript·vue.js
yingyima26 分钟前
GCP Cloud Scheduler 核心语法与实战示例速查手册
前端
用户573501072520627 分钟前
Elpis 项目阶段性总结 - 基于 vue3 完成领域模型架构建设
前端
东风破_32 分钟前
V8 如何执行你的代码——编译、上下文与调用栈
javascript
假如让我当三天老蒯34 分钟前
为什么 setData 能获取到 prev 参数?(自学用)
前端·react.js
AskHarries1 小时前
Workspace:文件系统、项目上下文和执行边界
java·服务器·前端