一鍵多環境構建——用 Hvigor 玩轉 HarmonyOS Next

引言

在 HarmonyOS Next 的應用開發中,常常需要針對不同環境(測試、預發、線上)或不同簽名(調試、正式)輸出多個 APP/HAP 包。雖然 HarmonyOS 提供了多目標構建(Multi-Target Build)能力,可以在同一項目里配置多個 product 并生成不同包名的多個產物,但某些深度定制(如動態修改 module.json5 中的 client_idapp_id,或基于構建時間改寫輸出包名)仍需借助自定義 Hvigor 插件來完成。

結合示例項目,演示如何通過 Hvigor 插件配合多目標構建,實現:

  1. 統一管理各環境的 API 地址、埋點地址等配置;
  2. 動態注入 clientIdappId 等應用信息;
  3. 基于構建時間和 product 名稱,定制化輸出包名,便于后續上架和線上排查。

一、在項目中使用 Hvigor 自定義插件

1. Hvigor 插件的入口

在 HarmonyOS 項目根目錄存在入口文件 hvigorfile.ts,將自定義 task 注冊到 plugins 中:

// 文件:hvigorfile.ts
import { buildSchemaProcessing } from './scripts/build-schema-processing';export default {system: appTasks,             // Hvigor 內置任務,不可修改plugins: [buildSchemaProcessing()     // 自定義插件:動態修改 module.json5、build-profile.json5 等]
};

點擊 DevEco Studio 上方的 Sync Now 或執行 hvigor sync,即可將插件加載到構建流程中。


2. Hvigor 常用 API 概覽

在自定義插件代碼中,我們通常會用到以下核心 API:

  • hvigor.getRootNode():獲取根節點,進而拿到各插件上下文
  • rootNode.getContext(pluginId):獲取指定插件的上下文對象,例如 OHOS_APP_PLUGINOHOS_HAP_PLUGIN
  • context.getAppJsonOpt() / getModuleJsonOpt():讀取 app.json5module.json5 的 AST 對象
  • context.getBuildProfileOpt():讀取根目錄 build-profile.json5 的 AST 對象
  • context.setAppJsonOpt() / setBuildProfileOpt():將修改后的 AST 寫回,生效于后續構建
// 示例:讀取上下文
const root = hvigor.getRootNode();
const appCtx = root.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;
const hapCtx = root.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosAppContext;
const appJson = appCtx.getAppJsonOpt();
const modJson = hapCtx.getModuleJsonOpt();
const buildProfile = appCtx.getBuildProfileOpt();// 修改后需要重新 set 回去
appCtx.setAppJsonOpt(appJson);
appCtx.setBuildProfileOpt(buildProfile);

在這里插入圖片描述


二、結合多目標構建與自定義插件 實現環境切換

1. 規范 Product 命名

為了腳本中便于解析,我們約定 productname 采用下劃線分隔、固定格式:

<應用標識>_<簽名標識>_<環境標識>
例如:demo1_debug_test、demo1_release_preRelease、demo2_debug_official

build-profile.json5 中配置多個 product:

"products": [{"name": "demo1_debug_test","signingConfig": "debug","buildOption": {"arkOptions": {"buildProfileFields": {"productsName": "demo1","buildTime": "","apiUrl": "","trackApiUrl": ""}}}},{"name": "demo1_release_officiallyReleased","signingConfig": "release","buildOption": { /* 同上 */ }},/* 更多 product 配置… */
]

TipbuildProfileFields 下的字段會被注入到應用運行時,便于在代碼中讀取環境信息。


2. 本地配置文件:config.json

將各環境的 API 地址,以及各應用的 clientId/appId 信息集中管理:

{"environmentInfo": {"test": {"apiUrl": "https://api.test.com","trackApiUrl": "https://stat.test.com"},"preRelease": {"apiUrl": "https://api-pre.example.com","trackApiUrl": "https://stat-pre.example.com"},"officiallyReleased": {"apiUrl": "https://api.prod.com","trackApiUrl": "https://stat.prod.com"}},"appConfigInfo": {"demo1": {"clientId": "111898773","appId": "5765880207855284373"},"demo2": {"clientId": "6917571239128090930","appId": "6917571239128090930"}}
}

并提供兩個輔助函數,在插件中使用:

