uniapp多地區(qū)、多平臺、多環(huán)境打包具體代碼與配置說明
前言:
本文基于真實的線上項目,介紹如何用一套代碼支持多個地區(qū)、多種平臺(微信/支付寶小程序、H5 等)、多種部署環(huán)境(開發(fā)/測試/生產(chǎn))的構建與打包,并給出具體代碼與配置說明。
開始之前,大家先想象這樣一個場景:同一套業(yè)務,要同時給 A 省、B 省、C 省上線微信小程序和支付寶小程序,每個省的標題、首頁內(nèi)容、支付方式、后端網(wǎng)關地址都不一樣,還要區(qū)分 dev / qa / prod 多套環(huán)境。如果每一套都復制一份代碼維護,成本會很快失控。那么我這篇文章講的,就是怎樣通過「一套代碼 + 一組腳本」把這些組合全部收攏起來,統(tǒng)一維護。
一、需求與目標
| 維度 | 說明 | 示例 |
|---|---|---|
| 地區(qū)(DISTRICT) | 不同省份/地區(qū),不同應用標題、頁面配置、manifest | 新疆、安徽、江蘇、吉林… |
| 平臺(UNI_PLATFORM) | 不同運行端 | 微信小程序 mp-weixin、支付寶 mp-alipay、H5 |
| 環(huán)境(DEPLOY) | 不同 API 與部署目標 | dev、qa02、release_anhui、xinjiang_prod… |
目標:通過一條 npm 腳本即可確定「地區(qū) + 平臺 + 環(huán)境」,打出對應產(chǎn)物,無需改代碼。
二、整體思路
npm script (cross-env 注入環(huán)境變量)
↓
process.env.UNI_PLATFORM / DISTRICT / DEPLOY / NODE_ENV
↓
vue.config.js 加載時先執(zhí)行 preBuild.js(類似于webpack自定義plugin的效果)
↓
preBuild.js 根據(jù)上述變量生成 CLIENT_TYPE、APP_TITLE、API_BASE_URL 等
↓
動態(tài)生成 pages.json、manifest.json(按地區(qū)合并)
↓
Webpack 通過 EnvironmentPlugin 將變量注入業(yè)務代碼
↓
構建產(chǎn)物中 process.env.XXX 被替換為常量
核心有以下三點:
- 環(huán)境變量驅動:用
UNI_PLATFORM、DISTRICT、DEPLOY等控制整條構建鏈。 - 構建前預處理:在 Webpack 之前跑
preBuild.js,統(tǒng)一把「平臺/地區(qū)/環(huán)境」轉成業(yè)務需要的CLIENT_TYPE、API_BASE_URL、APP_TITLE等。 - 配置與代碼注入:用 Webpack 官方
EnvironmentPlugin把process.env中的鍵注入到前端代碼,保證運行時代碼能拿到當前構建的「地區(qū)/平臺/環(huán)境」。
三、具體實現(xiàn)步驟與代碼說明
3.1 用 cross-env 在 npm script 中傳參
不同操作系統(tǒng)下設置環(huán)境變量方式不同,使用 cross-env 可統(tǒng)一寫法。
安裝:
npm i -D cross-env
package.json 中的腳本示例:
{
"scripts": {
"build:mp-weixin:anhui:release_anhui": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin DISTRICT=anhui DEPLOY=release_anhui vue-cli-service uni-build",
"dev:mp-weixin:anhui:release_anhui": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin DISTRICT=anhui DEPLOY=dev_anhui vue-cli-service uni-build --watch"
}
}
含義簡述:
cross-env KEY=value會在當前 Node 進程中設置process.env.KEY = value。- 后面執(zhí)行的
vue-cli-service uni-build與它加載的vue.config.js、preBuild.js都運行在同一進程,因此能直接讀到這些環(huán)境變量。 - 命名約定:
dev/build+平臺+地區(qū)+環(huán)境,便于一眼看出打的是哪一套。
關于 --watch:
- 開發(fā)腳本(如
dev:mp-weixin:...)末尾加上--watch,表示 開啟監(jiān)聽模式:當代碼或配置文件變更時,會自動重新編譯對應平臺/地區(qū)/環(huán)境的產(chǎn)物,無需每次手動重新執(zhí)行命令,適合本地聯(lián)調(diào)和反復修改。
常見變量:
| 變量 | 含義 | 示例 |
|---|---|---|
NODE_ENV | 開發(fā)/生產(chǎn) | development / production |
UNI_PLATFORM | 平臺 | mp-weixin、mp-alipay、h5 |
DISTRICT | 地區(qū) | anhui、xinjiang、jiangsu |
DEPLOY | 部署環(huán)境 | dev、qa、release_anhui |
CUSTOM_TAB | 可選,自定義 tab 配置 | 如 pay、order_search |
3.2 統(tǒng)一配置:preBuild.config.js
把「平臺 → 客戶端類型」「地區(qū) → 應用標題」「部署環(huán)境 → API 地址」等做成映射表,便于維護和擴展。
config/preBuild.config.js:
// 平臺與客戶端類型(用于接口等)
const CLIENT_TYPE_MAP = {
h5: 1,
'mp-weixin':2,
'mp-alipay':3,
'mp-baidu': 4,
'mp-toutiao': 5,
'mp-qq': 6
}
// 地區(qū)與應用標題等展示配置
const DISTRICT_CONFIG_MAP = {
jilin: { APP_TITLE: 'xxx' },
xinjiang: { APP_TITLE: 'xxx' },
// ... 其他地區(qū)
}
// 部署環(huán)境與 API 根地址(示例域名為占位)
const API_BASE_URL_MAP = {
dev: 'https://api-dev.example.com/mobile-app/api',
qa: 'https://api-qa02.example.com/mobile-app/api',
release_regionA: 'https://api-release-regionA.example.com/mobile-app/api',
// ... 其他環(huán)境
}
module.exports = {
CLIENT_TYPE_MAP,
DISTRICT_CONFIG_MAP,
API_BASE_URL_MAP
}
后續(xù)新增地區(qū)或環(huán)境時,只需在此處增補配置,無需改構建腳本邏輯。
3.3 構建前預處理:preBuild.js
在 Webpack 讀取 vue.config.js 之前,需要把「平臺/地區(qū)/環(huán)境」轉成業(yè)務和配置生成器使用的變量。因此把 preBuild.js 放在 vue.config.js 最前面執(zhí)行。
build/preBuild.js:
/**
* 設置自定義的 process.env.X 需同時在 vue.config.js 的
* configureWebpack.plugins 里加入 EnvironmentPlugin 對應 key
*/
const { CLIENT_TYPE_MAP, DISTRICT_CONFIG_MAP, API_BASE_URL_MAP } = require('../config/preBuild.config')
// 版本號等固定值(示例)
process.env.VERSION = '1.0.0'
// 由「平臺」得到客戶端類型
process.env.CLIENT_TYPE = CLIENT_TYPE_MAP[process.env.UNI_PLATFORM]
// 由「地區(qū)」得到應用標題(缺省用 jilin)
process.env.APP_TITLE = DISTRICT_CONFIG_MAP[process.env.DISTRICT || 'xuzhou'].APP_TITLE
// 由「部署環(huán)境」得到 API 根地址(缺省用 dev)
process.env.API_BASE_URL = API_BASE_URL_MAP[process.env.DEPLOY || 'dev']
// 可選:自定義 tab 等,未傳則空字符串
process.env.CUSTOM_TAB = process.env.CUSTOM_TAB || ''
// 便于排查:構建時打印當前維度
console.log('------------------------------')
console.log('NODE_ENV:', process.env.NODE_ENV)
console.log('DEPLOY:', process.env.DEPLOY)
console.log('UNI_PLATFORM:', process.env.UNI_PLATFORM)
console.log('DISTRICT:', process.env.DISTRICT)
console.log('CLIENT_TYPE:', process.env.CLIENT_TYPE)
console.log('API_BASE_URL:', process.env.API_BASE_URL)
console.log('------------------------------')
// 根據(jù) DISTRICT 等動態(tài)生成 pages.json、manifest.json
require('./pages.json.js')
require('./manifest.json.js')
要點:
- 只讀不寫:從
process.env讀取由 cross-env 注入的UNI_PLATFORM、DISTRICT、DEPLOY。 - 派生變量:寫入
CLIENT_TYPE、APP_TITLE、API_BASE_URL、CUSTOM_TAB等,供后續(xù) Webpack 和動態(tài)配置使用。 - 執(zhí)行順序:本文件在
vue.config.js的頂部被require,因此先于 Webpack 配置執(zhí)行;下面的pages.json.js、manifest.json.js會用到當前的process.env.DISTRICT等。
3.4 在 vue.config.js 中接入 preBuild 與 EnvironmentPlugin
vue.config.js:
const webpack = require('webpack')
const path = require('path')
// 必須最先執(zhí)行:注入 CLIENT_TYPE、API_BASE_URL 等,并生成 pages.json / manifest.json
require('./build/preBuild.js')
module.exports = {
configureWebpack: {
resolve: {
alias: {
// 按地區(qū)做目錄別名,業(yè)務里 import 來自 @district 即當前地區(qū)配置
'@district': path.join(__dirname, 'src/district', process.env.DISTRICT)
}
},
plugins: [
// 將 process.env 中列出的 key 在編譯時注入到業(yè)務代碼中
// 業(yè)務代碼中 process.env.UNI_PLATFORM 等會被替換為構建時的常量
new webpack.EnvironmentPlugin([
'UNI_PLATFORM',
'CLIENT_TYPE',
'VERSION',
'DISTRICT',
'API_BASE_URL',
'CUSTOM_TAB'
])
]
}
}
說明:
require('./build/preBuild.js'):保證在任何 webpack 配置使用process.env.DISTRICT、process.env.API_BASE_URL等之前,這些變量就已經(jīng)就緒。@district別名:指向src/district/${DISTRICT},便于按地區(qū)維護配置(如src/district/anhui/config.js),業(yè)務側統(tǒng)一從@district引用。- EnvironmentPlugin:Webpack 內(nèi)置插件,會把數(shù)組中列出的
process.env.XXX在編譯時替換為當前構建時的值,因此業(yè)務里寫process.env.UNI_PLATFORM、process.env.DISTRICT、process.env.API_BASE_URL等即可,無需再傳參。
3.5 按地區(qū)動態(tài)生成 pages.json(build/pages.json.js)
不同地區(qū)可能需要不同的頁面列表、tabBar 等,因此把「基礎配置」與「地區(qū)配置」合并后再寫入 src/pages.json。
build/pages.json.js:
const fs = require('fs')
const path = require('path')
const lodash = require('lodash')
const standardPages = require('../config/pages.js')
let districtPage = {}
let customPages = []
const district = process.env.DISTRICT
// 若存在該地區(qū)的 pages 配置則合并
try {
districtPage = require(`../config/districts/${district}/pages.js`)
} catch (e) {
console.log(`不存在【${district}】地區(qū)差異化 page.js,略過`)
}
// 若有 CUSTOM_TAB,可再合并 custom.xxx.pages.js
process.env.CUSTOM_TAB.split(',').forEach((type) => {
// ... 按 type 加載 config/custom.${type}.pages.js 與 config/districts/${district}/ 下同名文件
})
const pageJSON = lodash.mergeWith({}, standardPages, districtPage, ...customPages, (objValue, srcValue, key) => {
if (Array.isArray(objValue) && key === 'list') {
return srcValue // 如 tabBar.list 用地區(qū)配置覆蓋,而不是數(shù)組合并
}
})
fs.writeFileSync(path.join(__dirname, '../src/pages.json'), JSON.stringify(pageJSON, null, 2), { encoding: 'utf8' })
console.log('page.json 構建完成')
思路:對基礎 pages + 地區(qū) pages + 自定義 tab 配置 做 merge,對 list 類數(shù)組采用覆蓋策略,避免 tab 等被意外合并。
3.6 按地區(qū)動態(tài)生成 manifest.json(build/manifest.json.js)
小程序與 H5 的 appid、描述等可能按地區(qū)不同,同樣采用「標準 manifest + 地區(qū) manifest」合并。
build/manifest.json.js:
const fs = require('fs')
const path = require('path')
const lodash = require('lodash')
const standardManifest = {
name: 'app',
appid: 'xxx',
'mp-weixin': { /* ... */ },
'mp-alipay': { /* ... */ }
// ...
}
let districtManifest = {}
try {
districtManifest = require(`../config/districts/${process.env.DISTRICT}/manifest.json.js`)
} catch (e) {
console.log('該地區(qū)不存在差異化 manifest.json.js')
}
const merged = lodash.merge({}, standardManifest, districtManifest)
fs.writeFileSync(path.join(__dirname, '../src/manifest.json'), JSON.stringify(merged, null, 4), { encoding: 'utf8' })
console.log('manifest.json 生成完成')
地區(qū)目錄示例:config/districts/anhui/manifest.json.js、config/districts/xinjiang/pages.js 等,按需添加。
3.7 業(yè)務代碼中如何使用
構建時環(huán)境變量已被注入,業(yè)務中直接讀 process.env 即可。
按平臺分支:
// 例如僅微信小程序展示某模塊
if (process.env.UNI_PLATFORM === 'mp-weixin') {
// 微信邏輯
}
// 計算屬性中
moreModuleGroups: vm => process.env.UNI_PLATFORM === 'mp-weixin'
? xxxx
: xxxx
按地區(qū)使用配置:
// 使用別名 @district,實際指向 src/district/${DISTRICT}
import banner from '@district/banner.jpg'
// 或直接使用注入的常量
const district = process.env.DISTRICT
const apiBase = process.env.API_BASE_URL
請求 API:
// 封裝請求時用 process.env.API_BASE_URL 作為 baseURL
axios.create({ baseURL: process.env.API_BASE_URL })
四、目錄與腳本約定小結
| 角色 | 路徑/命令 | 作用 |
|---|---|---|
| 環(huán)境變量注入 | cross-env UNI_PLATFORM=... DISTRICT=... DEPLOY=... | 在 npm script 中傳入維度 |
| 映射配置 | config/preBuild.config.js | 平臺/地區(qū)/環(huán)境 → 客戶端類型、標題、API |
| 構建前邏輯 | build/preBuild.js | 設置 CLIENT_TYPE、API_BASE_URL 等并生成 pages/manifest |
| Webpack 入口 | vue.config.js | require preBuild、配置 @district、EnvironmentPlugin |
| 動態(tài)頁面配置 | build/pages.json.js | 合并基礎 + 地區(qū) pages,寫回 src/pages.json |
| 動態(tài) manifest | build/manifest.json.js | 合并基礎 + 地區(qū) manifest,寫回 src/manifest.json |
| 地區(qū)前端配置 | src/district/<DISTRICT>/config.js | 業(yè)務通過 @district 引用 |
| 地區(qū)構建配置 | config/districts/<DISTRICT>/pages.js、manifest.json.js | 僅該地區(qū)生效的頁面與 manifest |
五、新增地區(qū)/環(huán)境/平臺時的操作清單
新增地區(qū)
- 在
config/preBuild.config.js的DISTRICT_CONFIG_MAP中增加APP_TITLE等。 - 如需差異化頁面:在
config/districts/<新地區(qū)>/下增加pages.js。 - 如需差異化 manifest:在
config/districts/<新地區(qū)>/下增加manifest.json.js。 - 在
src/district/下新增同名目錄及config.js(可參考現(xiàn)有地區(qū))。
- 在
新增部署環(huán)境
- 在
config/preBuild.config.js的API_BASE_URL_MAP中增加DEPLOY→ API 地址。 - 在
package.json的 scripts 中增加對應dev/build:平臺:地區(qū):環(huán)境命令。
- 在
新增平臺
- 在
CLIENT_TYPE_MAP中增加平臺與客戶端類型。 - 若 uniapp 支持該平臺,只需在 script 中增加
UNI_PLATFORM=新平臺的 dev/build 腳本即可。
- 在
六、注意事項
- EnvironmentPlugin 與 preBuild 一致:凡在
preBuild.js里新加的process.env.XXX,若要在業(yè)務代碼中使用,需在vue.config.js的EnvironmentPlugin數(shù)組中增加'XXX'。 - DISTRICT / DEPLOY 默認值:preBuild 中使用了
process.env.DISTRICT || 'xuzhou'、process.env.DEPLOY || 'dev',未傳時會有默認地區(qū)與環(huán)境,可按需修改。 - 跨平臺兼容:使用
cross-env可避免在 Windows 與 Mac/Linux 下環(huán)境變量寫法不一致的問題。
按上述方案,即可用「地區(qū) + 平臺 + 環(huán)境」三維度通過一條命令完成打包,并實現(xiàn)配置集中、擴展清晰,歡迎大家學習指正!
到此這篇關于uniapp多地區(qū)、多平臺、多環(huán)境打包具體代碼與配置說明的文章就介紹到這了,更多相關uniapp多地區(qū)、多平臺、多環(huán)境打包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
在VUE中使用lodash的debounce和throttle操作
這篇文章主要介紹了在VUE中使用lodash的debounce和throttle操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
vue elementUI使用tabs與導航欄聯(lián)動
這篇文章主要為大家詳細介紹了vue elementUI使用tabs與導航欄聯(lián)動,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-06-06
vue-router實現(xiàn)組件間的跳轉(參數(shù)傳遞)
這篇文章主要為大家詳細介紹了vue-router實現(xiàn)組件間的跳轉,參數(shù)傳遞方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11

