vue,react 项目.env 环境变量原理解析

简介:

.env 文件扩展了 vuereact 项目的环境变量,相信大家用的比较多了,vuereactcli 里把这些配置好了,所有大家可以直接用,但是换个框架或者换个项目,这个问题就比较麻烦了。

比如说现在写 Ant Design Pro 的项目,它内部用的是 umi 来做这些配置,默认只支持.env 文件,那我想支持.env.development.env.production或者其他模式的环境变量怎么办?当然 umi@3 可以用config.dev.jsconfig.jsconfig.prod.js这些文件结合UMI_ENV来解决这些问题,可是心里很不爽。

于是你又开始写一个 nuxt 的项目,发现它里面的配置文件 nuxt.config.js 也仅仅支持 env:{} 对象扩展,那么问题来了,那我还想支持.env.development.env.production或者其他模式的环境变量怎么办?

既然项目的改变我们控制不了,那我们只能搞清楚 vue 里的 env 文件加载原理,以不变应万变了。

下面是解决思路。

1.新建一个.env.development 文件

1
NODE_ENV=development
2
VUE_APP_WEB_TITLE=test
3
VUE_APP_BASE_URL=http://0.0.0.0

2.核心实现,解析 env 文件

先安装依赖
dotenv
dotenv-expand

根据 vue-cli 源码
https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/Service.js

https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/util/resolveClientEnv.js
改写

parseEnv.js

1
const fs = require('fs')
2
const path = require('path')
3
const dotenv = require('dotenv') // 解析.env.*文件为键值对,并写入环境变量。
4
const variableExpansion = require('dotenv-expand') // 拿到dotenv解析的参数,扩展计算机上已经存在的环境变量(存在就赋值)。
5
6
const resolve = dir => path.join(__dirname, dir)
7
const prefixRE = /^VUE_APP_/
8
9
/*
10
这里加载的是development 模式文件,需要其他的可以根据启动参数来动态修改,或者NODE_ENV来修改
11
12
ag:根据NODE_ENV来修改
13
const env = variableExpansion(
14
  dotenv.parse(fs.readFileSync(resolve(`./.env.${process.env.NODE_ENV}`)))
15
)
16
*/
17
const env = variableExpansion(
18
  dotenv.parse(fs.readFileSync(resolve(`./.env.development`)))
19
)
20
Object.keys(env).forEach(key => {
21
  if (prefixRE.test(key) || key === 'NODE_ENV') {
22
    env[key] = JSON.stringify(env[key]) // JSON.stringify 的目的是为了给webpack.DefinePlugin 的值是 '"development"',DefinePlugin插件配置要求
23
  } else {
24
    Reflect.deleteProperty(env, key)
25
  }
26
})
27
28
module.exports = env

3.配置 webpack,注入环境变量到项目中

1
const webpack = require('webpack')
2
3
// 加载.env.* 环境变量
4
const env = require('./parseEnv')
5
6
console.log(env) // {NODE_ENV: '"development"',VUE_APP_WEB_TITLE: '"test"',VUE_APP_BASE_URL: '"http://0.0.0.0"'}
7
8
module.exports = {
9
  plugins: [new webpack.DefinePlugin({ 'process.env': env })]
10
}

4.使用

1
console.log(process.env.VUE_APP_BASE_URL) // 'http://0.0.0.0'

参考链接

1.https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/Service.js

2.https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/util/resolveClientEnv.js