本文作者为 360 奇舞团前端开发工程师 天明
前言
在现代的JavaScrip
t应用程序开发中,环境变量的配置是至关重要的。不同的应用场景和部署环境可能需要不同的配置,例如开发、测试和生产环境。最常见的需求是根据不同的环境,配置如是否开启sourceMap
、API
请求地址的切换、是否压缩代码等逻辑。本文主要介绍利用不同的工具:Webpack
、Vite
、Rollup
打包项目的环境变量的配置方式。
process.env.NODE_ENV
process.env.NODE_ENV
应该是我们最熟悉的环境变量了,我们知道在Node
环境中process
是一个全局变量,无需require
引入。process.env
属性返回一个包含用户环境信息的对象,当我们打印process.env
时,发现它并没有NODE_ENV
这一个属性。实际上process.env.NODE_ENV
是在package.json
的scripts
命令中注入的,可以通过以下方式进行设置:
go
{
"scripts": {
"dev": "NODE_ENV=development webpack --config webpack.dev.config.js",
"prod": "NODE_ENV=production webpack --config webpack.prod.config.js"
}
}
当运行npm run dev
或npm run prod
命令时,设置了NODE_ENV
的不同值,项目中访问到的process.env.NODE_ENV
值也会根据执行脚本的不同而分别取值:development
与production
. 我们可以根据这个值的不同而分别进行不同的配置,这就是配置环境变量的基本逻辑.
Webpack
项目环境变量配置方式
使用DefinePlugin
插件
前面提到,在scripts
命令中注入的NODE_ENV
只能被Webpack
的构建脚本访问,而被Webpack
打包的源码中是无法访问到的,此时可以借助Webpack
的DefinePlugin
插件,创建全局变量。
go
const webpack = require('webpack');
module.exports = {
//.....其他配置
plugins: [
new webpack.DefinePlugin({
'process.env.API_URL': JSON.stringify('https://api.example.com'),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
],
};
在上面的示例中,我们定义了两个环境变量:API_URL
和NODE_ENV
,并且使用JSON.stringify
将值转换为字符串。这样就可以在代码中使用process.env.API_URL
与process.env.NODE_ENV
来访问这两个环境变量的值了。
Windows
平台配置的注意点
在Windows
平台下直接设置NODE_ENV =XXX
是会报错的, 解决办法也很简单,可以使用cross-env
这个npm
包来进行配置,cross-env
能够提供一个设置环境变量的scripts
,这样我们就能够以unix
方式设置环境变量,然后在windows
上也能够兼容
- 安装
go
npm install cross-env --save
- 使用
go
"scripts": {
"dev": "cross-env NODE_ENV=development webpack",
"prod": "cross-env NODE_ENV=production webpack"
}
可以看到直接在NODE_ENV=XXX
前面添加cross-env
就可以了。
使用dotenv
插件
假如我们项目的环境变量有很多,全部设置plugins
中既不美观也不容易维护,此时将环境变量配置在.env
文件中,然后使用dotenv
插件来加载.env
配置文件。
- 安装
go
npm install dotenv-webpack --save-dev
- 创建环境变量文件 在项目根目录下创建一个
.env
文件,如果有多种不同的环境,可以针对不同的环境创建不同的配置文件,例如可以使用.env.development
、.env.test
,.env.production
在文件来分别表示:开发、测试、生产环境的环境变量。在文件中配置每个环境对应的变量:
go
// .env.development
API_URL=http://development.example.com
DEBUG=true
go
// .env.test
API_URL=http://test.example.com
DEBUG=true
go
// .env.production
API_URL=http://production.example.com
DEBUG=false
- 加载
.env
配置 在webpack.config.js
加载.env
配置:
go
require('dotenv').config({ path: path.resolve(__dirname, '.env.' + process.env.NODE_ENV) })
- 设置
scripts``scripts
命令中设置NODE_ENV
go
"scripts": {
"dev": "cross-env NODE_ENV=development webpack",
"dev": "cross-env NODE_ENV=test webpack",
"prod": "cross-env NODE_ENV=production webpack"
}
Rollup项目环境变量配置方式
Rollup
是一个现代化的JavaScript
模块打包工具,专注于构建JavaScript
库和组件。下面是Rollup
中配置环境变量的几种常见方式:
使用rollup-plugin-replace
Rollup
的rollup-plugin-replace
插件允许我们在打包过程中替换代码中的字符串。我们常用该插件来定义环境变量。
- 安装:
go
npm install rollup-plugin-replace --save-dev
rollup.config.js
中配置
go
const isProduction = process.env.NODE_ENV === 'production';
export default [
{
//.....其他配置
plugins: [
replace({
'process.env.API_URL': JSON.stringify(isProduction ? 'https://prod.example.cn' : 'https://dev.example.cn')
'process.env.NODE_ENV': JSON.stringify(isProduction? 'production' : 'development')
})
]
}
]
在上面的例子中,我们首先获取到当前组件库的环境变量,并根据它的值设置不同的API_URL
与NODE_ENV
.
之所以在组件库中使用
rollup-plugin-replace
替换process.env.NODE_ENV
的原因是为了在打包时,将代码中的环境变量替换为实际的值,以便在不同的环境中正确地运行组件库。这样就避免了宿主工程中的环境变量process.env.NODE_ENV
,对组件库环境变量的影响。
Rollup使用dotenv
插件
与Webpack
类似,在Rollup
中使用dotenv
插件进行环境变量的配置,可以按照以下步骤进行:
- 安装
dotenv
与rollup-plugin-replace
go
npm install dotenv rollup-plugin-replace --save-dev
-
创建环境变量文件 与上面的
Webpack
创建环境变量文件类似,这里也可以创建多个环境配置文件.env.development
、.env.test
,.env.production
-
在
rollup.config.js
加载.env
配置
go
import { config } from 'dotenv'
config({ path: ".env."+ process.env.NODE_ENV }).parsed
export default {
// ...
plugins: [
replace({
process.env.API_URL: JSON.stringify(process.env.API_URL),
process.env.DEBUG: JSON.stringify(process.env.DEBUG),
}),
// ...
],
};
在上例中,我们首先通过dotenv.config()
方法来加载.env
文件中的环境变量。然后,使用@rollup/plugin-replace
插件的replace
方法,将环境变量注入到代码中。
- 在
package.json
中设置scripts
go
"scripts": {
"build:dev": "cross-env NODE_ENV=development rollup -c",
"build:prod": "cross-env NODE_ENV=production rollup -c",
"build:test": "cross-env NODE_ENV=test rollup -c",
"dev": "cross-env NODE_ENV=development rollup -c -w",
}
执行对应的脚本命令后,在你的代码中,你可以通过process.env.XXX
来访问已配置的环境变量.
Vite项目环境变量配置方式
与使用Webpack
或是Rollup
项目配置环境变量相比,Vite
项目配置环境变量较为简单。
内建变量
Vite
在一个特殊的import.meta.env
对象上暴露环境变量
-
import.meta.env.MODE:
应用运行的模式。 -
import.meta.env.BASE_URL:
部署应用时的基本 URL。他由base 配置项决定。 -
import.meta.env.PROD:
应用是否运行在生产环境。 -
import.meta.env.DEV:
应用是否运行在开发环境 (永远与import.meta.env.PROD
相反)。 -
import.meta.env.SSR:
应用是否运行在 server 上。 这些变量可以直接在代码中访问
.env
文件
同样在项目的根目录下,根据环境的不同创建不同的配置文件,不过文件的命名有些特殊性:
go
.env # 所有情况下都会加载
.env.local # 所有情况下都会加载,但会被 git 忽略
.env.[mode] # 只在指定模式下加载
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略
加载的环境变量也会通过 import.meta.env
以字符串形式暴露给客户端源码。
注意:为了防止意外地将一些环境变量泄漏到客户端,只有以
VITE_
为前缀的变量才会暴露给经过vite
处理的代码。
模式
默认情况下,开发服务器 dev命令
运行在 development
模式,而build
命令则运行在production
模式。这意味着当执行vite build
时,它会自动加载.env.production
中可能存在的环境变量.在某些情况下,若想在vite build
时运行不同的模式,你可以通过传递 --mode
选项标志来覆盖命令使用的默认模式。
go
vite build --mode development
此时vite
会使用.env.development
文件下环境变量进行构建。
总结
通过对比发现虽然打包工具不同,但是配置环境变量的方式都大同小异,合理的使用环境变量,能够提高我们代码的灵活性、安全性、可维护性,并且将配置信息与代码分离是一种良好的开发实践,可以使应用程序更易于维护和管理。
参考:
https://cn.vitejs.dev/guide/env-and-mode.html
https://webpack.docschina.org/plugins/define-plugin/
- END -
关于奇舞团
奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。