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中echarts的用法及与elementui-select的协同绑定操作
Nov 17 Vue.js
详解Vue的mixin策略
Nov 19 Vue.js
vue使用echarts图表自适应的几种解决方案
Dec 04 Vue.js
基于vue+echarts数据可视化大屏展示的实现
Dec 25 Vue.js
vue 使用class创建和清除水印的示例代码
Dec 25 Vue.js
Vue实现随机验证码功能
Dec 29 Vue.js
vue-cli4.0多环境配置变量与模式详解
Dec 30 Vue.js
vue仿携程轮播图效果(滑动轮播,下方高度自适应)
Feb 11 Vue.js
Vue监视数据的原理详解
Feb 24 Vue.js
Vue中Object.assign清空数据报错的解决方案
Mar 03 Vue.js
ant design vue的form表单取值方法
Jun 01 Vue.js
vue3 自定义图片放大器效果的示例代码
Jul 23 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将Unicode 转化为UTF-8的实现方法(推荐)
2017/02/08 PHP
laravel 5.1下php artisan migrate的使用注意事项总结
2017/06/07 PHP
Thinkphp5行为使用方法汇总
2017/12/21 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
jQuery Ajax之$.get()方法和$.post()方法
2009/10/12 Javascript
JavaScript 语法集锦 脚本之家基础推荐
2009/11/15 Javascript
非主流的textarea自增长实现js代码
2011/12/20 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
2014/02/26 Javascript
原生JS和JQuery动态添加、删除表格行的方法
2015/05/28 Javascript
详细解读JavaScript编程中的Promise使用
2015/07/27 Javascript
基于Jquery easyui 选中特定的tab
2015/11/17 Javascript
Bootstrap每天必学之栅格系统(布局)
2015/11/25 Javascript
jQuery的promise与deferred对象在异步回调中的作用
2016/05/03 Javascript
原生javascript实现的ajax异步封装功能示例
2016/11/03 Javascript
js实现把图片的绝对路径转为base64字符串、blob对象再上传
2016/12/29 Javascript
JS对象创建的几种方式整理
2017/02/28 Javascript
详解JavaScript按概率随机生成事件
2017/08/02 Javascript
微信小程序如何获取用户信息
2018/01/26 Javascript
JavaScript 高性能数组去重的方法
2018/09/20 Javascript
vscode中Vue别名路径提示的实现
2020/07/31 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
2020/08/19 Javascript
[56:29]Secret vs Optic 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python通过pil模块获得图片exif信息的方法
2015/03/16 Python
对python-3-print重定向输出的几种方法总结
2018/05/11 Python
python 根据网易云歌曲的ID 直接下载歌曲的实例
2019/08/24 Python
Python加密模块的hashlib,hmac模块使用解析
2020/01/02 Python
Python递归实现打印多重列表代码
2020/02/27 Python
css3之UI元素状态伪类选择器实例演示
2017/08/11 HTML / CSS
高性能钓鱼服装:Huk Gear
2019/02/20 全球购物
青春奉献演讲稿
2014/05/08 职场文书
大专生找工作自荐书
2014/06/10 职场文书
就业协议书怎么填
2014/09/15 职场文书
投标售后服务承诺书
2015/04/29 职场文书
个人催款函范文
2015/06/24 职场文书
Axios取消重复请求的方法实例详解
2021/06/15 Javascript
漫画「日和酱的要求是绝对的」第3卷封面公开
2022/03/21 日漫