// scripts/config.ts
import cfgRaw from '../config.json';
import { format } from 'date-fns';export function formatBuildTime(date = new Date()): string {const pad = (n: number) => String(n).padStart(2, '0');return `${date.getFullYear()}-${pad(date.getMonth()+1)}-${pad(date.getDate())}`+ `_${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
}export function getLocalConfig() {const cfg = JSON.parse(JSON.stringify(cfgRaw));cfg.buildTime = formatBuildTime();return cfg;
}

3. 插件實現核心邏輯

build-schema-processing.ts 中,利用 Hvigor 生命周期鉤子完成配置注入與產物重命名。

// scripts/build-schema-processing.ts
import { getLocalConfig } from './config';export function buildSchemaProcessing() {const localCfg = getLocalConfig();let currentProduct = '', versionName = '', bundleName = '', appConfig: any;return {pluginId: 'custom-build-processor',apply(hvigor) {hvigor.getRootNode().afterNodeEvaluate(root => {// 獲取上下文const appCtx = root.getContext(OhosPluginId.OHOS_APP_PLUGIN) as OhosAppContext;const hapCtx = root.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosAppContext;const buildProfile = appCtx.getBuildProfileOpt();const appJson = appCtx.getAppJsonOpt();const modJson = hapCtx.getModuleJsonOpt();// 當前 product 信息currentProduct = appCtx.getCurrentProduct().getProductName() || '';versionName = appJson.app.versionName;const productKeys = currentProduct.split('_');const appKey = productKeys[0];const envKey = productKeys[2];appConfig = localCfg.appConfigInfo[appKey];const envConfig = localCfg.environmentInfo[envKey];// 注入 app.json5 中的 clientId、appIdif (modJson) {modJson['module']['appId'] = appConfig.appId;modJson['module']['clientId'] = appConfig.clientId;hapCtx.setModuleJsonOpt(modJson);}// 遍歷各 product,注入環境 & 時間 & 重命名 artifact(buildProfile.app.products || []).forEach((prd: any) => {prd.buildOption.arkOptions.buildProfileFields.buildTime  = localCfg.buildTime;prd.buildOption.arkOptions.buildProfileFields.apiUrl     = envConfig.apiUrl;prd.buildOption.arkOptions.buildProfileFields.trackApiUrl= envConfig.trackApiUrl;const suffix = `${appKey}_${versionName}_${localCfg.buildTime}`;if (prd.name === currentProduct) {bundleName = prd.bundleName || appJson.app.bundleName;}prd.output.artifactName = `AtomicPlatform-${suffix}`;});appCtx.setBuildProfileOpt(buildProfile);});hvigor.buildFinished(() => {console.log(`📅 構建時間: ${localCfg.buildTime}`);console.log(`📦 當前產物: ${currentProduct}`);console.log(`🔖 包名(bundleName): ${bundleName}`);console.log(`🆔 ClientID: ${appConfig.clientId}`);console.log(`🆔 AppID: ${appConfig.appId}`);});}};
}

在這里插入圖片描述


三、運行效果與日志驗證

執行 hvigor build,在日志中即可看到注入與重命名結果:

====================== 編譯包信息 ======================
📅 構建時間:  2025-04-24_09-32-05
📦 當前產物: demo2_debug_test
🔖 包名: com.atomicservice.6917571239128090930
🆔 ClientID: 6917571239128090930
🆔 AppID: 6917571239128090930
====================================================

同時,輸出的 HAP 包會命名為:

AtomicPlatform-demo2_1.0.0_2025-04-24_09-32-05.hap

通過上述方式,每次在不同 product 與環境下編譯,都能自動完成配置注入與產物重命名,極大提升了多環境多簽名的開發與發布效率。


四、總結

  • 統一管理:將環境信息、應用信息集中在 config.json,便于維護與擴展;
  • 自動注入:借助 Hvigor 插件,在構建階段動態修改 module.json5build-profile.json5,免去手動切換;
  • 定制產物:基于構建時間與 product 名稱,自定義輸出包名,方便版本追蹤與線上排查。

未來可在插件中進一步添加:

  1. 構建報告自動上傳到 CI/CD 平臺;
  2. 自動生成構建差異對比的 HTML 報告;
  3. 與 Git 提交、發布流程集成,構建完成自動觸發審核或推送。

五、源碼倉庫

倉庫分支參考:feature/hvigorfileBuild

倉庫地址:MultiBuildDemo: 構建多目標產物 - Gitee.com

六、參考文檔

擴展構建-編譯構建-DevEco Studio - 華為HarmonyOS開發者

HarmonyOS Next 編譯之如何構建不同包名應用在日常的開發中涉及到多簽名和多產物構建輸出時手動切換簽名文件和包 - 掘金

HarmonyOS多環境+多渠道+自定義路徑輸出+自定義名稱一鍵打app和hap包前言 做移動端開發時,不可避免的會遇到 - 掘金
sumer/cn/doc/harmonyos-guides/ide-build-expanding)

HarmonyOS Next 編譯之如何構建不同包名應用在日常的開發中涉及到多簽名和多產物構建輸出時手動切換簽名文件和包 - 掘金

HarmonyOS多環境+多渠道+自定義路徑輸出+自定義名稱一鍵打app和hap包前言 做移動端開發時,不可避免的會遇到 - 掘金

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77452.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77452.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77452.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

qt/c++云對象瀏覽器

簡介 本項目為基于QT5和C11的云對象存儲可視化管理工具 源碼獲取 int main(){ printf("源碼聯系綠泡泡:%s","joyfelic"); return 0; }

【Ubuntu】提升 docker ps -a 輸出的可讀性:讓 Docker 容器狀態更清晰

提升 docker ps -a 輸出的可讀性&#xff1a;讓 Docker 容器狀態更清晰 當我們使用 docker ps -a 查看所有 Docker 容器時&#xff0c;輸出的信息通常會非常多&#xff0c;尤其是在容器數量較多時。默認輸出中包含容器 ID、名稱、鏡像、狀態、端口等信息&#xff0c;容易讓人眼…

Spring Security自定義身份認證

盡管項目啟動時&#xff0c;Spring Security會提供了默認的用戶信息&#xff0c;可以快速認證和啟動&#xff0c;但大多數應用程序都希望使用自定義的用戶認證。對于自定義用戶認證&#xff0c;Spring Security提供了多種認證方式&#xff0c;常用的有In-Memory Authentication…

在亞馬遜云服務器上部署WordPress服務

在亞馬遜云服務器上部署WordPress服務第一步&#xff1a;創建EC2實例第二步&#xff1a;初始設置與安裝第三步&#xff1a;配置MySQL與WordPress第四步&#xff1a;配置Apache與WordPress第五步&#xff1a;訪問WordPress第六步&#xff1a;測試數據庫連接第七步&#xff1a;使…

Web3.0的認知補充(去中心化)

涉及開發技術&#xff1a; Vue Web3.js Solidity 基本認知 Web3.0含義&#xff1a; 新一代互聯網思想&#xff1a;去中心化及用戶為中心的互聯網 數據&#xff1a;可讀可寫可授權 核心技術&#xff1a;區塊鏈、NFT 應用&#xff1a;互聯網上應用 NFT &…

如何修復寶可夢時時刻刻冒險無法正常工作

寶可夢的時時刻刻冒險模式是一項強大的功能&#xff0c;即使應用程序關閉&#xff0c;它也能追蹤你的步行距離。它的工作原理是將你的步數與 iOS 上的 Apple Health 或 Android 上的 Google Fit 同步。它對于孵化寶可夢蛋和賺取好友糖果至關重要&#xff0c;但一旦它停止工作&a…

redis常用集合操作命令

在 Redis 的命令行界面&#xff08;redis-cli&#xff09;中&#xff0c; Redis 的集合&#xff08;Set&#xff09;是無序的&#xff0c;且集合中的元素是唯一的。Redis 本身沒有直接提供獲取集合中某個特定屬性的命令&#xff0c;因為集合中的元素是簡單的值&#xff0c;而不…

初識數據結構——二叉樹從基礎概念到實踐應用

數據結構專欄 ?(click) 初識二叉樹&#xff1a;從基礎概念到實踐應用&#x1f333; 一、樹型結構基礎 1.1 樹的基本概念 樹是一種非線性的數據結構&#xff0c;由n(n>0)個有限節點組成一個具有層次關系的集合。它看起來像一棵倒掛的樹&#xff0c;根朝上而葉朝下。 關鍵特…

駝峰命名法(Camel Case)與匈牙利命名法(Hungarian Notation)詳解

駝峰命名法&#xff08;Camel Case&#xff09;與匈牙利命名法&#xff08;Hungarian Notation&#xff09;詳解及對比? ?1. 駝峰命名法&#xff08;Camel Case&#xff09;? ?定義? 駝峰命名法&#xff08;Camel Case&#xff09;是一種變量、函數、類等標識符的命名方…

keil 中優化等級的bug

一&#xff0c;問題描述 程序中代碼有的執行&#xff0c;有的不執行&#xff0c;仔細研究&#xff0c;查詢人工智能。 程序中printf打印后面的代碼不執行&#xff0c; 然后過幾十個函數又開始正常了。 二.分析問題 跳過函數一般又判斷和Goto等語句&#xff0c;其它的溢出和錯誤…

織夢dedecms網站如何修改上一篇下一篇的標題字數

一般情況下&#xff0c;如果你的上一篇和下一篇是2行布局就不需要限制標題的字數了&#xff0c;如果你要一行布局上一篇和下一篇標題過長就會打亂網頁布局&#xff0c;那么限制上一篇和下一篇的標題字數是需要的&#xff0c;避免頁面看起來雜亂不堪。 織夢dedecms網站如何修改…

信創系統 sudoers 權限配置實戰!從小白到高手

好文鏈接&#xff1a;實戰&#xff01;銀河麒麟 KYSEC 安全中心執行控制高級配置指南 Hello&#xff0c;大家好啊&#xff01;今天給大家帶來一篇關于信創終端操作系統中 sudoers 文件詳解的實用文章&#xff01;在 Linux 系統中&#xff0c;sudo 是一項非常重要的權限控制機制…

《明解C語言入門篇》讀書筆記四

目錄 第四章&#xff1a;程序的循環控制 第一節&#xff1a;do語句 do語句 復合語句&#xff08;程序塊&#xff09;中的聲明 讀取一定范圍內的值 邏輯非運算符 德摩根定律 德摩根定律 求多個整數的和及平均值 復合賦值運算符 后置遞增運算符和后置遞減運算符 練習…

vite+vue2+elementui構建之 vite.config.js

webpack版本太低&#xff0c;構建依賴太多&#xff0c;頭大。 各種查閱資料&#xff0c;弄了一份直通構建vite構建elementUi核心文件&#xff0c; 構建基于開源若依vue2vue3版本改造&#xff0c;感謝開源&#xff0c;感謝若依。 package.json 地址 vitevue2elementui構建之…

超參數詳解:從基礎概念到優化策略的全面指南

摘要 本文深入解析機器學習中超參數的核心概念&#xff0c;詳細對比參數與超參數的本質區別&#xff0c;系統介紹學習率、隱含層數量等常見超參數類型&#xff0c;以及網格搜索、貝葉斯優化等主流尋優方法。結合超參數搜索的標準流程&#xff0c;通過具體案例演示如何高效調整…

計算機視覺與深度學習 | LSTM原理及與卡爾曼濾波的融合

長短期記憶網絡(LSTM)是一種特殊的循環神經網絡(RNN),旨在解決傳統RNN在處理長序列數據時出現的梯度消失和梯度爆炸問題。以下為你詳細介紹其基本原理: 核心思想:LSTM的核心思想是引入記憶單元和門控機制來控制信息的流動,從而解決傳統RNN的梯度消失問題。記憶單元類似…

EXCEL常用函數公式和VBA匯總第二篇

系列文章目錄 文章目錄 系列文章目錄前言一、excel公式應用1.rand函數2.rand函數隨機排序3.rand函數提取數據4.correl函數5.SUBSTITUTE函數6.MAX組合函數7.分析下班時間8.柏拉圖自動排序 總結 前言 一、excel公式應用 1.rand函數 用excel生成1-5的隨機數字&#xff0c;其中對…

iOS 類與對象底層原理

iOS 類與對象底層原理 文章目錄 iOS 類與對象底層原理探索對象本質objc_setProperty 源碼cls與類的關聯原理聯合體isa的類型isa_t 原理探索initIsa方法通過setClass方法中的shiftcls來驗證綁定的一個流程通過 isa & ISA_MSAK通過object_getClass通過位運算 類&類的結構…

浮點數:IEEE 754標準

IEEE 754 標準是一種由電氣和電子工程師協會&#xff08;IEEE&#xff09;制定的浮點數表示的標準&#xff0c;廣泛應用于計算機系統中&#xff0c;下面是詳細介紹&#xff1a; 歷史背景 在 IEEE 754 標準出現之前&#xff0c;不同的計算機系統采用各自的浮點數表示方法&…

centos7部署k8s集群

環境準備 服務器三臺 10.0.0.70master 10.0.0.71worker1 10.0.0.72worker2 配置yum源&#xff08;集群機器執行&#xff09; wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 安裝常用軟件 yum -y install lrzsz vim net-tools關閉f…