企业 webpack 迁移部署 rspack 踩坑

avatar
前端 @阿巴阿巴

本文是对当前项目部署的一个整理复盘,也可以作为一个前端项目部署的案例,还望大家批评指正

0. 前置知识:

rspack:

速度速度,还是速度,谁也不想一个cicd跑10分钟

与 webpack 类似,迁移成本低

发布平台:

公司内部的发布平台,作用是收集各个仓库cicd打包后的镜像资源,通过审核机制统一调配。可以理解为一个功能比较全的灰度系统。

cicd跑完后,资源会暂存在泰拉里,devops发布模板里,先去下载指定包(发布时会选择subId,subID 就是cicd打的时间戳的目录)。

发布模板是一个仓库一个模板,指明了发布的脚本和部署名称、主机host等

泰拉:

变更模板;

变更发布:

这里能拉取到这个仓库历次打包的镜像资源,后边的时间字符串就是 subID

然后执行部署脚本 :

模板里的脚本,作用是从存储目录压缩后copy到host的发布目录中

然后登录虚拟机查看。(登录步骤见:预发环境 nginx 操作指南

devops部署后,虚机路径 /data/uspeedo_console:

部署的资源文件路径:

与发布号对应即可找到资源:

通过 ID 号可以追溯发布

部署资源目录:

1. 代码修改

删去 webpack 相关依赖:

添加 rsbuild.config.js 配置文件,删去 config-override.js

三个环境变量:

.env.development 开发环境 预发配置

.env.pre 生产环境 预发配置

.env.production 生产环境 线上配置

本地开发:.env.development BUILD_MODE=development

预发: .env.pre BUILD_MODE=production

线上: .env.production BUILD_MODE=production

只有线上才需要埋点、sentry等:

index.html 植入了很多的埋点 sdk,需要特殊处理

只有本地开发才需要源码调试:

线上走 CDN

2. 打包路径动态写入 buildPath

由于我们部署项目,要过一道devops的选择版本的过程,这就需要保留历次打包的版本,中间需要多一级目录。

这在 .gitlab-ci.yml 文件中写明了:

所以,在 rspack 的配置文件中要设置多一级资源路径,保证上面的脚本中有 /$VERSION 目录:

// BUILD_PATH 是打包时的目录名,BUILD_MODE 可以区分开发环境和生产环境
const buildPath = process.env.BUILD_PATH || 'dist';
const isDev = process.env.BUILD_MODE === 'development';
...
// BUILD_MODE 有 cicd 写入
mode: isDev ? 'development' : 'production', 
html: {
    template: isPre ? './public/index.pre.html' : './public/index.html',
  },
output: {
    // 静态资源的路径前缀,只在生产环境使用
    assetPrefix: `/${buildPath}/`,
    distPath: {
      // root 是打包后的根目录,不再是 dist,而是cicd写入的时间戳
      root: buildPath,
    },
  },

查看打包后的文件:

若不配置这个,就会导致访问打包的静态资源就会是这样的路径: 10.72.xxx.xxx:8014/static/js/l… ,实际目录会比这个多一级,而打包的静态资源路径少一级,就找不到资源了。

全局访问会报错报错:Uncaught SyntaxError: Unexpected token '<' (at lib-react.js:1:1)

注意:mode 在 development 时,assetPrefix 失效,部署预发时他也是生产环境,而不是开发环境

3. 本地 dev 运行报错:Uncaught ReferenceError: process is not defined

environment.js 中要读取 process.env,结果就报错。

需新增配置,把 process 的 env 暴露出来

source: {
    define: {
      'process.env': JSON.stringify(process.env),
    },
  },

4. 引用 import {} from 'utils/const' 提示找不到路径

问题在于配置了 jsconfig.json,编辑器可以解析 "baseUrl": "src",但打包器不认识,需要配置:

source: {
    tsconfigPath: './jsconfig.json',
  },

5. 部署后模块报错:Uncaught ReferenceError: Cannot access 'c' before initialization

直观分析,举例说明: const.js 中引用了 FormatMessage,而 FormatMessage模块还没有加载,

字面量的循环依赖一般只是警告,如果涉及到异步加载的组件,就会报错

原因:

  1. 循环依赖:

const.js -> formatMessage -> const.js下的LanguageOptions --> formatMessage

utils/utils.js --> const.js的 timeFormat等 --> utils.js的contactDateAttributeFormat

MainRoutes.js --> layout/MainLayout --> Header/index.js --> NavBar/index.js --> hooks/useAcl --> routes/MainRoutes.js

之前线上偶发的白屏卡死问题,就是循环依赖造成的

构建配置中的 const 设置:在 Rspack 的构建配置中,output.environment.const 默认为 true,这会严格遵循 ES6 的行为,确保 const 声明的变量在初始化之前不可被访问。如果存在循环依赖,这种设置可能会导致运行时错误。

Webpack 的校验可以兼容 cjs,所以循环依赖问题之前是偶发,现在是必出现的。

处理方案:

迁移引用 useAcl.js:

检测手段:加入插件

本地启动时会检测: