process.env环境变量动态替换方案踩坑记录

前言

今天早上阅读几年前写的一段代码时,突然对其是否生效产生了怀疑,这段代码如下:

process.env环境变量动态替换方案踩坑记录_第1张图片

令我困惑的是:这里动态获取 process.env 上的属性是否生效?

先说结论:

这个项目使用的是 [email protected],采用基于 webpackreact-app-rewired 脚手架工具构建,这种动态取值写法是生效的

我的困惑

在我印象中,在项目中使用 process.env 上的环境变量不能使用这种动态取值写法,必须使用下面这种写法

// 我印象中的正确写法
const baseURL = process.env.REACT_APP_XXX_BASICPATH 

并且,不能对 process.env 进行解构

// 我印象中的错误写法
const { REACT_APP_XXX_BASICPATH } = process.env 

必须用 process.env.REACT_APP_XXX_BASICPATH 这种写法的原因:

webpack 在打包构建项目时,会分析源代码中的 process.env.XXX 所有的这种写法,并且用 webpack 编译时的 process.env 相应的值去替换源代码。

例如:

const baseURL = process.env.REACT_APP_XXX_BASICPATH 

webpack 编译替换后的结果:

// 这是示例,实际上代码还会被 webpack 压缩
const baseURL = 'https://xxx.com/xxx/' 

代码验证

1.react 项目

使用 process.env.XXX 写法

process.env环境变量动态替换方案踩坑记录_第2张图片

经过 webpack 编译打包后的代码如下,其中 process.env.REACT_APP_APPID 被替换成了一个确定的字符串

process.env环境变量动态替换方案踩坑记录_第3张图片

直接打印 process.env

process.env环境变量动态替换方案踩坑记录_第4张图片

编译打包后代码中的 process.env 被替换成了一个对象

process.env环境变量动态替换方案踩坑记录_第5张图片

如果使用动态属性取值呢

process.env环境变量动态替换方案踩坑记录_第6张图片

编译打包后代码中的 process.env 被替换成了一个对象,同时动态取值的写法也被转换了

process.env环境变量动态替换方案踩坑记录_第7张图片

经过上面这几种情况的验证,已初步证明 process.env 环境变量支持常规写法、动态取值写法、解构写法

为了排除这个 react 项目特殊性的原因,下面使用了一个 vue2 的项目经验验证,还是使用 webpack。

2.vue 项目

直接打印 process.env

process.env环境变量动态替换方案踩坑记录_第8张图片

编译打包后代码中的 process.env 同样被替换成了一个对象

process.env环境变量动态替换方案踩坑记录_第9张图片

使用 process.env.XXX 写法

process.env环境变量动态替换方案踩坑记录_第10张图片

其中 process.env.VUE_APP_VERSION_SHOW 被替换成了一个确定的字符串

使用动态属性取值

process.env环境变量动态替换方案踩坑记录_第11张图片

process.env 同样被替换成了一个对象,同时动态取值的写法也被转换了

process.env环境变量动态替换方案踩坑记录_第12张图片

3.结论

这里我验证用的 react、vue 项目对于 process.env 的环境取值的编译时替换技术的处理逻辑是一致的与 react 还是 vue 框架无关。

猜测可能与项目采用的构建打包工具 webpack、rollup、parcel 还是 vite 有关。

DefinePlugin

尝试验证

在 webpack 构建工具中处理环境变量编译时替换是用的 webpack.DefinePlugin 插件,使用代码验证跟踪如下

使用的是 [email protected]

webpack.config.js 配置文件

process.env环境变量动态替换方案踩坑记录_第13张图片

源码

process.env环境变量动态替换方案踩坑记录_第14张图片

打包编译结果及执行结果

process.env环境变量动态替换方案踩坑记录_第15张图片

与上面 vue 项目中验证结果对比发现纯粹使用 webpack.DefinePlugin 有如下限制:

1.源码中 process.env 不能被插件正确替换
2.源码 process.env[XXX] 动态取值写法不能被插件替换
3.源码对 process.env 的解构写法不能被插件替换

综上,上面 webpack.DefinePlugin 验证的结果说明文章开头我对 webpack 项目中环境变量的动态替换规的困惑和记忆中的写法是对的,那 “这里动态获取 process.env 上的属性是否生效?” 是怎么一回事呢?。

新写法验证

于是继续翻阅 webpack.DefindPlugin 官方文档,直到发现这段话

process.env环境变量动态替换方案踩坑记录_第16张图片

可能是插件的用法和 react、vue 脚手架中的用法不一致,于是修改 webpack.config.js 继续验证

process.env环境变量动态替换方案踩坑记录_第17张图片

打包编译结果及执行结果

process.env环境变量动态替换方案踩坑记录_第18张图片

可见,这个验证结果与文章开头 react、vue 项目中遇到的编译后结果完全一致。

环境变量替换过程

这里我还进一步分析了 react、vue 项目中环境变量在编译时替换的具体过程,如下:

这里 react、vue 项目的构建都是以 webpack 为例,vite 等其他构建工具不同

1.构建命令:create-react-app 或 @vue/cli 构建命令执行2.解析配置:根据命令参数解析本地 .env.test / .env.prod 文件3.读取配置:dotenv 读取本地 .env 配置文件4.挂载:将解析结果挂到 proces.env 对象上5.传入插件:process.env 对象被传入 webpack.DefindPlugin 插件6.替换:webpack.DefindPlugin 插件替换源码中的环境变量相关代码总结

关于前端项目的环境变量替换问题,这其实属于是一个项目工程化的问题,在以 webpack 为基础的构建工具项目中基本都是采用 webpack.DefinePlugin 和 dotenv 这一完整成熟的方案。

经过一系列的代码测试验证和重新翻阅文档,总算是对开头我的困惑进行了一个解答。

另外,也让我对这个环境变量动态替换方案的细节有了更深的认识。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

你可能感兴趣的:(webpack,javascript,前端)