如何更好的管理前端环境变量

原文地址:https://lon.im/post/use-environment-variables-better-in-front_end.html

本文主要分析使用环境变量管理前端项目时会遇到的问题,并介绍常用工具给出解决方案。

如何使用环境变量

在搭建基于 webpack 前端项目时(或任意基于 Node 的项目,本文以 webpack 项目为例),一般需要提供两种运行模式:开发模式和生产模式。通常的做法是,执行命令前设置环境变量 NODE_ENVproduction,如执行 NODE_ENV=production webpack 命令,然后在 JavaScript 代码中通过 process.env.NODE_ENV === 'production' 来判断是生产模式,否则为开发模式。通过区分不同的模式可以执行不同的操作,比如在开发模式下启动开发服务器并代理转发 API,或在生产模式下压缩合并代码等。为了更好的统一前端工程命令,可以将启动开发模式和生产模式的命令分别加入 package.json 文件的 scripts 字段中,以后只需要执行 npm startnpm run build 即可。通过定义环境变量的方式很好的解决了在项目中执行差异操作的需求。如果希望支持成员自定义环境变量,只要在程序中优先使用环境变量中的值即可。比如已经设置端口号优先使用环境变量中的 PORT 的值,项目成员开发时执行 PORT=8080 npm start 命令就可以自定义端口号为 8080 了。

使用环境变量时遇到的问题

上述的解决方案可以适用大部分场景,但却无法解决设置环境变量的跨平台和持久化问题

跨平台

如果项目中有使用 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 就可以跨平台工作了。

持久化

随着规模的增大,项目自定义环境变量的数量可能越来越多。比如部署后静态资源需要使用 CDN,项目生产模式就需要提供一个环境变量用于支持自定义 webpack 的 publicPath 字段;又比如有的成员并没有把 API 服务器运行在本机,而是运行在虚拟机里或另一台电脑上,项目开发模式就需要提供两个环境变量用于支持自定义 API 服务器地址和端口号……可能有的成员每次开发时必须执行类似这么长的命令:PORT=8080 API_SERVER=192.168.100.100 API_PORT=9000 npm start,因此需要一个可以持久化环境变量的工具,比如使用 dotenvenv-cmd 。以 env-cmd 为例,只需创建一个 .env.local 文件(不计入版本管理),写入:

NODE_ENV=development
PORT=8080
API_SERVER=192.168.100.100
API_PORT=9000

改写 package.json 中 start 命令(build 命令类似)为 env-cmd --fallback ./.env.local webpack 即可解决自定义环境变量过多每次手动输入繁琐的问题。

真正好用的环境变量管理工具

管理环境变量有很多工具,下面简单分析一下常用工具 dotenvcross-envenv-cmd 的优势与不足:

  • dotenv 可以解决跨平台和持久化的问题,但使用场景有限,只适用 node 项目,且和项目代码强耦合,需要在 node 代码运行后手动执行触发
  • cross-env 支持在命令行自定义环境变量。问题也非常明显,不能解决大型项目中自定义环境变量的持久化问题
  • env-cmd 也可以解决跨平台和持久化的问题,支持定义默认环境变量,不足的是不支持在命令行中自定义环境变量

事实上 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 提供的环境变量(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 致力于解决用户管理环境变量时遇到的各种问题,未来会加入更多人性化设计。如果你有任何想法,欢迎给项目提出宝贵的建议

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 一、什么是 npm 脚本? npm 允许在package.json文件里面,使用scripts字段定义脚本命令。 ...
    猪猪9527阅读 386评论 0 0
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,364评论 6 343
  • 关键词:npm 定义:npm 允许在package.json文件里面,使用scripts字段定义脚本命令。 上面代...
    ferrint阅读 13,580评论 2 6
  • git clone https://github.com/ruowenXin/start-project.git ...
    小辛_d98b阅读 188评论 0 0