Havigor 是鸿蒙平台一款使用 TypeScript 实现的构建任务编排工具,类似于 Android 平台的 Gradle。它主要提供任务管理机制,包括任务注册编排、工程模型管理、配置管理等关键能力。针对 HarmonyOS 应用提供了一系列编译构建任务,支持将 HarmonyOS 应用编译构建出对应的产物包。
作为一款 HarmonyOS 应用编译构建任务流工具,DevEco Hvigor 具备诸多提升构建效率的特性,比如并行编译、增量编译等等;支持多产物差异化构建。也支持HarmonyOS应用可分可合等特性。
文件结构介绍
当我们在 DevEco 中新建一个 Harmony OS 应用的项目后,可以在项目目录中看到如下关于 hvigor 的文件:
typescript
├─entry // entry 模块,对于后续新增的 module 同样会有一个 hvigotfile.ts 文件
│ ├─src
│ └─hvigorfile.ts // 模块级编译构建脚本
├─hvigor // hvigor 插件信息
│ ├─hvigor-config.json5 // hvigor 插件配置文件
│ └─hvigor-wrapper.js // hvigor 插件具体业务逻辑实现的 js 代码,执行此代码以执行 hvigor 相关操作
├─build-profile.json5 // 工程级配置文件,声明工程对应的构建参数
├─hvigorfile.ts // 工程级编译构建脚本
├─hvigorw // 非 Windows 系统下的执行脚本
└─hvigorw.bat // Windows 系统下的执行脚本
Hvigor-config.json5 文件主要用来配置 hvigor 和 hvigor-ohos-plugin 的版本,同时也支持一些编译过程中的配置,比如是够启用守护进程编译、是否启用增量编译、是否启用并行编译、是否启用类型检、定义日志级别、是否警用堆栈跟踪编译等等。
typescript
{
"hvigorVersion": "4.0.4",
"dependencies": {
"@ohos/hvigor-ohos-plugin": "4.0.4"
},
"execution": {
"daemon": true, /* 启用守护进程编译。默认值:true */
"incremental": true, /* 启用增量编译。默认值:true */
"parallel": true, /* 启用并行编译。默认值:true */
"typeCheck": false /* 启用类型检查。默认值:false */
},
"logging": {
"level": "info" /* 定义日志级别。取值:[ "debug" | "info" | "warn" | "error" ]。默认值:"info" */
},
"debugging": {
"stacktrace": false /* 禁用堆栈跟踪编译。默认值:false */
}
"nodeOptions": {
"maxOldSpaceSize": 4096 /* 启用守护进程编译时,守护进程内存大小,单位为MB。默认值:4096 */
}
}
增量构建
增量构建是hvigor执行任务的一种优化,如果在两次执行任务过程中,执行任务的输入和输出没有更改,hvigor 会复用上次构建产物,从而跳过该任务的执行节省构建时间。如果需要使用增量编译特性,我们需要在 DevEco 中(Setting->Build,Execution,Deployment->Build Tools->Hvigor)勾选 「Re-execute the task in incremental mode」。
除了前面我们说的,可以在 hvigor-config.json5 中 execution.incremental 字段来控制是否启用增量构建。我们还可以通过如下命令选择是否开启增量构建(hvigor 默认开启增量构建)。
bash
# 启用增量构建
./hvigorw <task> --incremental
# 关闭增量构建
./hvigorw <task> --no-incremental
开启增量构建后,我们会在增量执行场景下看到显著的性能改进。
并行构建
大部分工程都包含了多个子工程,其中一些子工程是相互独立的,也就是说,它们之间没有状态共享。在大多数情况下,通过并行构建可以有效地减少多个子工程的整体构建时间。对于 C++ 编译、ArkTS 任务等耗时且没有依赖关系的任务,DevEco Hvigor 可以使用不同的工作线程并行执行,提高编译构建的效率。熟悉 Android Gradle 的同学应该知道,这种特性在多模块的中大型项目中,会带来非常可观的耗时节省。然而,在特定的情况下,如子工程之间存在大量的依赖关系,可能无法显著缩短构建时间。节省的具体时间取决于我们的工程结构和子工程之间的依赖关系
如果需要使用并行编译特性,我们需要在 DevEco 中开启支持(Setting->Build,Execution,Deployment->Build Tools->Hvigor)
除了前面我们说的,可以在 hvigor-config.json5 中 execution.parallel 字段来控制是否启用增量构建。我们还可以通过如下命令选择是否开启增量构建(hvigor 默认开启并行构建)。
sh
# 启用并行执行
./hvigorw <task> --parallel
# 关闭并行执行
./hvigorw <task> --no-parallel
守护进程
hvigor 提供了进程常驻机制,通过将进程常驻在内存中,一方面避免了 Node 进程重复启动、减少了加载 js 文件的耗时,另w外一方面可以复用构建过程中的增量缓存、减少增量缓存信息的读取与落盘操作。另外,启用 hvigor 的常驻进程功能,还可以支持预览器的急速预览功能和调试的Hot reload功能。DevEco Hvigor 通过对代码文件的监听,可以快速编译代码片段,急速更新预览画面和在设备上实时调试代码修改。使用守护行程编译,我们需要在DevEco 中(Setting->Build,Execution,Deployment->Build Tools->Hvigor)勾选 「Enable the Daemon for tasks」。
除了前面我们说的,可以在 hvigor-config.json5 中 execution.daemon 字段来控制是否启用守护进程。我们还可以通过如下命令选择是否开启守护进程(hvigor 默认开启守护进程)。
sh
# 启用守护进程
./hvigorw <task> --daemon
# 关闭守护进程
./hvigorw <task> --no-daemon
默认情况下,hvigor 为我们的项目构建保留了4096 MB的内存空间,这对于大多数项目来说已经足够了,但是如果我们的项目非常庞大,项目的构建可能需要更多的内存来保存 hvigor 的模型和缓存。遇到这种情况,我们可以设置 hvigor-config.json5 文件中的nodeOptions.maxOldSpaceSize 字段来调整为更大的内存。
更多的设置选项可以参考hvigor-config.json5字段说明
查看 hvigor 可用任务
任务是一个基本的工作单元,是hvigor构建的一部分。在工程目录下,输入以下命令可以列出项目中所有可用的任务:
bash
./hvigorw tasks
Tasks 命令会列出当前项目中工程和模块中的所有可用的任务:
bash
> hvigor hvigor client: The argument passed to Node.js or hvigor version have changed and a new daemon will be created to replace the existing daemon. Reason:{isHvigorVersionChanged: false, isNodeEnvChanged: true}
> hvigor hvigor client: Starting hvigor daemon.
> hvigor Hvigor Daemon started in 258 ms
--------------------------------------------------------------------------
All tasks from hvigor node 'entry'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorCoreNode.
taskTree - Displays the task dag tree of the HvigorCoreNode.
Sync tasks
-------------
init
> hvigor Finished :entry:tasks... after 1 ms
--------------------------------------------------------------------------
All tasks from hvigor node 'router_library'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorCoreNode.
taskTree - Displays the task dag tree of the HvigorCoreNode.
Sync tasks
-------------
init
> hvigor Finished :router_library:tasks... after 1 ms
--------------------------------------------------------------------------
All tasks from hvigor node 'WBRouter'
--------------------------------------------------------------------------
Help tasks
-------------
tasks - Displays the tasks of the HvigorCoreNode.
taskTree - Displays the task dag tree of the HvigorCoreNode.
Other tasks
-------------
prune - Clean up old hvigor cache files and remove unreferenced packages from store.
clean - Clear the cache information.
collectCoverage - Generate coverage statistics reports based on instrumentation dotting data.
Hook tasks
-------------
assembleApp - Assemble the task for the packaged app.
Sync tasks
-------------
init
Sign tasks
-------------
SignApp - Sign the app package.
Package tasks
-------------
PackageApp - Build the app package in the stage model.
Generate tasks
-------------
GeneratePackRes - Build the pack.res file in the stage model.
MakeProjectPackInfo - Generate project pack.info in the stage model.
Verification tasks
-------------
PreBuildApp - Prepare before building the app.
> hvigor Finished ::tasks... after 1 ms
> hvigor BUILD SUCCESSFUL in 834 ms
根据输出结果可以看到,当前的 hvigor 任务有:
模块级的任务(entry 和 router_library两个module)
- Help tasks (tasks、taskTree)
- Sync tasks(init)
工程级的任务 (WBRouter)
- Help tasks(tasks、taskTree)
- Other tasks (prune、clean、collectCoverage)
- Hook tasks (assembleApp)
- Sync tasks (init)
- Sign tasks (SignApp)
- Package tasks (PackageApp)
- Generate tasks (GeneratePackRes、MakeProjectPackInfo)
- Verification tasks (PreBuildApp)
自定义你的任务
在hvigorfile.ts文件中只需定义一个pluginId(任务Id)和name(任务名称),并实现其中的run方法,即可创建一个任务。例如,我们创建一个打印"Hello HarmonyOS"任务:
typescript
function helloHarmonyOS() {
return {
pluginId: 'HelloHarmonyOS',
apply(pluginContext) {
pluginContext.registerTask({
// 编写自定义任务
name: 'HelloHarmonyOS',
run: (taskContext) => {
console.log('Hello HarmonyOS!');
}
})
}
}
}
export default {
system: [],
plugins: [ helloHarmonyOS() ]
}
运行任务:
typescript
./hvigorw HelloHarmonyOS
关于 DevEco Hvigor 本篇我们就先介绍到这,下一篇我们将继续介绍 hvigor 的编译过程,以及如何开发 hvigor 任务插件。