We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在 Node.js 中通常会使用 process.env 来获取环境变量。
process.env
它返回一个包含用户环境的对象。这里的用户环境是 Shell 进程,这个对象包含了当前进程的变量。注意,process.env 对象可以被修改,但其修改不会影响到此进程之外。
分类:
作用域:
local
export
Shell 环境是天然隔离的,在当前进程内设置或修改变量,都不会影响到其他非关联进程的环境变量。
function fn() { foo=1 # 作用域为当前进程 local bar=2 # 作用域为当前函数 export baz=3 # 作用域为当前进程及子进程 } fn echo $foo # 1 echo $bar # 空字符串 echo $baz # 3
在 Shell 中,如果引用的变量不存在,它不会报错,而是输出空字符。
假设有以下包:
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "node -e 'console.log(process.env)'" } }
执行 npm run start 时,会得到这些变量:
npm run start
{ // Shell 内置变量 SHELL: '/bin/zsh', USER: 'frankie', HOME: '/Users/frankie', // ... // zsh 自定义环境变量 NVM_DIR: '/Users/frankie/.nvm', // ... // npm config 相关变量 npm_config_sass_binary_site: 'https://npmmirror.com/mirrors/node-sass', npm_config_prefix: '/Users/frankie/.nvm/versions/node/v18.16.0', // ... // npm package 相关变量 npm_package_json: '/Users/frankie/Web/Git/html-demo/src/demo/node-env/package.json', npm_package_name: 'node-env', npm_package_version: '1.0.0', // ... }
process.env 的值都是字符串。如果赋值时不是字符串,会被隐式转换为字符串。
可以看到两类与 npm 相关的环境变量,在执行 npm run 命令时自动载入。
npm run
npm_config_
npm_package_
其中 npm_config_ 开头的环境变量源自 .npmrc 配置文件,优先级从上到下:
.npmrc
$HOME/.npmrc
$PREFIX/etc/npmrc
$PREFIX
npm config get prefix
/path/to/npm/npmrc
其中 key 大小写不敏感,它们都会被转换为小写形式,- 也会被转为 _。
-
_
其中 npm_package_ 则源自 package.json。比如使用 process.env.npm_package_version 获取包版本号。
package.json
process.env.npm_package_version
以上是 npm run 内部执行逻辑带入的环境变量,也可以自定义。
比如:
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "NODE_ENV=development node -e 'console.log(process.env.NODE_ENV)'" } }
这样就能在 Node 脚本里获取到这个 NODE_ENV 变量值了。
NODE_ENV
在命令前加上变量声明,它会传递给子进程。类似 export 的效果,但不完全相同,这种方式不会影响当前进程的同名变量。Simple Command Expansion
但它仅支持 Unix-like 操作系统,到 Windows 就不行了。后者需要使用 set 命令:
set
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "set NODE_ENV=development node -e 'console.log(process.env.NODE_ENV)'" } }
注意,Windows 操作系统的环境变量不区分大小写。
后来,出现了一些跨平台方案,比如 cross-env。用法变成了这样:
$ npm i cross-env -D
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "cross-env NODE_ENV=development node -e 'console.log(process.env.NODE_ENV)'" } }
cross-env is "finished" (now in maintenance mode)
如果项目的环境变量很多,script 就会很长很长,不好看也不好维护,后来又使用 dotenv 方案。
比如,项目根目录有 .env、.env.development 文件:
.env
.env.development
由于 .env 文件可能会包含像密钥这类敏感信息,它不在版本控制范围内,应该添加到 .gitignore 里。如果是多人协作的项目,可以考虑添加类似 .env.example 模板到仓库里,以便其他成员清楚了解用到哪些环境变量。
.gitignore
.env.example
# .env API_URL=https://example.com/api/
# .env.development API_URL=https://dev.example.com/api/
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "cross-env NODE_ENV=development node -e 'console.log(process.env.API_URL)'", "build": "cross-env NODE_ENV=production node -e 'console.log(process.env.API_URL)'" } }
这样本地开发和打包的时候,就能根据 NODE_ENV 的值从对应的 .env 文件中读取配置。
当然,以上环境变量仅可在编译时有效。要在业务代码中使用,还得借助类似 webpack.DefinePlugin、webpack.EnvironmentPlugin 等插件处理,它们将会在编译时被替换为相应的字符串。
webpack.DefinePlugin
webpack.EnvironmentPlugin
$ npm i dotenv
const webpack = require('webpack') require('dotenv').config() module.exports = { plugins: [ new webpack.DefinePlugin({ 'process.env.API_URL': JSON.stringify(process.env.API_URL), }), ], }
如果已有同名环境变量,dotenv 解析时将会忽略它。比如开发环境中先后加载 .env.development、.env,其中解析前者时已设置 API_URL 变量,当解析到后者时就会忽略 API_URL。
API_URL
以上仅为示例,如果你是使用 webpack 的话,可以用 dotenv-webpack。
Node.js 20.6.0 原生支持 .env 文件,处于实验性阶段,当前还有很多功能上的缺失,不能完全替代 dotenv。更多请看 Node.js 20.6.0 includes built-in support for .env files
注意,很多构建工具只有「特定前缀开头」以及像 NODE_ENV 这种很通用的环境变量才能在运行时(即业务代码)可用。
VITE_
VUE_APP_
REACT_APP_
TARO_APP_
任何不能对外公开的信息,都不要嵌入构建当中,因为它们都可以在构建产物中查到。
除此之外,还有其他一些方式可以提供。
可以通过 webpack-cli 的 --env 参数传递。比如:
--env
$ npm i webpack webpack-cli -D
{ "name": "node-env", "version": "1.0.0", "scripts": { "start": "webpack -w --env test", "build": "webpack --env prod", "build:pre": "webpack --env pre", } }
执行 npm run build:pre 时,可以这样获取到值:
npm run build:pre
// webpack.config.js module.exports = function (env, argv) { console.log(env.pre) // true // 可以结合 webpack.DefinePlugin 使用 // ... }
若使用 --env,webpack 配置需导出为函数。
更多请看 Environment Options。
还想多说一下。
以 webpack 为例,其模式有 development、production 和 none 三种。当「显式」声明 mode 为前两者时,它会自动设置 process.env.NODE_ENV 为对应值(更多)。从这个角度看,process.env.NODE_ENV 通常用来区分开发模式、打包模式。比如,开发模式下启用 sourcemap、HMR 等以便于开发调试。打包模式下启用 minimizer、splitChunks 等以减少产物体积。
development
production
none
mode
process.env.NODE_ENV
但好像有些同学会将 process.env.NODE_ENV 用于区分「项目」的测试、生成环境,其实“不对”的。假设项目有测试环境、预生产环境和生产环境呢,那它就不够用了。而且,即使是部署到非正式环境,在打包时也应该使用 production 模式。
可以像上面那样不同项目环境传入不同的 --env 参数,然后结合 webpack.DefinePlugin 来定义特定变量,比如:
const webpack = require('webpack') module.exports = function (env, argv) { return { // ... plugins: [ new webpack.DefinePlugin({ 'process.env.TEST': env.test, 'process.env.PRE': env.pre, 'process.env.PROD': env.prod, }), ], } }
// 业务 export const IS_TEST = process.env.TEST export const IS_PRE = process.env.PRE export const IS_PROD = process.env.PROD export const API_URL = IS_TEST ? 'http://test.example.com/api/' : IS_PRE ? 'http://pre.example.com/api/' : 'http://example.com/api/'
说那么多,是为了不要混淆 --env、--mode 与 process.env.NODE_ENV 的关系。process.env.NODE_ENV 在各大构建工具频繁出现,算是一个约定俗成的变量了,它与项目环境是不同的概念。
--mode
未完待续...
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
在 Node.js 中通常会使用
process.env
来获取环境变量。它返回一个包含用户环境的对象。这里的用户环境是 Shell 进程,这个对象包含了当前进程的变量。注意,
process.env
对象可以被修改,但其修改不会影响到此进程之外。Shell 变量
分类:
作用域:
local
显式声明的变量,其作用域仅在函数内。export
显式声明的变量,其作用域是当前进程及子进程。NPM 环境变量
假设有以下包:
执行
npm run start
时,会得到这些变量:可以看到两类与 npm 相关的环境变量,在执行
npm run
命令时自动载入。npm_config_
npm_package_
其中
npm_config_
开头的环境变量源自.npmrc
配置文件,优先级从上到下:.npmrc
$HOME/.npmrc
$PREFIX/etc/npmrc
(其中$PREFIX
为npm config get prefix
的路径)/path/to/npm/npmrc
其中
npm_package_
则源自package.json
。比如使用process.env.npm_package_version
获取包版本号。NPM Script 自定义环境变量
以上是
npm run
内部执行逻辑带入的环境变量,也可以自定义。比如:
这样就能在 Node 脚本里获取到这个
NODE_ENV
变量值了。但它仅支持 Unix-like 操作系统,到 Windows 就不行了。后者需要使用
set
命令:后来,出现了一些跨平台方案,比如 cross-env。用法变成了这样:
如果项目的环境变量很多,script 就会很长很长,不好看也不好维护,后来又使用 dotenv 方案。
比如,项目根目录有
.env
、.env.development
文件:这样本地开发和打包的时候,就能根据
NODE_ENV
的值从对应的.env
文件中读取配置。当然,以上环境变量仅可在编译时有效。要在业务代码中使用,还得借助类似
webpack.DefinePlugin
、webpack.EnvironmentPlugin
等插件处理,它们将会在编译时被替换为相应的字符串。注意,很多构建工具只有「特定前缀开头」以及像
NODE_ENV
这种很通用的环境变量才能在运行时(即业务代码)可用。VITE_
VUE_APP_
REACT_APP_
TARO_APP_
其他
除此之外,还有其他一些方式可以提供。
webpack
可以通过 webpack-cli 的
--env
参数传递。比如:执行
npm run build:pre
时,可以这样获取到值:还想多说一下。
以 webpack 为例,其模式有
development
、production
和none
三种。当「显式」声明mode
为前两者时,它会自动设置process.env.NODE_ENV
为对应值(更多)。从这个角度看,process.env.NODE_ENV
通常用来区分开发模式、打包模式。比如,开发模式下启用 sourcemap、HMR 等以便于开发调试。打包模式下启用 minimizer、splitChunks 等以减少产物体积。但好像有些同学会将
process.env.NODE_ENV
用于区分「项目」的测试、生成环境,其实“不对”的。假设项目有测试环境、预生产环境和生产环境呢,那它就不够用了。而且,即使是部署到非正式环境,在打包时也应该使用production
模式。可以像上面那样不同项目环境传入不同的
--env
参数,然后结合webpack.DefinePlugin
来定义特定变量,比如:未完待续...
The text was updated successfully, but these errors were encountered: