前端 Webpack 项目构建时环境变量

date
Apr 14, 2023
slug
frontend-env
status
Published
summary
tags
前端
type
Post
前端应用程序中可能需要使用环境变量(如API URL)。由于这些变量可能在不同的环境中(甚至不同项目)发生变化,因此我们就需要配置应用程序以在每个环境中调用正确的变量。
举几个场景:
  • 开发环境调取开发环境的 URL,测试环境调取测试环境的 URL
  • 不同的项目需要走不同的逻辑,例如:A客户需要A逻辑,B客户需要B逻辑;A公司要A样式风格,B公司要B样式风格(此场景比较频繁发生在公有云产品私有部署)。
在没有环境变量之前,我们只能通过不同分支写不同代码来处理,而有了这个环境变量之后,我们就可以通过同一套代码来处理不同的逻辑了。

环境变量

我们在项目根目录中放置下列文件来指定环境变量:
这个模式一般分为2种:
  • development 模式用于开发环境
  • production 模式用于生产环境
 

只在本地有效的变量

有的时候我们可能有一些不应该提交到代码仓库中的变量,尤其是当我们的项目托管在公共仓库时。这种情况下你应该使用一个 .env.local 文件取而代之。本地环境文件默认会被忽略,且出现在 .gitignore 中。
.local 也可以加在指定模式的环境文件上,比如 .env.development.local 将会在 development 模式下被载入,且被 git 忽略。
 
使用 `dotenv` 库来注入文件:
可以注意到,其中有个 PLATFORM_ENV 环境,这里可以通过不同的value来覆盖默认的环境变量。举例我在当前执行命令中配置了 PLATFORM_ENV=companyA ,那么,会首先注入 .env.companyA 文件里配置的环境变量,也就是实现说公司A需要A逻辑,公司B需要B逻辑的需求。

特定环境的构建

取不同的 dotenv 文件构建,是根据当前CI服务器所在的环境变量而定的。
比如在 Jenkins环境中注入环境变量来构建不同的产物,或者docker中注入环境变量来构建不同的产物等等。
而本地环境的话,我们也可以通过执行命令的时候来注入变量。

cross-env 解决设置所有系统的环境变量

假设有这么一个 package.json
在执行 NODE_ENV=production webpack 命令时,Webpack 实际上会使用后面设置的值 production,而不是继承当前 Node.js 环境中的 NODE_ENV 值。
当我们在命令行中设置环境变量时,它会覆盖当前环境中的同名变量。在这个例子中,命令 NODE_ENV=production webpack 设置了环境变量 NODE_ENV 的值为 production,会覆盖当前 Node.js 环境中的同名变量的值(即如果之前 NODE_ENV 环境变量的值为 Test,那么它将被覆盖为 production)。
因此,Webpack 将使用后面设置的值 production 作为当前的环境模式,并使用相应的生产环境配置进行打包。
在 Mac 以及 Linux 中,执行这个命令并不会报错,然后在大部分 Windows 环境下,会直接出错执行不了。因此需要使用cross-env这个库来解决这个问题。
如下:

在客户端侧代码中使用环境变量

以上所有环境变量其实只是注入到process.env中了,只是node环境可访问,也就是说我们只能在node执行的脚本中才能使用,比如Webpack的构建等,但是客户端侧代码中是无法使用的。
我们可以通过Webpack的EnvironmentPlugin 这个插件来注入,考虑到非所有变量都需注册,我们手动指定 REACT_APP_ 前缀开头的变量才会被嵌入。
接着我们就可以在应用的代码中这样访问它们:
console.log(process.env.REACT_APP_SECRET)
在构建过程中,process.env.REACT_APP_SECRET 将会被相应的值所取代。在 REACT_APP_SECRET=secret 的情况下,它会被替换为 "secret"
 
这里有个很关键的点,是在构建过程中被替换的,如果没有构建过程,则无法访问,会出现process.env 报错。比如使用 Vite 在开发时,不构建编译JS文件,而是直接访问的话就会报错。
 
最后附上完整代码:
 

运行时的环境变量

以上的环境均指构建时而非运行时,也就是说只有被node处理完的文件才可以使用这些环境变量(哪怕是客户端侧使用)。如果想在浏览器端运行时也能使用,那就需要统一挂载到window,或者使其成为一个全局变量。
然后在html中引入这个文件。

参考资料

 

© Stanley Wind 2023 - 2024