4

Node.js/Vue/Nuxt.js项目中的环境变量process.env用法详解

 2 years ago
source link: https://xmanyou.com/node-vue-nuxt-process-env-details/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. Node.js的环境变量对象 process.env

https://nodejs.org/dist/latest-v8.x/docs/api/process.html#process_process_env

process.env是一个包含了操作系统当前用户的环境变量的对象。

几个要点:

  • 环境变量只在启动时被加载
  • 进程隔离
    process.env的值可以被在Node.js进程中被修改,但是,并不会真正修改用户的环境变量,也就是说,脱离这个进程之后,这些修改将不生效。
    例如:
$ node -e 'process.env.foo = "bar"' && echo "foo=$foo"
foo=

node-nuxt-vue-process-env-details-01

这是因为,实际上,process.envs是环境变量的值拷贝,而不直接操作环境变量。

  • process.env中的值都是字符串
    对process.env中的属性进行赋值,将直接被转换为字符串类型,例如:
process.env.test = null;
console.log(process.env.test);
// => 'null'
process.env.test = undefined;
console.log(process.env.test);
// => 'undefined'
  • Windows系统中,process.env的属性是大小写无关的。
  • 使用delete可以移除process.env中的配置
process.env.TEST = 1;
console.log(process.env.TEST);
// => '1'
delete process.env.TEST;
console.log(process.env.TEST);
// => undefined

2. Vue项目的环境变量

https://cli.vuejs.org/zh/guide/mode-and-env.html#环境变量

Vue,准确的说是vue-cli-service在处理环境变量。

2.1. 运行模式

vue-cli-service 支持3种模式:

  • development 开发环境
  • test 单元测试环境
  • production 生产环境

NODE_ENV 可用于指定vue-cli-service运行的模式。

2.2. 环境变量文件

vue-cli-service使用dotenv来管理环境变量,定义在环境变量文件中的参数,会被注入到process.env中。

关于dotenv: https://github.com/motdotla/dotenv

自动环境变量文件
Vue项目根目录下,如果包含以下环境变量文件,将按照一定规则被自动加载:

.env                # 在所有的环境中被载入
.env.local          # 在所有的环境中被载入,但会被 git 忽略
.env.[mode]         # 只在指定的模式中被载入
.env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略

注意
未测试Nuxt.js项目是否遵从这个规则。

2.3. 运行时的环境变量

所有变量可以在vue-cli-service的命令、插件或者依赖中被使用。

但是,只有 NODE_ENV,BASE_URL 和以 VUE_APP_ 开头的变量,会被编译到客户端代码中。

特别注意
编译的方式是直接替换成实际的值。
也就是说,在编译后的客户端代码,是无法直接访问process.env的。
这也符合Node.js对process.env的规定:process.env是Node.js进程中的一个对象,而Vue的客户端并不是一个Node.js进程。
大胆猜测一下,进一步的,在一个编译后的Vue应用中,process.env也许甚至不能被访问(undefined),或者是一个空对象。(注意:实际结果未经测试)

特殊参数

  • NODE_ENV 用于定义当前的运行模式,始终是development, production, test中的一个。
  • BASE_URL 与vue.config.js中的publicPath一致,是应用会被部署到的基础路径。

3. Nuxt.js项目的环境变量

首先,Nuxt.js是一个Node.js项目,所以也遵守Node.js的环境变量规则,使用process.env来访问环境变量。
其次,Nuxt.js也是一个Vue项目,也遵守Vue的一些规则。至于到底遵守多少,得看Nuxt.js的具体实现。
最后,Nuxt.js又不是一个单纯的Vue项目或者Node.js项目,它既包含了服务端的代码,也包含了客户端的代码,所以也有自己的环境变量规则。

官方文档:

https://nuxtjs.org/docs/directory-structure/nuxt-config#env

从官方文档可以看到,nuxt.config.js 提供了多个配置环境变量的字段和方法,看起来很乱。

实际上,nuxt.js中有两种环境变量:

  • 编译阶段的环境变量
  • 运行阶段的环境变量

3.1. 编译阶段的环境变量

通过在nuxt.config.js文件中配置env字段,可以设置在编译阶段使用的环境变量,这些变量无法在运行时被访问(无论服务端还是客户端)。

示例

