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',
    },
  },
};
相关推荐
问道飞鱼10 分钟前
【前端知识】强大的js动画组件anime.js
开发语言·前端·javascript·anime.js
k093311 分钟前
vue中proxy代理配置(测试一)
前端·javascript·vue.js
傻小胖13 分钟前
React 脚手架使用指南
前端·react.js·前端框架
程序员海军25 分钟前
2024 Nuxt3 年度生态总结
前端·nuxt.js
m0_7482567835 分钟前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
web135085886351 小时前
前端node.js
前端·node.js·vim
m0_512744641 小时前
极客大挑战2024-web-wp(详细)
android·前端
若川1 小时前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
潜意识起点1 小时前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛2 小时前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode