本文是对当前项目部署的一个整理复盘,也可以作为一个前端项目部署的案例,还望大家批评指正
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模块还没有加载,
字面量的循环依赖一般只是警告,如果涉及到异步加载的组件,就会报错
原因:
- 循环依赖:
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:
检测手段:加入插件
本地启动时会检测:
完