Rspack 在 vue-cli 4.x + vue2.6 的项目集成和上线,提高5x构建速度!

背景

前端项目工程的开发和编译时间很慢,通过调研vite,发现开发环境的使用还是挺快的,所以在项目中进行开发模式的实践,最后也落地了一下vite开发的模式。

当前,公司项目编译还是采用webapck编译部署,项目部署普遍在3min以上,有的可能甚至更长,影响编译部署测试环境的体验。

所以想利用vite在部署编译上能不能有落地,但经过一段时间的研究发现,并不能vite生产编译不是很好,一些公司内部的webpack都需要进行重写,成本很高,构建速度甚至还不如webpack。随着rspack的推出,官方据说项目接入之后会有5-10倍的构建提升编译时间越长,优化空间也是巨大的 。所以对rspack研究了相当多的时间(几个月),现在已经在c2c这个大项目中进行了部署上线,取得了不错的效果。从之前的3-4min到现在的39s左右,算上部署过程中的安装包和部署校验啥的,总共花费时间也在1min之内。

填坑经历

接入

node版本使用14.20以上

非webpack5项目

升级项目到webpack5,已经是webpack5可以下一步

js 复制代码
使用"vue-loader" 指定版本 15.11.1

使用 @vue/[email protected]

@vue/[email protected]

@vue/[email protected]

"@vue/babel-preset-app": "^5.0.8"

"@rspack/cli": "^0.3.10"

"webpack": "5.89.0"

webpack5项目

perl 复制代码
使用"vue-loader" 指定版本 15.11.1
"@rspack/cli": "^0.3.10"
"webpack": "5.89.0"

根目录添加 rspack.confg.js

javascript 复制代码
const path = require('node:path')
const rspack = require('@rspack/core')
const { VueLoaderPlugin } = require('vue-loader')

const isProduction = process.env.NODE_ENV === 'production'
const imgPublicPath = 'https://img1.demo.com/path/'
const assetsPublicPath = 'https://s1.demo.com/path/'
const publicPath = isProduction ? assetsPublicPath : '/path/'


function resolve(dir) {
  return path.join(process.cwd(), dir)
}
const rspackPlugins = [
  new VueLoaderPlugin(),
  new rspack.HtmlRspackPlugin({
    template: 'public/index.html',
    filename: isProduction ? 'webserver/index.html' : 'index.html'
  }),
  new rspack.CopyRspackPlugin({
    patterns: [
      {
        from: 'public',
        globOptions: {
          ignore: ['**/index.html']
        }
      }
    ]
  })
]

/**
 * @type {import('@rspack/cli').Configuration}
 */
