前言
這篇文章主要介紹uniapp
在Hbuilderx
中,通過工程化,區(qū)分不同環(huán)境、動態(tài)修改小程序appid
以及自定義條件編譯,解決代碼發(fā)布
和運行時
手動切換到問題。
背景
在企業(yè)級的應用中,通常會分為,開發(fā)、聯調、生產等多個環(huán)境,一個項目可能要發(fā)布到多個微信小程序,在工程化中,通過使用不同的打包命令設置不同的環(huán)境變量,解決不同環(huán)境各變量的內容需手動修改的問題,比如:接口、前綴、appid
等;在使用uniapp開發(fā)項目時,通常使用Hbuilder
可視化運行項目,點擊運行編譯出來都代碼環(huán)境是(development)
,點擊發(fā)布運行編譯出來的代碼是(production)
,分別對應開發(fā)和生產,使用process.env.NODE_ENV
來獲取運行環(huán)境。但是在很多企業(yè)項目中,就兩個環(huán)境,很難滿足使用場景。
為了解決以上問題,通過在package.json
中增加增加 uni-app節(jié)點
,自定義條件編譯和環(huán)境,通過modifyManifest.js
重寫appid
,擴展vue.config.js
配置,用環(huán)境標識區(qū)分接口
一、自定義條件編譯
以微信小程序為例,在做條件編譯時候,只有一種判斷條件
<!-- #ifdef MP-WEIXIN -->
<view>我是微信</view>
<!-- #endif -->
<!-- #ifdef H5 -->
<view>我是后</view>
<!-- #endif -->
但實際情況是,我們有兩個微信主體,希望在不同主體展示不同信息:
<!-- #ifdef MP-CJN -->
<view>我是CJN</view>
<!-- #endif -->
<!-- #ifdef MP-YYT -->
<view>我是YYT</view>
<!-- #endif -->
在package.json
中新增uni-app
官網自定義配置;
實際使用時,刪除掉文件中所有的注釋信息,否則編譯時會報錯。
{
"uni-app": {
"scripts": {
"cjnDev": {
"title":"小程序1-聯調環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "cjnDev"
},
"define": {
"MP-CJN": true
}
},
"cjnTest": {
"title":"小程序1-測試環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "cjnTest"
},
"define": {
"MP-CJN": true
}
},
"cjnProd": {
"title":"小程序1-生產環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "cjnProd"
},
"define": {
"MP-CJN": true
}
},
"yytDev": {
"title":"小程序2-聯調環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "yytDev"
},
"define": {
"MP-YYT": true
}
},
"yytTest": {
"title":"小程序2-測試環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "yytTest"
},
"define": {
"MP-YYT": true
}
},
"yytProd": {
"title":"小程序2-生產環(huán)境",
"env": {
"UNI_PLATFORM": "mp-weixin",
"NAME": "yytProd"
},
"define": {
"MP-YYT": true
}
}
}
}
}
注意:盡量保證yytProd和NAME值保持一致
以上代碼以微信小程序在不同主體的展示為例,分別為小程序1(MP-CJN)、小程序2(MP-YYT)
,同時區(qū)分了三個環(huán)境,聯調、測試和生產,配置好以后,我們在Hbuilder中點擊運行和發(fā)行可以看到下面效果
這時就可以使用<!-- #ifdef MP-YYT -->
來實現在微信平臺,區(qū)分不同主體的條件編譯,通過環(huán)境變量process.env.NAME
取得配置文件中NAME
的信息
二、配置其他變量
創(chuàng)建`env.js`,存放相關環(huán)境變量的信息;我是在common中創(chuàng)建的,可以根據自己項目實際情況選擇目錄
module.exports = {
// 小程序1聯調環(huán)境
cjnDev: {
requestUrl: 'https://mp.com',
appid: '小程序appid'
},
// 小程序1測試環(huán)境
cjnTest: {
requestUrl: '接口地址',
appid: '小程序appid'
},
// 小程序1線上環(huán)境
cjnProd: {
requestUrl: '接口地址',
appid: '小程序appid'
}
// 小程序2聯調環(huán)境
yytDev: {
requestUrl: '接口地址',
appid: '小程序appid'
},
// 小程序2測試環(huán)境
yytTest: {
requestUrl: '接口地址',
appid: '小程序appid'
},
// 小程序2線上環(huán)境
yytProd: {
requestUrl: '接口地址',
appid: '小程序appid'
}
}
其中變量名 cjnDev
、cjnTest
、cjnProd
等要跟package.json
中的NAME
一致,方便后續(xù)通過變量名取值。
在根目錄下創(chuàng)建vue.config.js
let configUrl = require('./common/env.js');
// 動態(tài)修改appid,調試環(huán)境時,可以先注釋掉
require('./src/modifyManifest.js');
module.exports = {
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
args[0]['process.env.config'] = JSON.stringify(configUrl)
return args
})
}
}
通過定義一個全局的變量process.env.config
存儲的就是env.js
中的全部變量信息,此時就可以直接獲取到當前運行所對應的配置信息
// 運行小程序1-聯調環(huán)境 獲得:https://mp.com
le url = process.env.config[process.env.NAME].requestUrl
動態(tài)修appid
appid
在項目根目錄的manifest.json
內,動態(tài)修改邏輯是使用nodejs
的fs
模塊,通過方法readFileSync
讀取文件,然后跟進當前環(huán)境對內容進行修改,最后通過writeFileSync
寫入到manifest.json
中
在src
目錄下創(chuàng)建modifyManifest.js
,劃重點:一定得是在src目錄下
let configUrl = require('../common/env.js');
const fs = require('fs');
// 讀取 manifest.json
const manifestPath = `${process.env.UNI_INPUT_DIR}/manifest.json`
let Manifest = fs.readFileSync(manifestPath, { encoding: 'utf-8' })
/**
* 替換 manifest.json 文件內容
* @param {String} path 目標元素的鍵
* @param {String} value 目標元素的值
*/
function replaceManifest(path, value) {
const arr = path.split('.')
const len = arr.length
const lastItem = arr[len - 1]
let i = 0
let ManifestArr = Manifest.split(/\n/)
for (let index = 0; index < ManifestArr.length; index++) {
const item = ManifestArr[index]
if (new RegExp(`"${arr[i]}"`).test(item)) ++i;
if (i === len) {
const hasComma = /,/.test(item)
ManifestArr[index] = item.replace(new RegExp(`"${lastItem}"[\\s\\S]*:[\\s\\S]*`), `"${lastItem}": ${typeof value === 'string'? '"'+value+'"' : value}${hasComma ? ',' : ''}`)
break;
}
}
Manifest = ManifestArr.join('\n')
}
// 替換appid
const appid = configUrl[process.env.UNI_SCRIPT].appid;
replaceManifest('mp-weixin.appid', appid);
// 文件輸出
fs.writeFileSync(manifestPath, Manifest, {
"flag": "w"
})
關于環(huán)境變量,此時獲取不到process.env.NAME
,通過打印可以看到process.env.UNI_SCRIPT
與NAME的值一致,這也是為什么我們前面強調:‘盡量保證yytProd
和NAME
值保持一致’的原因。
三、使用方式
1. 本地調試運行:Hbuilder->運行,選擇對應的自定義環(huán)境執(zhí)行
2. 上線發(fā)布:Hbuilder->發(fā)行->自定義發(fā)行,選擇對應的自定義環(huán)境執(zhí)行
3. 業(yè)務開發(fā)通過`process.env.config[process.env.NAME]`獲取對應環(huán)境的變量對象