.env
文件配置 文件说明
.env
:全局默认配置文件,无论什么环境都会加载合并。.
:开发环境的配置文件.
:生产环境的配置文件.env.[mode]
: 只在指定的模式中被载入.
: 在所有的环境中被载入,但会被 git 忽略.env.[mode].local
: 只在指定的模式中被载入,但会被 git 忽略
例:
-
.env.[mode]
比如.
该文件表明其只在 stage 环境下被加载
在这个文件中,我们可以配置如下键值对的变量:
NODE_ENV=stage
VUE_APP_TITLE=stage mode
在 中访问这些变量呢?很简单,使用 .[name] 进行访问就可以了,比如:
(.NODE_ENV); // development(在终端输出)
因为 vue-cli-service serve 命令默认设置的环境是 development,你需要修改 中的 serve 脚本的命令为:
"scripts": {
"serve": "vue-cli-service serve --mode stage",
}
--mode stage
其实就是修改了 webpack 4 中的 mode
配置项为 stage
,同时其会读取对应 .env.[model] 文件下的配置,如果没找到对应配置文件,其会使用默认环境 development,同样 vue-cli-service build 会使用默认环境 production。
-
.env
再创建一个 .env的文件,再次配置重复的变量,但是值不同,如:
NODE_ENV=staging
VUE_APP_TITLE=staging mode
VUE_APP_NAME=project
.env 文件会被所有环境加载,即公共配置,那么最终我们运行 vue-cli-service serve 打印出来的是哪个呢?答案是 stage
如果是 . 文件中配置成上方这样,答案便是 staging
.env.[mode].local 会覆盖 .env.[mode] 下的相同配置。同理 . 会覆盖 .env 下的相同配置。
相同配置项的权重:
.env.[mode].local > .env.[mode] > . > .env
除了相同配置项权重大的覆盖小的,不同配置项它们会进行合并操作
环境注入
ue 的前端代码中打印出的 与 中输出的可能是不一样的,这需要普及一个知识点:webpack 通过 DefinePlugin 内置插件将 注入到客户端代码中。
// webpack 配置
{
...
plugins: [
new webpack.DefinePlugin({
'': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
],
...
}
由于 vue-cli 封装的 webpack 配置中已经帮我们完成了这个功能,所以我们可以直接在客户端代码中打印出 的值,该对象可以包含多个键值对,也就是说可以注入多个值,但是经过 CLI 封装后仅支持注入环境配置文件中以 VUE_APP_ 开头的变量,而 NODE_ENV 和 BASE_URL 这两个特殊变量除外。
比如我们在环境中配置
NODE_ENV=stage2
VUE_APP_TITLE=stage mode2
NAME=vue
尝试在 中打印 ,终端输出:
{
...
npm_config_ignore_scripts: '',
npm_config_version_git_sign: '',
npm_config_ignore_optional: '',
npm_config_init_version: '1.0.0',
npm_package_dependencies_vue_router: '^3.0.1',
npm_config_version_tag_prefix: 'v',
npm_node_execpath: '/usr/local/bin/node',
NODE_ENV: 'stage2',
VUE_APP_TITLE: 'stage mode2',
NAME: 'vue',
BABEL_ENV: 'development',
...
}
除了我们环境配置中的变量外还包含了很多 npm 的信息,但是我们在入口文件 中打印会发现输出:
{
"BASE_URL": "/vue/",
"NODE_ENV": "stage2",
"VUE_APP_TITLE": "stage mode2"
}
可见注入时过滤调了非 VUE_APP_ 开头的变量
其中多出的 BASE_URL 为你在 设置的值,默认为 /,其在环境配置文件中设置无效。
额外配置
.env 配置文件中的参数目前只支持静态值,无法使用动态参数,在某些情况下无法实现特定需求,这时候我们可以在根目录下新建 config 文件夹用于存放一些额外的配置文件。
/* 配置文件 */
// 公共变量
const com = {
IP: JSON.stringify('xxx')
};
module.exports = {
// 开发环境变量
dev: {
env: {
TYPE: JSON.stringify('dev'),
...com
}
},
// 生产环境变量
build: {
env: {
TYPE: JSON.stringify('prod'),
...com
}
}
}
里注入这些变量
/* */
const configs = require('./config');
// 用于做相应的 merge 处理
const merge = require('webpack-merge');
// 根据环境判断使用哪份配置
const cfg = process.env.NODE_ENV === 'production' ? configs.build.env : configs.dev.env;
module.exports = {
...
chainWebpack: config => {
config.plugin('define')
.tap(args => {
let name = '';
// 使用 merge 保证原始值不变
args[0][name] = merge(args[0][name], cfg);
return args
})
},
...
}
最后在客户端成功打印出包含动态配置的对象:
{
"NODE_ENV": "stage2",
"VUE_APP_TITLE": "stage mode2",
"BASE_URL": "/vue/",
"TYPE": "dev",
"IP": "xxx"
}
实际场景
实际场景: 比如在非线上环境我们可以给自己的移动端项目开启 vConsole 调试,但是在线上环境肯定不需要开启这一功能,我们可以在入口文件中进行设置,代码如下:
/* */
import Vue from 'vue'
import App from './'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// 如果是非线上环境,加载 VConsole
if (process.env.NODE_ENV !== 'production') {
var VConsole = require('vconsole/dist/');
var vConsole = new VConsole();
}
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
配置中的 BASE_URL 来设置路由的 base 参数
/* */
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/'
import About from './views/'
Vue.use(Router)
let base = `${process.env.BASE_URL}`; // 获取二级目录
export default new Router({
mode: 'history',
base: base, // 设置 base 值
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
]
})
每一个环境变量你都可以用于项目的一些地方,它提供给了我们一种全局的可访问形式,也是基于 Node 开发的特性所在。
结语
环境的配置和管理对于项目的构建起到了至关重要的作用,通过给项目配置不同的环境不仅可以增加开发的灵活性、提高程序的拓展性,同时也有助于帮助我们去了解并分析项目在不同环境下的运行机制,建立全局观念。