Appearance
在多环境的情况下我们期望的是通过配置文件进行配置,然后在代码中通过环境变量来获取配置的值。
在实际的node 开发中都会将这一类的配置属性挂载在 process.env
返回的对象上,来做到一些全局的配置属性
process.env
是Nodejs提供的一个全局对象API,用于访问当前进程的环境变量,它返回一个当前 Node.js 运行环境的环境变量包含用户环境信息的对象。环境变量是一组键值对,用于存储有关应用程序运行环境的配置信息。这些配置信息可以包括操作系统、用户、应用程序等级的变量。
这里面其中还包含一些默认变量例如
环境变量 | 描述 |
---|---|
NODE_ENV | 指定当前 Node.js 应用程序的运行环境,如 "development" 或 "production"。 |
PATH | 指定可执行文件的搜索路径,用于运行命令行工具。 |
HOME (Unix) 或 USERPROFILE (Windows) | 当前用户的主目录路径。 |
PWD (Unix) | 当前工作目录的路径。 |
LANG 或 LC_ALL (Unix) | 指定当前系统的语言和地区设置。 |
HOSTNAME | 当前计算机的主机名。 |
USER (Unix) 或 USERNAME (Windows) | 当前登录用户的用户名。 |
OS 或 OSTYPE | 指定操作系统类型。 |
SHELL (Unix) | 当前用户的默认 Shell。 |
TZ | 指定当前时区的环境变量。 |
也可以通过变量赋值的形式去指定特殊的自定义的key 要注意的是这种自定义打印出来的 value 都是字符串形式
js
console.log(process.env.foo) // null
console.log(typeof process.env.foo) // string
环境变量可以在操作系统或应用程序启动时设置,并在整个应用程序的执行过程中使用。如果我们想在项目启动时候就注入这些变量,而不是运行时候赋值,在不同系统上如果设置 环境变量需要针对不同系统去写不一样的脚本文件,
- 命令行方式:在启动应用程序的命令前设置环境变量,例如:
Windows: SET NODE_ENV=development && node your-app.js
类 Unix:NODE_ENV=development node your-app.js
- 使用脚本:编写一个脚本文件,在脚本中设置环境变量并启动应用程序,例如:
Windows: 创建一个批处理文件(.bat):
bash
SET NODE_ENV=development
node your-app.js
类 Unix:创建一个 Shell 脚本文件(.sh):
bash
#!/bin/bash
export NODE_ENV=development
node your-app.js
获取 NODE_ENV
js
console.log(process.env.NODE_ENV) // development
当我们需要全局使用的一些系统变量打入程序中可以在不同操作系统上一致地设置环境变量,并将其传递给 Node.js 应用程序中的 process.env
变量时候一般会选用一些第三方的库 dotenv
和 cross-env
cross-env
,在不同系统中的兼容性问题。使用 cross-env
设置 node
内存变量
bash
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 pnpm vite build",
有时候想传入更多的配置信息
json
"scripts": {
"start-with-env": "cross-env PORT=3000 ENV=local node server.js"
},
现在,无论在 windows 上还是 mac/linux 上运行 npm run start-with-env 程序都能正常运行了
当环境变量越来越多时,难以维护此时可以使用
dotenv 是一个非常流行的 JavaScript 库,用于管理环境变量。它允许你将环境变量从 .env
文件中加载到 process.env
对象中。这样做的好处是,你可以在不更改代码的情况下,轻松地在不同的环境(如开发、测试和生产环境)中使用不同的设置。
二者在使用上可以理解 dotenv 主要用于环境变量的管理和存储,而 cross-env 主要用于解决跨操作系统设置环境变量的问题,但本质解决问题上都是一样的
Vite 中环境变量
在 Vite 中,dotenv
库用于读取和解析 .env
文件,然后将这些环境变量合并到 Vite 的环境变量系统中。
加载
.env
文件:当你运行vite
或vite build
命令时,Vite 会自动查找项目根目录下的.env
文件(以及任何环境特定的.env
文件,如.env.development
或.env.production
)。解析和合并:Vite 使用
dotenv
库来解析这些.env
文件,并将解析后的环境变量合并到import.meta.env
对象中。前缀过滤:与直接使用
dotenv
不同,Vite 通常只会将以VITE_
开头的环境变量暴露给前端代码。访问环境变量:在你的代码中,你可以通过
import.meta.env
对象来访问这些环境变量。
示例
假设你有一个 .env
文件,内容如下:
VITE_API_URL=https://api.example.com
DB_PASSWORD=secret
在这种情况下,只有 VITE_API_URL
会被暴露给前端代码,可以通过 import.meta.env.VITE_API_URL
来访问。
VITE 中环境变量使用
Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量,一般会在根目录下创建一些用来保存环境变量的文件
.env
所有情况下都会加载,文件可以理解成全局配置文件不管什么环境都会优先读取这个文件下的配置.env.local
所有情况下都会加载,但会被 git 忽略.env.[mode]
只在指定模式下加载.env.[mode].local
只在指定模式下加载,但会被 git 忽略
这些文件要注意的是
.env.*.local
文件应是本地的,可以包含敏感变量。你应该将*.local
添加到你的.gitignore
中,以避免它们被 git 检入。由于任何暴露给 Vite 源码的变量最终都将出现在客户端包中,VITE_*
变量应该不包含任何敏感信息。
为了方便默认的开发环境和生产环境 vite 也将做好了默认指定分别是 .env.development
和 .env.production
.env.development
只在开发模式下加载 .env.production
只在生产模式下加载
bash
npm run dev # 会加载 .env 和 .env.development 内的配置
npm run build # 会加载 .env 和 .env.production 内的配置
通过指令运行来指定配置文件,在 vite 中 --mode
选项可以用来指定环境变量的配置文件,可以通过命令行 --mode
选项来指定。例如
bash
npm run vite --mode test # 读取是.env.test 文件
npm run vite build --mode test # 读取是.env.test 文件
vite 环境变量在浏览器和配置文件使用
webpack帮我们做了处理,使浏览器可以直接识别node的process.env
变量,从而实现了浏览器识别环境变量的功能。
vite中,我们的代码运行在浏览器环境中,因此是无法识别process.env
变量的。(这意味着,vite中识别环境变量的方式与webpack中不同),Vite 使用了一种特殊的方式来处理环境变量,它并不是直接使用 Node.js 的 process.env。相反,它使用了 import.meta.env
这个特殊的对象来让你在前端代码中访问环境变量
在帮我们转换后 我们需要通过使用 import.meta.env
是 ECMAScript
模块的一个特殊属性,用于在在持 ECMAScript 模块的现代浏览器中才可用访问环境变量。它提供了一种在前端代码中获取环境变量的方式。
import.meta.env 是一个包含当前模块环境变量的对象。它类似于 Node.js 中的 process.env,但适用于浏览器环境。
但是像vite.config.js运行在node环境中,因此,可以识别process.env
变量,如果是在浏览器运行的文件例如打包后 vue 文件是需要使用 import.meta.env
vite 结合了 dotenv
也配置了一些默认值如下
import.meta.env.MODE
: {string} 应用运行的模式。import.meta.env.BASE_URL
: {string} 部署应用时的基本 URL。他由base配置项决定。import.meta.env.PROD
: {boolean} 应用是否运行在生产环境。import.meta.env.DEV
: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。import.meta.env.SSR
: {boolean} 应用是否运行在 server 上。
js
console.log(' import.meta.env.MODE: ', import.meta.env.MODE);
console.log(' import.meta.env.BASE_URL: ', import.meta.env.BASE_URL);
console.log(' import.meta.env.PROD: ', import.meta.env.PROD);
console.log(' import.meta.env.DEV: ', import.meta.env.DEV);
console.log(' import.meta.env.SSR: ', import.meta.env.SSR);
在一些其他情况下像让某些配置文件打包内容模仿生产环境,例如 .env.t
想让其运行 import.meta.env.PROD
为 true 可以在配置文件声明
bash
# .env.t
NODE_ENV=production
就可以模仿是生产配置环境进行运行改打包过程
其他
- 自定义 前缀 vite.config.ts
js
//vite.config.ts
export default defineConfig({
plugins: [vue()],
envPrefix:"APP_",//APP_ 为自定义开头名
})
使用是ts
如果你使用的是ts,为了有良好的ts提示,我们在src目录下新增types目录,然后新增global.d.ts类型定义文件,vite/client
包含了默认的 env 配置字段
ts
/**
* 可以看到默认包含的
* interface ImportMetaEnv {
[key: string]: any
BASE_URL: string
MODE: string
DEV: boolean
PROD: boolean
SSR: boolean
}
*
*/
/// <reference types="vite/client" />
// 自定义属于自己的 回和默认的合并
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
使用 dotenv
可以通过 npm 或 yarn 来安装这个库:
bash
npm install dotenv
# 或
yarn add dotenv
基本用法
- 在项目的根目录下创建一个
.env
文件,并添加一些键值对:
DATABASE_URL=example-database-url
API_KEY=example-api-key
- 在你的 JavaScript 文件中,尽早地导入并配置
dotenv
:
javascript
require('dotenv').config();
或者,如果你使用 ES6 模块:
javascript
import dotenv from 'dotenv';
dotenv.config();
- 现在,你可以通过
process.env
对象来访问这些环境变量:
javascript
console.log(process.env.DATABASE_URL); // 输出 "example-database-url"
console.log(process.env.API_KEY); // 输出 "example-api-key"
高级用法
- 自定义路径:如果你的
.env
文件位于自定义路径,你可以如下配置:
javascript
require('dotenv').config({ path: '/custom/path/to/.env' });
环境特定文件:你可以为不同的环境(如开发、测试、生产)创建不同的
.env
文件(例如.env.development
,.env.production
)。然后,你可以通过 `process.env.NODE_ENV` 来访问当前的环境变量:
javascript
console.log(process.env.NODE_ENV); // 输出 "development"
你可以通过 `dotenv` 的 `config` 方法来指定当前环境的 `.env` 文件:
javascript
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });
或者,如果你使用 ES6 模块:
javascript
import dotenv from 'dotenv';
dotenv.config({ path: `.env.${process.env.NODE_ENV}` });
现在,你可以在不同的环境中使用不同的环境变量了。