Vue CLI中模式与环境变量的深入详解


Posted in Vue.js onMay 30, 2021

前言

在实际项目的开发中,我们一般会经历项目的开发阶段、测试阶段和最终上线阶段,每一个阶段对于项目代码的要求可能都不尽相同,那么我们如何能够游刃有余的在不同阶段下使我们的项目呈现不同的效果,使用不同的功能呢?
这里就需要引入环境的概念。官方文档中模式和环境变量说明

一般一个项目都会有以下 3 种环境:

  • 开发环境(开发阶段,本地开发版本,一般会使用一些调试工具或额外的辅助功能);
  • 测试环境(测试阶段,上线前版本,除了一些 bug 的修复,基本不会和上线版本有很大差别);
  • 生产环境(上线阶段,正式对外发布的版本,一般会进行优化,关掉错误报告);

作为一名开发人员,我们可能需要针对每一种环境编写一些不同的代码并且保证这些代码运行在正确的环境中,那么我们应该如何在代码中判断项目所处的环境同时执行不同的代码呢?这就需要我们进行正确的环境配置和管理。

1. 配置文件

正确的配置环境首先需要我们认识不同环境配置之间的关系,如图所示:

Vue CLI中模式与环境变量的深入详解

我们从上图中可以了解到每一个环境其实有其不同的配置,同时它们也存在着交集部分,交集便是它们都共有的配置项,那么在 Vue 中我们应该如何处理呢?

我们可以在根目录下创建以下形式的文件进行不同环境下变量的配置:

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

Vue CLI中模式与环境变量的深入详解

Vue CLI中模式与环境变量的深入详解

如:创建一个名为 .env.development 的文件,该文件表明其只在 development 环境下被加载。

在这个文件中,我们可以配置如下键值对的变量:

# 开发环境配置
NODE_ENV=development
VUE_APP_API_BASE_URL=https://www.baidu.com/

这时怎么在 vue.config.js 中访问这些变量呢?使用 process.env.[name] 进行访问就可以了。

// vue.config.js
console.log(process.env.NODE_ENV); // development(在终端输出)

当运行 npm run serve 命令后会发现输出的是 development,因为 vue-cli-service serve 命令 默认设置的环境就是 development。

如果我们需要修改,可将 package.json 中的 serve 脚本的命令为:

// package.json
"scripts": {
  "serve": "vue-cli-service serve --mode stage",
},

?mode stage 其实就是修改了 webpack 4 中的 mode 配置项为 stage,同时其会读取对应 .env.[model] 文件下的配置。
如果没找到对应配置文件,其会使用默认环境 development,同样 vue-cli-service build 会使用默认环境 production。

如果再创建一个 .env 的文件,再次配置重复的变量,但是值不同。

# 环境配置
NODE_ENV=ENV
VUE_APP_API_BASE_URL=http://www.soso.com/

因为 .env 文件会被所有环境加载,即公共配置,那么最终运行 vue-cli-service serve 打印出来的是哪个呢?

答案是 development。

但是如果是 .env.development.local 文件中配置成上方这样,答案便是 ENV。

所以 .env.[mode].local 会覆盖 .env.[mode] 下的相同配置。

同理 .env.local 会覆盖 .env 下的相同配置。

由此可以得出结论,相同配置项的权重:.env.[mode].local > .env.[mode] > .env.local > .env
注意: 除了相同配置项权重大的覆盖小的,不同配置项它们会进行合并操作,类似于 Javascript 中的 Object.assign 的用法。

2. 环境注入

通过上述配置文件的创建,我们成功地使用命令行的形式对项目环境进行了设置并可以自由切换,但是注意:在 Vue 的前端代码中打印出的 process.env 与 vue.config.js 中输出的可能是不一样的,这需要普及一个知识点:webpack 通过 DefinePlugin 内置插件将 process.env 注入到客户端代码中。

// webpack 配置
{
    ...
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        }),
    ], 
    ...
}

由于 vue-cli 3.x 封装的 webpack 配置中已经帮我们完成了这个功能,所以可以直接在客户端代码中打印出 process.env 的值,该对象可以包含多个键值对,也就是说可以注入多个值,但是 经过 vue-cli 封装后仅支持注入环境配置文件中以 VUE_APP_ 开头的变量,而 NODE_ENV 和 BASE_URL 这两个特殊变量除外。

比如:在权重最高的 .env.development.local 文件中写入:

# 开发环境配置
NODE_ENV=developmentLocal
VUE_APP_API_BASE_URL=https://www.baidu.com/
NAME=javaScript

然后我们尝试在 vue.config.js 中打印 process.env,终端输出:

{
    ...
    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: 'developmentLocal',
    VUE_APP_API_BASE_URL: 'https://www.baidu.com/',
    NAME: 'javaScript',
    BABEL_ENV: 'development',
    ...
}

可以看到输出内容除了环境配置中的变量外还包含了很多 npm 的信息,但在入口文件 main.js 中打印会发现输出:

{
  BASE_URL: "/",
  NODE_ENV: "developmentLocal",
  VUE_APP_API_BASE_URL: "https://www.baidu.com/",
}

可见注入时过滤调了非 VUE_APP_ 开头的变量,其中多出的 BASE_URL 为你在 vue.config.js 设置的值,默认为 /,其在环境配置文件中设置无效。

Vue CLI中模式与环境变量的深入详解

3. 额外配置

以上我们通过新建配置文件的方式为项目不同环境配置不同的变量值,能够实现项目基本的环境管理,但是 .env 这样的配置文件中的参数目前只支持静态值,无法使用动态参数,在某些情况下无法实现特定需求。

这时候可以在根目录下新建 config 文件夹用于存放一些额外的配置文件。

