浅谈Webpack下多环境配置的思路


Posted in Javascript onJune 27, 2018

前言

由于前后端分离的前端应用脱离了后端的支持,在单独开发前端应用时,页面调试时使用固定的开发环境地址还好,如果出现在本地开发时需要调试不同环境的远端API,或者需要将应用部署到不同环境的服务器上时,如果不将这些环境对应的服务器地址、环境专属变量等单独配置,也许每次切换环境都需要修改大量代码。网上关于这部分的资料较少,所以下面将以用vue-cli init命令生成的Vue/Webpack项目作为例子,介绍一下我当前正在使用的简单的多环境配置的思路。

1、理想中的多环境配置

在后端开发中,项目中不同环境对应的参数配置在不同的配置文件中。当需要打包基于Maven的Java项目时,通常只需要在打包命令的后面加上-P参数指定Profile环境,即可打包出对应环境的包,同理前端在使用webpack开发或者打包时如果也能这么做,就会方便很多。

/* maven常用打包命令 */
mvn clean package -P prod

而在前端项目中,调试与打包命令vue-cli init已经为我们在package.json中生成好了。

/* /package.json */
"scripts": {
  "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
  "start": "npm run dev",
  "lint": "eslint --ext .js,.vue src",
  "build": "node build/build.js"
 }

如果可以将这些命令改造成后端中类似的打包命令,就很方便了,例如:

/* 改造后的命令,只是打个比方,实际并不一定是这样 */
"scripts": {
  "start:dev": "npm run dev -P dev",
  "build:test": "node build/build.js -P test"
 }

/* 命令行 */
$ npm run start:dev //本地调试,开发环境
$ npm run build:test //打包,测试环境

所以首先需要解决的是如何把参数传递到调试/打包的脚本中。

注意:这里想特别说明一下的是,vue-cli脚手架帮我们生成好了整个项目,而且也有对应webpack.dev.conf.jswebpack.prod.conf.js两个分离的webpack配置文件,但由于文件的命名问题(dev.conf.js/prod.conf.js),很容易让人误以为这两个文件就是webpack针对不同环境的配置。但实际上这两个文件一个是用于本地调试时的配置文件,另一个是用于打包部署的配置文件。调试/打包两种模式 与 环境(dev/test/pre/prod等)是可以相互组合的。理论上来讲这两个webpack的配置文件我觉得应该叫webpack.debug.conf.jswebpack.build.conf.js会更贴切一点。

2、脚本参数化

node.js中传递参数到脚本中,有多种方法,例如使用process.argv

/* hello.js */
console.log('hello ', process.argv[2]);

/* 命令行 */
$ node ./hello.js tidus
//process.argv = ['node', './hello.js', 'tidus']
hello tidus

虽然process.argv很方便,但可配置性不高,所以这里用的是yargs,它是node.js中的一个组件,可以通过npm直接安装。
===>戳我查看yargs的api文档

$ npm install yargs --dev --save

/* hello.js */
const argv = require('yargs').argv;
console.log('hello ', argv.env);

/* 命令行 */
$ node ./hello.js --env test
hello test

通过yargs可以方便的获取指定名称的命令行参数,接下来就要看看如何利用这个参数实现多文件配置。

3、引入环境变量

首先在Webpack的官网中已经有过简单介绍如何配置环境变量的文档,具体参考Webpack Production。简单的来说就是DefinePlugin插件会将我们源码中所有出现的指定字符串替换为我们提供的对象/字符串,不同环境的配置文件则放在/config目录下。

/* /build/webpack.dev.conf.js: */
plugins: [
  new webpack.DefinePlugin({
   // 源码中所有 process.env 都会被替换为
   // '../config/dev.env'这个module export出来的东西
   'process.env': require('../config/dev.env')
  })
]

/* /config/dev.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
 NODE_ENV: '"development"'
})

显然我们可以直接用这个插件为我们的多环境变量服务。

我们可以通过上面传入到脚本中的环境参数,动态加载不同环境的配置文件,以达到切换环境的目的。动态加载不同配置环境的代码:

/* /build/webpack.env.conf.js */
// 定义参数配置
const argv = require('yargs').argv;

// 获取环境变量
const env = argv.e;
process.stdout.write('the env is '+ env +'\n');

// require指定的环境配置文件
const envConfigFile = "../config/" + env + ".env.js";
process.stdout.write('the env config file is '+ envConfigFile +'\n');

// 将require的配置文件原封不动export回出去
module.exports = require(envConfigFile);

接下来要将动态加载的环境文件丢到webpack的配置文件中,由于webpack.dev.conf.jswebpack.prod.conf.js都是继承自webpack.base.conf.js,所以我们直接改写wepack.base.conf.js的插件配置部分,直接添加DefinePlugin插件的配置,并去掉原配置文件该插件的配置:

/* /build/webpack.base.conf.js */

// 引入上面的webpack.env.conf模块
const envConfig = require('./webpack.env.conf')
module.exports = {
 ...
 ,
 // 配置DefinePlugin插件
 plugins: [
  // http://vuejs.github.io/vue-loader/en/workflow/production.html
  new webpack.DefinePlugin({
   'process.env': envConfig
  })
 ],
 ...
}

然后调试/打包的命令还是用回默认生成的命令,只不过在命令后面传入环境参数:

/* /package.json */
"scripts": {
  "start:dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --e dev",
  "start:test": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --e test",
  "start:pre": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --e pre",
  "start:prod": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --e prod",
  "build:dev": "node build/build.js --e dev",
  "build:test": "node build/build.js --e test",
  "build:pre": "node build/build.js --e pre",
  "build:prod": "node build/build.js --e prod",
 }

我们的环境配置文件中的内容可以是这样的:

/* /config/test.env.js */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
 NODE_ENV: '"test"',
 API_HOST: '"http://test.xx.com:8080"'
})

然后我们就可以在源码中使用process.env.NODE_ENV来获取我们配置的环境变量的值,甚至可以单独抽离一个api模块:

/* /src/api/index.js */
const API_HOST = process.env.API_HOST;

export default {
 api1: `${API_HOST}/path/to/api1`,
 api2: `${API_HOST}/path/to/api2`
}

最后,在我们的Vue组件中就可以很方便的使用这些环境配置了:

/* /src/components/HelloWorld.vue */
 import api from '@/api';
 data () {
   return {
    msg: 'Welcome to Your Vue.js App',
    env: process.env.NODE_ENV,
    api1: api.api1,
    api2: api.api2
   }
  }

4、总结

整个流程下来,我们添加了一个webpack.env.conf.js模块,稍微小修改了一下vue-cli生成的3个webpack配置文件,并在config目录下添加了各个环境的配置文件,项目的结构是这样子的:

浅谈Webpack下多环境配置的思路

目录结构

最终在页面上看到的是这样子的:

浅谈Webpack下多环境配置的思路

输出环境参数

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery学习笔记 获取jQuery对象
Sep 19 Javascript
JS中三目运算符和if else的区别分析与示例
Nov 21 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
Jan 18 Javascript
JavaScript调试之console.log调试的一个小技巧分享
Aug 07 Javascript
浅谈Angular路由复用策略
Oct 04 Javascript
vue-scroller记录滚动位置的示例代码
Jan 17 Javascript
AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
Jan 30 Javascript
vue 修改 data 数据问题并实时显示的方法
Aug 27 Javascript
详解在HTTPS 项目中使用百度地图 API
Apr 26 Javascript
详解小程序之简单登录注册表单验证
May 13 Javascript
Vue替代marquee标签超出宽度文字横向滚动效果
Dec 09 Javascript
JS class语法糖的深入剖析
Jul 07 Javascript
Vue使用vue-area-linkage实现地址三级联动效果的示例
Jun 27 #Javascript
详解关于vue-area-linkage走过的坑
Jun 27 #Javascript
详解nuxt sass全局变量(公共scss解决方案)
Jun 27 #Javascript
Vue引入sass并配置全局变量的方法
Jun 27 #Javascript
详解解决使用axios发送json后台接收不到的问题
Jun 27 #Javascript
vue中v-model的应用及使用详解
Jun 27 #Javascript
JS基于封装函数实现的表格分页完整示例
Jun 26 #Javascript
You might like
ajax返回值中有回车换行、空格的解决方法分享
2013/10/24 PHP
php实现json编码的方法
2015/07/30 PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
2018/10/16 PHP
PHP配合fiddler抓包抓取微信指数小程序数据的实现方法分析
2020/01/02 PHP
javascript测试题练习代码
2012/10/10 Javascript
JavaScript中的Truthy和Falsy介绍
2015/01/01 Javascript
javascript中tostring()和valueof()的用法及两者的区别
2015/11/16 Javascript
使用UrlConnection实现后台模拟http请求的简单实例
2017/01/04 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
2017/03/28 Javascript
vue拦截器Vue.http.interceptors.push使用详解
2017/04/22 Javascript
Node.js利用debug模块打印出调试日志的方法
2017/04/25 Javascript
Vue上传组件vue Simple Uploader的用法示例
2017/08/25 Javascript
vue 系列——vue2-webpack2框架搭建踩坑之路
2017/12/22 Javascript
JS运动特效之同时运动实现方法分析
2018/01/24 Javascript
webpack 打包压缩js和css的方法示例
2018/03/20 Javascript
webpack4的迁移的使用方法
2018/05/25 Javascript
jquery获取元素到屏幕四周可视距离的方法
2018/09/05 jQuery
typescript nodejs 依赖注入实现方法代码详解
2019/07/21 NodeJs
Node.js API详解之 os模块用法实例分析
2020/05/06 Javascript
javascript实现扫雷简易版
2020/08/18 Javascript
vue 使用rules对表单字段进行校验的步骤
2020/12/25 Vue.js
Selenium执行JavaScript脚本的方法示例
2020/12/31 Javascript
python 控制语句
2011/11/03 Python
python的文件操作方法汇总
2017/11/10 Python
书单|人生苦短,你还不用python!
2017/12/29 Python
解决pycharm下pyuic工具使用的问题
2020/04/08 Python
Anaconda和ipython环境适配的实现
2020/04/22 Python
Kears 使用:通过回调函数保存最佳准确率下的模型操作
2020/06/17 Python
物业客服专员岗位职责
2013/11/30 职场文书
护士毕业生自我鉴定
2014/02/08 职场文书
学生周末长期请假条
2014/02/15 职场文书
《阳光》教学反思
2014/02/23 职场文书
开展党的群众路线教育实践活动个人对照检查材料
2014/11/05 职场文书
中学校园广播稿
2015/08/18 职场文书
七年级写作指导之游记作文
2019/10/07 职场文书
html用代码制作虚线框怎么做? dw制作虚线圆圈的技巧
2022/12/24 HTML / CSS