当前位置:首页 » 《我的小黑屋》 » 正文

node 中的环境变量

1 人参与  2024年09月27日 08:42  分类 : 《我的小黑屋》  评论

点击全文阅读


node 中的环境变量

process.env 可以返回一个对象,里边包含了系统运行环境信息,在开发环境或者部署环境中都需要使用到。比如:

{  TERM: 'xterm-256color',  SHELL: '/usr/local/bin/bash',  USER: 'maciej',  PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',  PWD: '/Users/leo',  EDITOR: 'vim',  SHLVL: '1',  HOME: '/Users/leo',  LOGNAME: 'leo',  _: '/usr/local/bin/node'} 

我们可以通过修改这个对象吗,但是这个修改只会在当前的 node 的进程中展示出来,并不会影响到外部的全局变量或者其他 Worker 线程。

不会打印 foo 的值:

node -e 'process.env.foo = "bar"' && echo $foo

当在一个进程中设置就可以访问:

process.env.bar = 'foo';console.log(process.env.bar)  // foo

添加的环境变量值会被隐式转换成 string 格式,这种方式在最新版本已经被废弃,对于非 string、number、boolean 值 node 会直接报错,而不是隐式转换成 string。

process.env.nullish = null;console.log(process.env.nullish);     // 'null'process.env.undefined = undefined;console.log(process.env.undefined);   // 'undefined'process.env.obj = {};console.log(process.env.obj);   // [object Object]

因为 process.env 是一个对象,因此可以使用 delete 关键词删除属性:

process.env.nullish = null;delete process.env.nullish;console.log(process.env.nullish)  // undefined

在 windows 操作系统中,环境变量是大小写不敏感的:

process.env.VALUE = 'value';console.log(process.env.value)   // 'value'

如果我们写过react、vue的项目,会对下面的配置文件非常熟悉:

// .env.development 文件ENV = 'development'VUE_APP_BASE_API = '/dev-api'

这些配置就是添加到 process.env 中的。

在 node 项目中,会经常使用 process.env 对象添加环境变量,本文主要以 vite 为例,看看一个成熟的 node 项目是如何使用 process.env 的。

vite 如何处理项目中的 .env 文件

核心就是 vite/src/node/env.ts 文件中。

从 getEnvFilesForMode 方法中可以看到,vite 默认是可以处理 .env、.env.local、.env. m o d e 、 . e n v . {mode}、.env. mode、.env.{mode}.local这样的配置文件。

function getEnvFilesForMode(mode: string): string[] {  return [    /** default file */ `.env`,    /** local file */ `.env.local`,    /** mode file */ `.env.${mode}`,    /** mode local file */ `.env.${mode}.local`,  ]}

mode 的值可以在 vite.config.js 中配置

{  mode: 'development'}

mode 的值可以是 development(默认)、product,当然也可以设置成其他的,比如 build、dev,但是不能是 local,因为与 .env.local 后缀相同。

也可以在启动 vite 项目的时候通过命令行中携带 --mode xxx 指定 mode 值,这种方式优先级最高,可以覆盖 vite.config.js 中的 mode 字段。

之后 vite 会尝试在项目中加载相关的配置文件(loadEnv 方法)。可以通过在 vite.config.js 中的 envDir 字段配置文件目录(默认是在根目录中)。

vite 不单会加载一个文件,它会尝试加载 getEnvFilesForMode 方法返回的4个文件(后边的会覆盖前面的,也就是说 .env.${mode}.local 优先级最高)。

const envFiles = getEnvFilesForMode(mode)// 加载并合并const parsed = Object.fromEntries(  envFiles.flatMap((file) => {    const filePath = path.join(envDir, file);    if (!tryStatSync(filePath)?.isFile()) return [];    return Object.entries(parse(fs.readFileSync(filePath)));  }));

根据这个特性,我们可以在 .env / .env.local 这两个文件中配置开发模式和生产模式下共享的环境变量,在 .env.${mode} 文件配置某个模式下特有的环境变量。

vite 加载 .env 文件是通过 dotenv 这个库实现的,为了解决配置的变量名与系统上的配置重名,还使用 dotenv-expand。

为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。例如下面这些环境变量:

VITE_SOME_KEY=123DB_PASSWORD=foobar
function resolveEnvPrefix({  // 配置前缀,默认 VITE_  envPrefix = 'VITE_',}: UserConfig): string[] {  envPrefix = arraify(envPrefix)  if (envPrefix.includes('')) {    throw new Error(      `envPrefix option contains value '', which could lead unexpected exposure of sensitive information.`,    )  }  return envPrefix}for (const key in process.env) {  // 只有以配置的环境变量前缀的变量才会暴露  if (prefixes.some((prefix) => key.startsWith(prefix))) {    env[key] = process.env[key] as string  }}

在 vite.config.js 文件中的 envPrefix 字段中配置环境变量前缀。

从上面的代码可以看到环境变量的值是一个 string,即使我们设置的是其他类型,但是都是 string,我们在使用的时候要特别注意。

envPrefix 不应被设置为空字符串 ‘’,这将暴露所有的环境变量,导致敏感信息的意外泄漏。 检测到配置为 ‘’ 时 Vite 将会抛出错误.
如果我们想暴露一个不含前缀的变量,可以在 define 中配置:

{  define: {    'import.meta.env.ENV_VARIABLE': JSON.stringify(process.env.ENV_VARIABLE)  }  }

如果想要在环境变量中使用 $ 符号,则必须使用 \ 对其进行转义。

KEY=123NEW_KEY1=test$foo   # testNEW_KEY2=test\$foo  # test$fooNEW_KEY3=test$KEY   # test123

环境变量使用

加载的环境变量也会通过 import.meta.env 以字符串形式暴露给客户端源码。

console.log(import.meta.env.VITE_SOME_KEY) // "123"console.log(import.meta.env.DB_PASSWORD) // undefined

原理:

在 importAnalysisPlugin 中的判断代码中是否存在 import.meta.env 字符串,存在的话在代码最开头注入 import.meta.env = {xxx: xxx},这样在运行这段代码的时候就不会报错,并能够成功获取变量值。


点击全文阅读


本文链接:http://zhangshiyu.com/post/165172.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1