/* 配置文件 index.js */
 
// 公共变量
const com = {
  IP: JSON.stringify('xxx')
};

module.exports = {
  // 开发环境变量
  dev: {
    env: {
      TYPE: JSON.stringify('dev'),
      ...com
    }
  },
  // 生产环境变量
  build: {
    env: {
      TYPE: JSON.stringify('prod'),
      ...com
    }
  }
}

以上代码把环境变量分为了公共变量、开发环境变量和生产环境变量,当然这些变量可能是动态的,比如用户的 ip 等。
现在我们要在 vue.config.js 里注入这些变量,可以使用 chainWebpack 修改 DefinePlugin 中的值:

/* vue.config.js */
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 = 'process.env';
      // 使用 merge 保证原始值不变
      args[0][name] = merge(args[0][name], cfg);
      return args
    })
  },	
}

最后可以在客户端成功打印出包含动态配置的对象:

{
  BASE_URL: "/",
  IP: "xxx",
  NODE_ENV: "developmentLocal",
  TYPE: "dev",
  VUE_APP_API_BASE_URL: "https://www.baidu.com/",
}

4. 实际场景

使用 process.env.xxx 来访问属性

<script>
export default {
  data() { 
    return {
      BASEURL:process.env,
    } 
  },  
  mounted(){
 	console.log(this.BASEURL.VUE_APP_API_BASE_URL) // https://www.baidu.com/
  }
}
</script>
// 创建 axios 实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  timeout: 5000
})

结语

环境的配置和管理对于项目的构建起到了至关重要的作用,通过给项目配置不同的环境不仅可以增加开发的灵活性、提高程序的拓展性,同时也有助于帮助我们去了解并分析项目在不同环境下的运行机制,建立全局观念。

到此这篇关于Vue CLI中模式与环境变量的文章就介绍到这了,更多相关Vue CLI模式与环境变量内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
vue+iview实现分页及查询功能
Nov 17 Vue.js
用vue设计一个日历表
Dec 03 Vue.js
Vue中computed和watch有哪些区别
Dec 19 Vue.js
vue监听滚动事件的方法
Dec 21 Vue.js
vue 实现图片懒加载功能
Dec 31 Vue.js
vuex的使用步骤
Jan 06 Vue.js
Vue中的nextTick作用和几个简单的使用场景
Jan 25 Vue.js
如何封装Vue Element的table表格组件
Feb 06 Vue.js
vue3.0中使用element的完整步骤
Mar 04 Vue.js
vue使用节流函数的踩坑实例指南
May 20 Vue.js
vue中div禁止点击事件的实现
Apr 02 Vue.js
vue封装数字翻牌器
Apr 20 Vue.js
springboot+VUE实现登录注册
May 27 #Vue.js
vue+springboot实现登录验证码
vue+spring boot实现校验码功能
May 27 #Vue.js
vue-cropper组件实现图片切割上传
May 27 #Vue.js
vue-cropper插件实现图片截取上传组件封装
May 27 #Vue.js
HTML+VUE分页实现炫酷物联网大屏功能
Vue实现动态查询规则生成组件
You might like
php图片缩放实现方法
2014/02/20 PHP
PHP+swoole实现简单多人在线聊天群发
2016/01/19 PHP
图片自动缩小的js代码,用以防止图片撑破页面
2007/03/12 Javascript
网上抓的一个特效
2007/05/11 Javascript
js中访问html中iframe的文档对象的代码[IE6,IE7,IE8,FF]
2011/01/08 Javascript
获取表单控件原始(初始)值的方法
2013/08/21 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
24款热门实用的jQuery插件推荐
2014/12/24 Javascript
JavaScript中Number.MAX_VALUE属性的使用方法
2015/06/04 Javascript
jQuery中数据缓存$.data的用法及源码完全解析
2016/04/29 Javascript
jQuery简单实现上下,左右滑动的方法
2016/06/01 Javascript
移动端日期插件Mobiscroll.js使用详解
2016/12/19 Javascript
用jQuery.ajaxSetup实现对请求和响应数据的过滤
2016/12/20 Javascript
老生常谈ES6中的类
2017/07/31 Javascript
Node.js+jade抓取博客所有文章生成静态html文件的实例
2017/09/19 Javascript
nodejs微信开发之授权登录+获取用户信息
2019/03/17 NodeJs
Vue学习之axios的使用方法实例分析
2020/01/06 Javascript
解决iView Table组件宽度只变大不变小的问题
2020/11/13 Javascript
[04:50]DOTA2亚洲邀请赛小组赛第四日 TOP10精彩集锦
2015/02/02 DOTA
Python callable()函数用法实例分析
2018/03/17 Python
python自动化生成IOS的图标
2018/11/13 Python
python实现QQ邮箱/163邮箱的邮件发送
2019/01/22 Python
Python OpenCV视频截取并保存实现代码
2019/11/30 Python
python求绝对值的三种方法小结
2019/12/04 Python
Python常用库Numpy进行矩阵运算详解
2020/07/21 Python
python实现录音功能(可随时停止录音)
2020/10/26 Python
美国知名男士服饰品牌:Brooks Brothers(布克兄弟)
2016/08/25 全球购物
数据库方面面试题
2012/04/22 面试题
企业管理部经理岗位职责
2013/12/24 职场文书
优秀班组长事迹
2014/05/31 职场文书
迎国庆横幅标语
2014/10/08 职场文书
党员群众路线个人整改措施思想汇报
2014/10/12 职场文书
2015年化验室工作总结
2015/04/23 职场文书
实习指导老师意见
2015/06/04 职场文书
摘录式读书笔记
2015/07/01 职场文书
MySQL详解进行JDBC编程与增删改查方法
2022/06/16 MySQL