项目纪实杂症之process is not defined

背景介绍

项目使用的Vite构建React前端项目,符号现代化web开发规范,部署到云端通过新建流水线后实现自动部署。通常情况是本地修改之后之后上传release分支,运行流水线,部署完成(uat)。终于有一天,按照常规操作之后,再次访问项目,意外出现白屏无法问题。开始排查…

排查流程

从最直观的错误出发

  1. 登录成功之后进入首页,页面空白,打开开发控制台,控制台明显报错,见下图
    err01.png
    err02.png

  2. 从错误信息可以直观判断出,源码中使用了process,但是没定义,process是node环境下的定义的,如果说在浏览器端直接使用的话,是会出这样的问题,于是找到本地代码,查找process的使用地方,排除了node_modules第三库之外,只有一处使用了process.cwd(),和错误处相距甚远,显然不是这个这里导致的。

  3. 项目代码没问题,那究竟是哪里出来问题?同样的代码,之前构建跑的流水线能够使用,今天却突然不行了,极大的可能是流水线哪里出了问题,于是…

排查前后流水线的差别

经过前后对比前后2条流水线的对比之后发现,出问题的这条流水线的部分包的依赖版本更高,像esbuild rollup等,刚好这些是vite的依赖,竟然是vite来进行打包,那么合理的猜想便是这些包的版本高了导致的问题,查看vite包依赖如下:

1
2
3
4
5
6
"dependencies": {
"esbuild": "^0.17.5",
"postcss": "^8.4.21",
"resolve": "^1.22.1",
"rollup": "^3.18.0"
}

这里需要了解的第一个知识点,包版本范围的控制的控制

  • ^符号表示可以安装指定包的最新版本,但是版本号的第一位不能变。例如,”^1.2.3”表示可以安装1.2.x系列中最新的版本,但不能安装1.3.0及以上版本
  • ~符号表示可以安装指定包的最新版本,但是版本号的前两位不能变。例如,”~1.2.3”表示可以安装1.2.x系列中最新的版本,但不能安装1.3.x及以上版本
  • >:表示可以安装指定包的最新版本,但是必须大于指定的版本号。
  • >=:表示可以安装指定包的最新版本,但是必须大于等于指定的版本号。
  • <:表示可以安装指定包的最新版本,但是必须小于指定的版本号。
  • <=:表示可以安装指定包的最新版本,但是必须小于等于指定的版本号。
  • =:表示只能安装指定的版本号。
  • -:表示可以安装指定范围内的任意版本。例如,”1.2.3 - 1.2.5”表示可以安装1.2.3、1.2.4和1.2.5这三个版本

由上再结合npm官网esbuild包的更新,发现正好esbuild前两天更新了,那么此时拉到最新版本0.17.18符合预期,考虑到可能是包更新导致的问题,想办法只安装esbuild版本为0.17.17,好的流水线真是0.17.17版本,作了以下尝试:

在项目的devDependencies中的vite下面添加

1
2
"vite": "^4.2.1"
"esbuild": "0.17.17"

发现这种情况并不能阻止安装最新的esbuild为0.17.18, a few minutes later, 来到了第二个知识点,当想要固定项目中依赖的依赖时,package.json中添加字段如下:

1
2
3
"resolutions": {
"esbuild": "0.17.17",
},

修改完成,构建部署,打开页面,同样的错误,就说不会这么简单~ 继续对比,发现rollup的版本也和esbuild是一样的情况,那么也尝试固定一下rollup的版本呢,如下:

1
2
3
4
"resolutions": {
"esbuild": "0.17.17",
"rollup": "3.20.6"
},

结论出来了,看了仅仅改变包依赖的问题还是不能解决,只能另想它法了。这个process到底是哪里使用,于是又有了新的思路!

寻找process使用源头

由于线上是生产打包文件,打包的文件,不是很好确定!考虑本地来复现问题,首先移除node_modules,拉取最新的包依赖和线上保持一致,完事之后,运行yarn dev,打开访问地址,登录,进入首页,空白!!Ops, 复现,打开控制台,便很容易得到以下截图
err03.png

终于,罪魁祸首引用的地方找到了,原来是@ant-design/pro-components包中引用报错,看看npm官网,这个包最近也是有所更新,那么到底是这个包升级导致的问题与否,问了官方的人员没给我答复。我暂且不追究了,搜索得知,vite在本地开启服务的时候是可以通过define字段来定义,于是在vite.config.ts中添加字段定义

1
2
3
4
define: {
'process.env': {},
},

再次yarn dev,可以! 搞定了,折腾得已经够久了,然后愉快打个包,线上仍然是同样的问题 …

经过一番思索,上面那个配置应该是在vite开发环境下编译注入,打包之后便失去了效果,那么如果有能对于打包的配置,在输出的时候注入不就可以了~ 果然还是有这样的答案,文章是针对rollup配置,刚好vite也是rollup来进行打包,这下刚刚好,参考文章之后添加如下配置

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 省略了不必要的代码
export default defineConfig(mode) => {
const Global = `var process = {
env: {}
}`

return {
build: {
rollupOptions: {
banner: Global, // 如此之后在打包输出文件添加了process变量
}
}
}
}

在经过以上的配置,打包,访问,首页出现,完美收工!

总结

出现这个问题自是包依赖版本拉取到最新的问题,但具体是哪个环节出了问题,没有定论。

需要掌握的几个知识点:

  • package.json包依赖的版本范围控制
  • 项目依赖项中子依赖的版本控制
  • 构建工具vite有了更高的体会,使用import.meta.env而非process.env来控制环境变量等