{
export default {
  env: {
    NODE_ENV="staging",
    VERSION="1.2.3"
  }
}
}

3.2. 运行阶段的环境变量

与Vue项目一样,Nuxt.js也使用dotenv库来实现运行阶段的环境变量设置。

如果项目的根目录下存在.env文件,则会被自动加载进process.env。
如果配置文件是别的名字,也可以在启动的时候,显示指定并加载:

--dotenv <配置文件>

通过这种方式,可以为不同环境指定不同的配置文件。

.env文件的变量是被加载进process.env的,那么如何在代码中使用呢?

首先,我们知道,nuxt.js提供了多种渲染方式,服务端渲染、客户端渲染、静态渲染。为了安全,Nuxt.js又提出了两种运行时配置:

  • 运行阶段的公有配置 publicRuntimeConfig
  • 运行阶段的私有配置 privateRuntimeConfig

1). 公有配置 publicRuntimeConfig 字段

nuxt.config.js中的publicRuntimeConfig用于设置在服务端和客户端都可以使用的参数:

export default {
  publicRuntimeConfig: {
   GUEST_USER: process.env.GUEST_USER || "guest",
   GUEST_SECRET: process.env.GUEST_SECRET || "guest"
  }
}

在运行时,可以直接使用$config.<参数>来访问。

注意: 不是什么代码中都可以直接使用$config

2). 私有配置 privateRuntimeConfig 字段

nuxt.config.js中privateRuntimeConfig用于设置仅在服务端使用的参数,通常用于保存敏感信息:

export default {
  publicRuntimeConfig: {
   ADMIN_USER: process.env.ADMIN_USER || "admin",
   ADMIN_SECRET: process.env.ADMIN_SECRET || "password"
  }
}

同样的,在运行时,可以直接使用$config.<参数>来访问。

注意
如果privateRuntimeConfig与publicRuntimeConfig有同名参数,则私有参数覆盖公有参数,也就是privateRuntimeConfig优先级更高。

3). 使用运行阶段的配置参数

运行阶段的配置参数会被注入到nuxt.config中。

在script中,可以通过context.$config,或者this.$config来访问:

<script>
  asyncData ({ $config: { baseURL } }) {
    const posts = await fetch(`${baseURL}/posts`)
      .then(res => res.json())
  }
</script>

注意 也就说,script的环境中需要有Nuxt.js的context才能访问。

或者template中,直接使用$config

<template>
  <p>Our Url is: {{ $config.baseURL}}</p>
</template>

官方提示
如果在服务端之外的环境中使用$config,则可能会暴露私有配置。也就说,不要在客户端代码中使用私有参数。

node-nuxt-vue-process-env-details-02

那么,问题来了:
这是因为这些参数会被静态嵌入到客户端代码里,还是注入到客户端的$config,从而被暴露?

3.3. 模块Modules的参数配置

nuxt.config.js中还可以直接为模块设置参数,具体参数的由每个模块自己来实现。

例如,常用的axios网络模块,会读取nuxt.config.js中的 axios 字段作为自己的默认参数:

  axios: {
    // baseURL: process.env.API_URL + '/api',
    // proxy: true,
    baseURL: process.env.BASE_URL
  }

而谷歌分析模块@nuxtjs/google-analytics读取字段 googleAnalytics:

  googleAnalytics: {
    id: process.env.GOOGLE_ANALYTICS_ID
  },

那么,问题又来了:
这些参数是编译阶段参数、还是运行阶段参数?在私有还是公有?该如何使用呢?

要回答这些问题,需要参考Nuxt.js的module文档:

https://nuxtjs.org/docs/directory-structure/modules/

3.4. 总结

Nuxt.js项目中,环境变量可以

  • 在操作系统中设置
  • 在启动命令中设置(运行时设置,或者配置在package.json中)
  • 在nuxt.config.js中的env中配置
  • 在编译阶段,可以使用process.env来访问环境变量
  • 而在运行阶段,通过将process.env赋值给publicRuntimeConfig或者privateRuntimeConfig,注入到context.$config,供服务端代码或者客户端代码使用。

在博文《Node环境变量 process.env 的那些事儿》的评论中,有一个有趣的回复:

https://segmentfault.com/a/1190000011683741
node-nuxt-vue-process-env-details-03


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK