前篇文章 2020年,《深刻淺出Webpack》(吳浩麟2018/01)學習總結html
我寫了學習webpack的目的和過程,正所謂程序員的價值,每每經過他寫的代碼帶給社會的價值來體現。那麼這篇文章,我就結合本身目前所作的項目,介紹如何在修改更少代碼的狀況下創建多個開發環境及多個生產環境。前端
業務需求背景:筆者所服役的公司是一個小型外包,先後端並行開發,團隊都是按項目狀況從公司其餘地方的員工分配過來的人員,默契不算過高,連產品經理都是其餘公司的人員。vue
筆者這麼個還算新人的前端小白,也被誤打誤撞成了前端的負責人(固然,工資待遇是不會提升的,只有工做時間會提升)node
使用的是vue-cli2.9的模認模版,(vue-cli2以前的模板都仍是用了原生的webpack,如今最新的vue-cli三、vue-cli4都是用了vue團隊作的插件來佈置工做環境,有不少配置不但要懂webpack,還要去學習vue-cli了。)webpack
需求:新創建一個用於mock數據模擬的dev環境,修改build打包異步請求的地址,創建5個不一樣的打包地址,以供甲方不一樣部門的審查,而且開發環境與生產環境的NODE_ENV
值不變,還分別是development
、production
ios
項目開發完成度已接近70%,不宜修改過多的業務代碼,而且前端是多人開發,新環境應新增啓動命令,而不是用舊命令去執行新功能。程序員
項目處於一邊開發,一邊對接接口,這是因爲不少數據由甲方提供模型,再由後端同事處理返回(同時,測試也是用後端的測試數據)個別接口數據後端開發比前端快,前端用devServer,跟據返回數據再開發而無需使用mock模擬。如遇後端尚未提供接口的請況,則啓用mock模擬的環境web
npm run dev //運行普通dev環境,可用於對接現有接口 npm run dev:mock //運行專門的mock模擬環境
因爲項目常常要打包多個不一樣的axios.baseUrl地址發給不一樣的人(本公司項目負責人,甲方測試,甲方測試2,甲方的甲方服務地址(因此我實際上是乙方的乙方的乙方)共有5個地)vue-cli
分別運行不一樣的地址,打包到不一樣的文件夾。npm
npm run build //普通打包,以放代碼其餘人接手後不看文檔 npm run build:none //打包地址尋打當前服務器目錄 => '/' npm run build:193 //打包爲http://193.xxx.xx.xxx:8080/xxx/xx npm run build:192 //打包爲http://192.xxx.xx.xxx:8080/xxx/xx npm run build:113 //打包爲http://113.xxx.xx.xxx:8080/xxx/xx npm run build:10 //打包爲http://10.xxx.xx.xxx:8080/xxx/xx
而後,最後的包分別放在項目跟目錄下的: dist 、dist-none、dist-19三、dist-19二、dist-11三、dist-10
根據上一篇文章對webpack的學習( 2020年,《深刻淺出Webpack》(吳浩麟2018/01)學習總結),webpack能夠經過在package.json的script中經過命令向node環境傳遞參數,寫法:
//package.json { 」script「: { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "dev:mock": "ENV_NUM=0 npm run dev", } }
這樣,若是運行 npm run dev:mock就會將ENV-NUM的值傳給process.env,在項目中就能夠經過process.env.ENV_NUM 拿到值,爲 ’0‘;
可是webpack 的NPM.script 傳參寫法在不一樣系統上兼容不同,有可能會致使系統卡死。(我是用mac的,個人同事全是用windows,說不定給甲方的代碼也會有用lunix的大神,固然若是是用服務器打包,那是lunix多)
網友介紹了用cross-env插件來處理
安裝 npm i cross-env --save
同時package.json修改以下:
//package.json { 」script「: { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "dev:mock": "cross-env ENV_NUM=0 npm run dev", } }
在ENV_NUM=0前加多了一個cross-env
細心的我已經發現了,vue-cli的項目中,在設定webpack.config.js時,它又在代碼裏重新修改了一下process.env的值,因此在npm.script中是設定了一個ENV-NUM,可是會在接下來被配置中的設定重新賦值,從而致使在項目代碼中找不到。
plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env'),//在此對process.env進行了從新賦值 }), ... ]
因此,在config目錄下,
修改dev.env.js
,注意加多了ENV_NUM: '"1"'
'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', ENV_NUM: '"1"' })
同時,新建一個文件 dev.mock.js
,ENV_NUM的值爲'"0"'
'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', ENV_NUM: '"0"' })
再修改build/webpack.dev.conf.js
//新增env const env = process.env.ENV_NUM === '0' ? require('../config/mock.env') : require('../config/dev.env'); //plugins修改成 plugins: [ new webpack.DefinePlugin({ 'process.env': env }), //其餘不變 ...
在axios
的url處設定爲一個數組,而且數組的第一個元素爲mock接口,用於dev:mock。第二個元素爲真實後臺接口,用於dev和build
例:
axios.request({ // /mock/user 用於模擬 url: ['/mock/user','/user'], })
同時,在axios的請求攔截處區分傳入的url
// src/libs/axios.js //請求攔截 service.interceptors.request.use( config => { let url = getNowUrl(config.url); config.url = url; return config; }, error => { console.log(error); return Promise.reject(error) } ); //src/libs/utils.js export const getNowUrl = (url) => { let num; //0使用數據模擬,1不使用數據模擬 num = process.env.ENV_NUM; if(Array.isArray(url)){ if(url.length === 1){ num = "0"; } return url[num]; }else{ return url; } }
這樣,當咱們運行npm run dev:mock時,它會請求URL數組中的第一個,而運行npm run dev或npm run build時,就會請求第二個,而且當url不是數組或數組只有一個元素,都能打到可用的地址。
按照development的方法只要給process.env加入多一個參數就能夠在項目中區分不一樣的地址了。可是因爲build只是改了打包地址而且地址有不少個,若是每一個地址再新建一個prod.env.js文件,大量的重複代碼會讓項目顯得臃腫。
因而我想到,在webpack修改process.env以後,再將參數注入process.env中
根據設計,只須要修改process.env 和打包後輸出文件夾,再在代碼中跟據process.env中約定的字段的不一樣值來選擇不一樣的baseUrl。
先來看看vue-cli的默認配置:
baseUrl地址寫在:src/config/index.js
baseUrl: { dev: '', pro: 'http://193.xxx.xx.xxx:8080/',//生產環境的地址 test: '', }
在axios的配置文件中選擇
//src/libs/axois.js const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro const service = axios.create({ baseURL: baseUrl, timeout: 10000, })
修改開始:
package.json
中加入BASE_URL,值爲數字形式
{ "scripts": { ... "dev:mock": "cross-env ENV_NUM=0 npm run dev", "build:none": "cross-env BASE_URL=0 npm run build", "build:193": "cross-env BASE_URL=1 npm run build", "build:113": "cross-env BASE_URL=2 npm run build", "build:192": "cross-env BASE_URL=3 npm run build", "build:10": "cross-env BASE_URL=4 npm run build" } }
src/config/index.js
加入一個屬性prodUrl爲數組
baseUrl: { dev: '', pro: 'http://193.xxx.xx.xxx:8080/', test: '', prodUrl:[ '/', 'http://193.xxx.xx.xxx:8080/', 'http://113.xxx.xxx.xxx:8082/xxxx/xxx/', 'http://192.xxx.xx.xxx:8082/xxxx/xxx/', 'http://10.xx.xxx.xxx:8082/xxxx/xxx/', ] },
修改webpack的production配置
//build/webpack.prod.conf.js const env = process.env.NODE_ENV === 'testing' ? require('../config/test.env') : require('../config/prod.env'); //paths let assetsRoot = ''; //新增 let htmlIndex = '/index.html'; //新增 //新增 console.log('env',env) if(env.NODE_ENV === '"production"'){//注意,此處有兩個引號 env.BASE_URL = utils.findBaseUrl(); assetsRoot = utils.findPaths(); htmlIndex = assetsRoot + htmlIndex; } console.log('env2',env); console.log('assetroot',assetsRoot); console.log('htmlIndex',htmlIndex); ... plugins: [ new webpack.DefinePlugin({ 'process.env': env }), ... //修改這個對象的配置 new HtmlWebpackPlugin({ filename: process.env.NODE_ENV === 'testing' ? 'index.html' : (assetsRoot ? path.resolve(__dirname,htmlIndex) : config.build.index), template: 'index.html', inject: true, ... } ... ] // build/utils.js 導出以下兩個函數 exports.findBaseUrl = function(){ let baseUrlNum = "-1"; if(process.env.BASE_URL){ baseUrlNum = process.env.BASE_URL; }; return baseUrlNum; } exports.findPaths = function(){ let path = '../dist'; if(process.env.BASE_URL){ switch(process.env.BASE_URL) { case '0': path = '../dist-none'; break; case '1': path = '../dist-193'; break; case '2': path = '../dist-113'; break; case '3': path = '../dist-192'; break; case '4': path = '../dist-10'; break; default: path = '../dist'; break; } }; return path; }
上面的方法修改了webpack打包後輸出的地址,避免了不一樣的地址全都輸出在dist文件夾。
接下來修改axios的baseURL
// src/libs/axios.js import { getNowUrl, findBaseUrl } from './util'; const service = axios.create({ baseURL: findBaseUrl(), timeout: 10000, })
// src/libs/utils.js export function findBaseUrl(){ let baseUrl = '/'; if(process.env.NODE_ENV === 'development'){ baseUrl = config.baseUrl.dev; }else{ if(process.env.BASE_URL){ baseUrl = process.env.BASE_URL === '-1' ? config.baseUrl.pro : config.baseUrl.prodUrl[process.env.BASE_URL]; }else{ baseUrl = config.baseUrl.pro } }; return baseUrl; };
OK完成!
在控制檯輸入npm run build:none
試一下:
打印的路徑都正常了!
再看看最後輸出
以上兩種環境的配置都沒有改變默認的開發方式,不影響其餘開發人員。此次的修改也是在新型肺炎多出的假期中。
找了好久的資料,都沒有找到很符合的案例,網上大可能是加多一個test環境,因此只能本身多多學習,看完了一本webpack的書,再結合項目慢慢摸索出來的。在這期間也踩過不少的坑,同時也但願能幫到你們。
我想,大部分的軟件開發者都是在一線城市工做吧!一線城市的人員都來自四面八方,正式回崗復工後但願你們都能當心點,同時2月3號至2月9號在家上班的這幾天的工資都能拿到。
若是你以爲有什麼更好的方法,也能夠評論討論。如查你以爲有用,給我一個當心心吧。