vue,react 项目.env 环境变量原理解析
简介:
.env
文件扩展了 vue
,react
项目的环境变量,相信大家用的比较多了,vue
和 react
的 cli
里把这些配置好了,所有大家可以直接用,但是换个框架或者换个项目,这个问题就比较麻烦了。
比如说现在写 Ant Design Pro
的项目,它内部用的是 umi
来做这些配置,默认只支持.env
文件,那我想支持.env.development
和.env.production
或者其他模式的环境变量怎么办?当然 umi@3 可以用config.dev.js
,config.js
, config.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