const baseWebpackConfig = {
  cache: false,
  mode: isProduction ? 'production' : 'development',
  context: __dirname,
  entry: {
    main: './src/main.ts'
  },
  output: {
    clean: true,
    publicPath,
    cssFilename: 'static/css/[name].[contenthash:8].css',
    filename: 'static/js/[name].[contenthash:8].js',
    cssChunkFilename: 'static/css/[name].[contenthash:8].css',
    chunkFilename: 'static/js/[name].[contenthash:8].js'
  },
  target: ['web', 'es5'],
  builtins: {
    PresetEnv: {
      mode: 'entry',
      targets: ['2015']
    },
    pluginImport: [
      {
        libraryName: 'vant',
        style: '{{ kebabCase member }}/style/index.js'
      }
    ]
  },
  devServer: {
    https: true,
    hot: true,
    host: 'local-ip',
    port: 8088,
    allowedHosts: 'all',
    historyApiFallback: true
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        use: [
          {
            loader: 'vue-loader',
            options: {
              experimentalInlineMatchResource: true
            }
          }
        ]
      },
      {
        test: /.tsx$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-typescript', { allExtensions: true, isTSX: true }],
                [
                  // 注意 @vue/babel-preset-jsx适配vue2.x @vue/babel-plugin-jsx 适配vue3.x
                  '@vue/babel-preset-jsx',
                  {
                    injectH: false
                  }
                ]
              ]
            }
          }
        ]
      },
      {
        test: /.css$/,
        use: ['postcss-loader'],
        type: 'css'
      },
      {
        test: /.scss$/,
        use: [
          'postcss-loader',
          'sass-loader',
          {
            loader: 'style-resources-loader',
            options: {
              patterns: [
                resolve('src/assets/vars.scss'),
                resolve('src/assets/common.scss')
              ],
              injector: 'prepend'
            }
          }
        ],
        type: 'css'
      },
      {
        test: /.less$/,
        use: ['postcss-loader', 'less-loader'],
        type: 'css'
      },
      {
        resourceQuery: /lang=ts/, // 如果需要在 Vue SFC 里使用 Typescript, 请添加该规则
        type: 'ts'
      },
      {
        test: /.(png|jpe?g|gif|svg)/i,
        type: 'asset',
        generator: {
          publicPath: isProduction ? imgPublicPath : publicPath,
          filename: 'static/img/[name].[hash:8][ext]'
        }
      },
      {
        test: /.(png|jpe?g|gif|svg)/i,
        type: 'asset/inline',
        generator: {
          publicPath: isProduction ? imgPublicPath : publicPath,
          filename: 'static/img/[name].[hash:8][ext]'
        }
      },
      {
        test: /.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'static/font/[name].[hash:8][ext]'
        }
      }
    ]
  },
  experiments: {
    css: true
  },
  resolve: {
    extensions: ['.mjs', '.js', 'jsx', '.ts', '.tsx', '.vue'],
    alias: {
      '@': resolve('src'),
      '@src': resolve('src'),
      'vue-loader': resolve('node_modules/vue-loader')
    }
  },
  optimization: {
    realContentHash: true,
    splitChunks: {
      cacheGroups: {
        someVendor: {
          chunks: 'all',
          minChunks: 2
        }
      }
    }
  },
  plugins: rspackPlugins
  // stats: 'verbose'
}
module.exports = baseWebpackConfig

注意事项

  • 因为rspack对AMD规范没有全面支持。所以遇到打包后页面报

    require is not defined,需要找到相关依赖包,升级到最新的AMD规范的包。相关issue在

    github.com/web-infra-d...

    所以需要升级相关依赖包看能不能解决。

  • 如果项目中采用下图中的方式书写代码,里面包含render jsx,需要在script中添加lang="tsx",让tsx loader进行处理

  • 注意 @vue/babel-preset-jsx适配vue2.x @vue/babel-plugin-jsx 适配vue3.x

  • script配置 build采用rspack build进行编译,开发的话可以采用,dev:rspack或者dev:vuecli,由于rspack对dev支持不是特别好,可以开发采用cli的。当然开发也可以采用vite

js 复制代码
"build:rspack": "rspack build",
"build:vuecli": "vue-cli-service build --no-module",
"dev:rspack": "rspack serve",
"dev:vuecli": "vue-cli-service serve",
"dev": "npm run dev:vuecli",
"build": "npm run build:rspack"

回归测试

  1. 项目部署到测试环境后,对项目中的路由都进行一下回归,看看页面有问题没,console有没有异常。可以小组内分模块进行回归。
  2. 测试一下离线包和预渲染等
  3. 上线后观察sentry有没有异常

接入效果

接入前

接入之后

总结

虽然接入rspack不是一帆风顺的,但结果是好的,并且自己也收获了很多,学习了相关的webpack,vue-loader知识等。rspack对webpack相关的生态支持还是比较好的,比如公司内部的离线包和sentry插件都不用改,直接可以进行使用。接入成本是很低的,最后也可以考虑集成到内部脚手架,方便其他同学使用。

相关推荐
SunTecTec10 分钟前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
拉不动的猪1 小时前
前端常见数组分析
前端·javascript·面试
小吕学编程1 小时前
ES练习册
java·前端·elasticsearch
Asthenia04122 小时前
Netty编解码器详解与实战
前端
袁煦丞2 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛3 小时前
vue组件间通信
前端·javascript·vue.js
一笑code3 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员3 小时前
layui时间范围
前端·javascript·layui
NoneCoder3 小时前
HTML响应式网页设计与跨平台适配
前端·html
凯哥19703 小时前
在 Uni-app 做的后台中使用 Howler.js 实现强大的音频播放功能
前端