写在前面
最近在忙一个新web平台的技术调研工作, 昨天在项目站会汇报时,同事说已完成项目多环境切换, 有点困惑就去看了下git提交记录, 发现有提交.env/.env.test/.env.development等文件, 不太懂什么意思,故有了此文章。
vue-cli脚手架搭建的
在项目启动时,vue-cli会将以VUE_APP开头的变量读取至环境变量,这是vue-cli强制要求的=.=
.env是什么?
.env不管生产or开发环境都会加载的文件; .env.production是生产环境配置文件; .env.development是开发环境配置文件。
我们先看下常规的package.json文件一般是如下这么配置的
{"scripts": {"dev": "vue-cli-service serve", // npm run dev本地开发运行,会把process.env.NODE_ENV设置为'development'"build": "vue-cli-service build", // npm run build默认打包模式, 会把process.env.NODE_ENV设置为'production'}}
如何使用.env实现多环境切换?
为便于描述,这里先展示2个环境: production生产环境&&development开发环境。
- 项目根目录下新建.env.production && .env.development文件
- 分别配置2个文件的环境属性(Tips:必须与VUEAPP开头且属性命名必须全部大写) ``` // .env.production VUE_APP_BASE_URL=”http://vtodo-list.com“
// .env.development VUE_APP_BASE_URL=”http://localhost:3000“
- 在需要的使用, 通过如下命令去获取
console.log(‘当前环境baseurl:’, process.env.VUE_APP_BASE_URL)
<a name="Kh5Lm"></a>### 如何新增自定义环境?若想追加自定义环境的话eg:测试环境test, 可按照下面的配置:- 根目录下新建.env.test文件- 配置该文件的环境属性
// .env.test VUE_APP_BASE_URL=”http://vtodo-test-list.com“
- package.json中新增环境变量命令
// 添加自定义环境, —mode后面的参数对应.env.xx文件后缀 { “scripts”: { “dev:test”: “vue-cli-service serve —mode test” } }
- 测试配置是否生效
npm run dev:test
// 需要使用的文件处 console.log(‘当前环境baseurl:’, process.env.VUE_APP_BASE_URL)
<a name="Xd1hf"></a>### vue.config.js中代理配置如何跟.env联系起来?> 现状: 在本地开发时,通过localhost访问接口会跨域,此方案是通过本起一个devServer服务, 反向代理的方式处理此问题,若需要切换环境时需要每次手动改代码。> 考虑:既然.env能实现多环境的切换, 那么该文件的代理配置能否跟.env联系起来呢?
// vue.config.js文件 module.exports = { devServer: { port: 9999, proxy: { ‘/*’: { target: “https://www.xxx-test.com“, //dev环境 // target: ‘https://www.xxx.com‘, //prd环境 target: process.env.VUE_APP_BASE_URL, // 关键代码通过.env联系起来 changOrigin: true, }, }, } }
<a name="X7YrJ"></a>##<a name="L0cbA"></a>## 剖析process.env环境<a name="T8TBQ"></a>### dotenv> 零依赖模块, 将环境变量从.env文件读取至process.env环境变量中.下面我们研究下使用教程:- 初始化package.json文件
npm init -y
- 安装dotenv
npm i dotenv -D
笔者在安装过程中遇到报错了Error: Refusing to install package with name 'dotenv' under a package.<br /><br />该问题出现的原因是:安装的依赖名跟项目名重复了,这里修改下package.json中的name即可正确安装。<br />- 项目根目录下新建.env文件
// 内容可自定义,符合key=value即可
以#开头的会被注释, 不会被读取到
BASE_URL=’http://192.168.103.88‘
- 新建src/main.js文件
const dotenv = require(‘dotenv’)
dotenv.config({})
console.log(name=> ${process.env.BASE_URL})
- 本地运行该文件
node src/mian.js
我们看下终端输出情况:是能正确拿到.env文件配置的。这里需要注意的是: 若你先进入src目录然后再执行node命令,你会发现输出是undefined。> **这是因为dotenv默认是去加载当前路径下的.env文件, 故会出现此差异。**<br />相信你看到这里也是有个疑问的:这是运行在node环境,而我们的项目是运行在浏览器环境的,这倆是怎么关联起来的呢?请往下看?<a name="F3FsS"></a>### 结合webpack使用- 安装webpack webpack-cli, 为方便管理HTML还安装html-webpack-plugin
npm i webpack webpack-cli html-webpack-plugin -D
- 根目录下新建webpack.config.json文件
const {resolve} = require(‘path’) const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
module.exports = { mode: ‘development’, entry: ‘./src/main.js’, output: { filename: ‘[name].js’, path: resolve(__dirname, ‘dist’), clean: true, }, plugins: [ new HtmlWebpackPlugin({ title: ‘自定义加载env文件’ }) ] }
- 新建index.html,引入main.js文件
<!DOCTYPE html>
- 修改src/main.js文件,如下
const process = {} console.log(document, ‘document’) process.env = document.title console.log(‘process相关参数’, process.env)
- 执行打包命令
npx webpack ./src/main.js
- 打包成功后,浏览器访问dist/index.html文件: 你会发现该终端有如下输出:<br />其实这里的主要目标是: 将webpack的HtmlWebpackPlugin插件配置的网页标题,在js文件中通过process.env去获取.> **该做法的缺陷: 所有需要使用到该网页标题的,需要单独引入该变量,不知道有没更好的办法注入该代码呢?**<br /><a name="bm5g8"></a>### 引入 DefinePlugin内置插件> DefinePlugin 允许在 编译时 将你代码中的变量替换为其他值或表达式。简单来说,它的作用就是文本替换,将值或表达式硬编码到代码中。其实我们思考下, 我们的webpack是运行在node环境的,而我们的项目是运行在浏览器的,2者是怎么联系起来的?- 使用dotenv加载.env中的环境变量- 在打包阶段读取环境变量- 以某种方式将环境变量合并到打包结果中下面我们演示下要怎么做替换✅- 修改webpack.config.js文件如下
const { resolve } = require(‘path’) const { DefinePlugin } = require(‘webpack’)
const BASE_URL = “‘http://192.168.0.0.1‘“
module.exports = { mode: ‘development’, entry: ‘./src/main.js’, output: { filename: ‘[name].js’, path: resolve(__dirname, ‘dist’), clean: true, }, plugins: [ new DefinePlugin({ ‘process.env’: BASE_URL }) ] }
- 修改main.js如下
console.log(name=> ${process.env.BASE_URL})
- 执行如下命令进行打包
npx webpack ./src/main.js
```
我们看下终端运行效果: 打包是成功的,也有在本地生成dist文件夹
- 本地打开dist/index.html文件,你会发现终端能正常输出env的配置
不过这里需要注意的是:若是number类型可直接替换, But进行文本替换的时候, 必须使用”‘xxx’”, 直接’xxx’会报错, 请看下图.

写在最后
webpack + dotenv + webpack DefinePlugin相互作用的成果,这也是前端工程化的表现。
