原文地址:https://lon.im/post/use-envir...javascript
本文主要分析使用环境变量管理前端项目时会遇到的问题,并介绍经常使用工具给出解决方案。html
在搭建基于 webpack 前端项目时(或任意基于 Node 的项目,本文以 webpack 项目为例),通常须要提供两种运行模式:开发模式和生产模式。一般的作法是,执行命令前设置环境变量 NODE_ENV
为 production
,如执行 NODE_ENV=production webpack
命令,而后在 JavaScript 代码中经过 process.env.NODE_ENV === 'production'
来判断是生产模式,不然为开发模式。经过区分不一样的模式能够执行不一样的操做,好比在开发模式下启动开发服务器并代理转发 API,或在生产模式下压缩合并代码等。为了更好的统一前端工程命令,能够将启动开发模式和生产模式的命令分别加入 package.json 文件的 scripts 字段中,之后只须要执行 npm start
或 npm run build
便可。经过定义环境变量的方式很好的解决了在项目中执行差别操做的需求。若是但愿支持成员自定义环境变量,只要在程序中优先使用环境变量中的值便可。好比已经设置端口号优先使用环境变量中的 PORT
的值,项目成员开发时执行 PORT=8080 npm start
命令就能够自定义端口号为 8080 了。前端
上述的解决方案能够适用大部分场景,但却没法解决设置环境变量的跨平台和持久化问题java
跨平台node
若是项目中有使用 Windows 操做系统的成员,在执行 npm run build
(即 NODE_ENV=production webpack
)时会失败,缘由是 Windows 命令不支持使用这种方式设置环境变量。虽然在 Windows 下也能够根据 build 脚本内容,手动执行 set NODE_ENV=production webpack
,却破坏了统一前端工程命令的初衷,为此须要引入一个解决跨平台设置环境变量的库。如使用 cross-env,只要改写 package.json 中的 build 脚本为 cross-env NODE_ENV=production webpack
就能够跨平台工做了。webpack
持久化git
随着规模的增大,项目自定义环境变量的数量可能愈来愈多。好比部署后静态资源须要使用 CDN,项目生产模式就须要提供一个环境变量用于支持自定义 webpack 的 publicPath 字段;又好比有的成员并无把 API 服务器运行在本机,而是运行在虚拟机里或另外一台电脑上,项目开发模式就须要提供两个环境变量用于支持自定义 API 服务器地址和端口号……可能有的成员每次开发时必须执行相似这么长的命令:PORT=8080 API_SERVER=192.168.100.100 API_PORT=9000 npm start
,所以须要一个能够持久化环境变量的工具,好比使用 dotenv 或 env-cmd 。以 env-cmd 为例,只需建立一个 .env.local 文件(不计入版本管理),写入:github
NODE_ENV=development PORT=8080 API_SERVER=192.168.100.100 API_PORT=9000
改写 package.json 中 start 命令(build 命令相似)为 env-cmd --fallback ./.env.local webpack
便可解决自定义环境变量过多每次手动输入繁琐的问题。web
管理环境变量有不少工具,下面简单分析一下经常使用工具 dotenv、cross-env 和 env-cmd 的优点与不足:npm
事实上 NPM 自己也提供了相似设置项目环境变量的功能。以上述自定义端口号的需求为例,也能够在项目目录下执行 npm config set project-name:PORT 8080
(project-name 为项目名称),执行 npm start
后在代码中能够经过 process.env.npm_package_config_PORT
获取到 8080。并且还能够将 package.json 中 config 字段设置为 {"PORT": 8000}
,用于指定 npm_package_config_PORT
的默认值。使用 NPM 的 config 功能管理环境变量的最大优点是原生支持,放在 package.json config 字段中的默认环境变量也很是方便查看。遗憾是的,变量名前面都会有冗长的 npm_package_config_
;脚本必须从 package.json 的 scripts 字段中执行(即执行 npm run your_script_name);还有就是全部项目共用一份配置文件(.npmrc,默认在用户目录下),不方便手动编辑和查看。
所以一个好用的前端环境变量管理工具应该具有如下功能:
npm_package_*
和 npm_config_*
)为此又诞生了一个环境变量管理工具:fuck-env,取义“恶搞环境变量”,支持以上全部功能。
fuck-env 安装和使用
npm install fuck-env
若有一个包含 package.json 和 main.js 两个文件的项目,文件代码以下:
package.json
{ "name": "fuck-env-demo", "config": { "PORT": 8000, "APP_NAME": "$npm_package_name" }, "scripts": { "start": "fuck-env node main.js" }, "dependencies": { "fuck-env": "*" } }
main.js
console.log(process.env.PORT) // 8080 console.log(process.env.APP_NAME) // fuck-env-demo
执行 fuck-env PORT=8080 npm start
后,输出“8080”和“fuck-env-demo”,不管是在 Windows 仍是 POSIX(macOS、Linux 等)系统中。
若是成员但愿本地持久化自定义的端口号,能够新建一个 .env 文件(此文件须加入 .gitignore,不计入版本管理,格式为类 .ini 文件的简单键值对)。
.env
PORT=8080
之后只需执行 npm start
便可。此外 fuck-env 还提供了另外一个命令行工具:fuck,用于快速设置本地环境变量。好比,若是成员又但愿使用 9000 端口,能够在项目根目录下执行 fuck set PORT 9000
(需全局安装 fuck-env),此时项目目录下 .env 文件的内容即会变为“PORT=9000”,使用 fuck 命令在环境变量较多时很是方便。
当环境变量过多时,所有放置 package.json 的 config 字段也会显得臃肿。fuck-env 支持统一管理默认环境变量,只需将 config 字段下全部环境变量移至 default.env 文件(计入版本库)中便可。
更多实例请参考这里
fuck-env 致力于解决用户管理环境变量时遇到的各类问题,将来会加入更多人性化设计。若是你有任何想法,欢迎给项目提出宝贵的建议。