node 中的环境变量

news2024/9/8 23:39: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=123
DB_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=123
NEW_KEY1=test$foo   # test
NEW_KEY2=test\$foo  # test$foo
NEW_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://www.coloradmin.cn/o/1957876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mecanim Animation System

动画系统简介 Unity 有一个非常丰富而又复杂的动画系统,官方称其为Mecanim。该系统具有以下功能: 支持从外部导入动画剪辑,如:fbx、mb | ma(Autodesk maya 原件)、.max(3ds Max原件&#xff09…

5.仓颉编程_数组使用与异常捕捉

5.仓颉编程_数组使用与异常捕捉 数字数组与字符串数组 import std.console.*main() {var qty 10var zero2 0var array [1,2,3] //数组var str_arr:Array<String> [aa,bb]try {//qty qty / zero2//println(qty)println(str_arr[0])println(array[0])// println(arr…

rhce THE homework of first

ssh远程免密登录成功 下载httpd和nginx 关闭防火墙 查看selinux的状态 为服务器配置ip 填充网站的内容 添加服务器配置 将文本写入网站

2024电赛H题参考方案(+视频演示)——自动行使小车

目录 一、题目要求 二、参考资源获取 三、参考方案 1、环境搭建及工程移植 2、移植MPU6050模块 3、移植TB6612电机驱动模块 4、整体控制方案视频演示 总结 一、题目要求 小编自认为&#xff1a;此次H题属于控制类题目&#xff0c;相较于往年较为简单&#xff0c;功能也算单一&a…

深入解析 GZIP 压缩传输:优化网络性能的利器

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…

MATLAB中“varargin”的作用

varargin是什么&#xff1f; 在MATLAB中&#xff0c;varargin是一个特殊的变量&#xff0c;用于接收函数输入参数中的可变数量的参数。它允许用户在调用函数时传递不确定数量的参数。 varargin的本质是一个包含了所有可变参数的cell数组。在函数内部&#xff0c;可以使用cell…

dpdk 响应icmp请求(Echo or Echo Reply Message)

注&#xff1a;对于"Echo or Echo Reply Message"类型的icmp报文&#xff0c;响应报文的Identiy和Sequence Number的值与请求报文的这两个字段的值要相同。 Identifier&#xff08;标识符&#xff09;字段通常由发送方设置&#xff0c;并被用于将ICMP请求与相应的回复…

Lombok注解之@SneakyThrows作用

Lombok注解之SneakyThrows作用 读法 [ˈsniːki] [θroʊz] 悄悄的 抛出顾名思义&#xff0c;它能够自动偷摸的为咱们的代码生成一个try…catch块&#xff0c;并把异常向上抛出来。 使用 SneakyThrows的使用范围&#xff1a; 只能作用在方法和构造函数之上。从源码就可以…

【C++】选择结构-多条件if语句

多条件if语句格式为 if(第一个条件) else if(若第一个条件未满足&#xff0c;执行此条件) {第二个条件满足执行此操作} else if(若第二个条件未满足&#xff0c;执行此条件) {第三个条件满足执行此操作} ...... else{若所有条件都不满足执行此操作} 下面是一个实例 #inc…

app逆向实战:某咨询6.0.4.4版本signature等参数抓包与破解

本篇博客旨在记录学习过程&#xff0c;不可用于商用等其它途径 入口 密码登录接口 抓包 根据抓包结果得知动态参数是client_timestamp&#xff0c;keyword&#xff0c;client_session&#xff0c;sig&#xff0c;sigTime&#xff0c;cursor 初步观察得出以下结论&#xff…

负债了,打死也别干的六件事!逾期了,六句谎言千万别信!

负债这事儿&#xff0c;真是一言难尽&#xff0c;稍不留神&#xff0c;就可能让情况雪上加霜。今儿咱们聊聊&#xff0c;负债后那几件打死也别干的几件事&#xff0c;尤其是针对还没有逾期的朋友们&#xff0c;免得后悔莫及。 首先&#xff0c;千万别动歪脑筋&#xff0c;拿公款…

深入剖析:GaussDB与MySQL在COUNT查询中的并行化技术

引言 数据库查询性能优化是数据库管理和开发中的一个重要议题。在处理大数据量的COUNT查询时&#xff0c;传统的单线程处理方式可能无法满足现代应用的性能需求。GaussDB(for MySQL)和MySQL作为流行的数据库系统&#xff0c;它们在并行查询优化方面有着各自的策略和技术。本文…

【C++】C++的类型的转换

目录 C语言中的类型转换 C中的类型转换 C强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast C语言中的类型转换 C语言中又两种类型转换&#xff1a;&#xff08;强制&#xff09;显示类型转换和隐式类型转换。 &#xff08;强制&#xff09;显示类型…

多线程与并发思想

问题分析 设计并发程序的目的就是为了使程序运行得更快&#xff08;时间就是金钱、生命&#xff09;&#xff0c;提高软件的性能。并发程序之所以能快&#xff0c;就在于这个“并”字&#xff0c;因为程序能并发(单核)或并行(多核、多CPU)执行&#xff0c;当然能快。这就好比工…

修改linux服务器上的mariadb/mysql数据库的密码

文章目录 一、查看数据库的状态二、修改密码 可能我们在最初安装数据库时没有设置密码或者已经设置了但是又想修改另一个密码&#xff0c;可以这样操作来修改我们的密码。 以数据库 mariadb 为例。 一、查看数据库的状态 使用命令 systemctl is-active mariadb 查看当前数据库…

链表篇-02.从尾到头打印链表(反转链表)

解题思路&#xff1a; 链表从尾到头打印链表, 我的思路是 用三个指针,第一个指针(pre)指向指向头节点的前一个位置&#xff0c;第二个指针(cur)指向头节点&#xff0c; 然后依次往后执行&#xff0c;第三个指针用于临时记录第二个指针的下一个位置。 代码详情: import java.…

Linux云计算 |【第二阶段】AUTOMATION-DAY5

主要内容&#xff1a; YAML语法格式&#xff0c;层级关系、Ansible Playbook文件及语法格式、Ansible变量&#xff08;定义变量方法、优先级顺序、setup和debug查看变量&#xff09; 补充&#xff1a;Ansible ad-hoc 可以通过命令行形式远程管理其他主机&#xff0c;适合执行一…

python学习笔记——字符串

一、创建字符串 1.我们可以使用引号( 或 " )来创建字符串。创建字符串很简单&#xff0c;只要为变量分配一个值即可。 var1 Hello World! var2 "Runoob" 二、访问字符串中的值 1.Python 访问子字符串&#xff0c;可以使用方括号 [] 来截取字符串。…

RocketMQ的Admin Tool工具

文档&#xff1a;https://github.com/apache/rocketmq/blob/develop/docs/cn/operation.md写的很全面&#xff0c;我写了一半就偷懒了&#xff0c;地址放这里。 命令大全&#xff1a;https://github.com/apache/rocketmq/blob/develop/docs/cn/operation.md 1. 删除讨厌的告警…

VUE3——003、VUE 项目中的文件结构(index.html、main.ts、App.vue)

虽然是号称是小白初学&#xff0c;但本文只是对 VUE 小白&#xff0c;其它的基功还是有一丢丢的&#xff0c;不太懂的同学去看看一下详解&#xff0c;我这里记述的是自己的理解和观点。见谅&#xff01; index.html&#xff1a;入口文件&#xff08;以创建 vue3 项目的默认文件…