《京东金融APP的鸿蒙之旅系列专题》鸿蒙工程化:Hvigor构建技术
作者:京东科技 杨拓
一、构建工具概述
Hvigor构建工具是一款基于TypeScript实现的构建任务编排工具,专为提升构建和测试应用的效率而设计。它主要提供以下关键功能:
1、DevEco Studio与Hvigor的集成
DevEco Studio使用Hvigor构建工具来自动执行和管理构建流程,实现应用和服务构建任务流的执行,最终完成HAP/APP的构建打包。Hvigor的优势在于其灵活性和独立性:
2、构建过程的一致性
无论使用命令行工具还是DevEco Studio来构建项目,构建过程的输出将保持一致。这种一致性确保了开发者在不同的构建环境中都能获得相同的构建结果,减少了由于环境差异导致的问题。
3、典型使用场景
1. 本地开发:开发者可以在DevEco Studio中使用Hvigor进行本地开发和测试,方便快捷。
2. 命令行构建:对于习惯使用命令行工具的开发者,Hvigor提供了命令行接口,可以在终端中执行构建任务。
3. 持续集成/持续部署(CI/CD):在集成服务器上,Hvigor可以作为构建工具,自动化执行构建和测试任务,确保代码的持续集成和部署。
Hvigor构建工具通过其强大的任务管理和配置管理功能,为开发者提供了高效、灵活的构建解决方案。无论是在DevEco Studio内使用,还是通过命令行工具和集成服务器进行构建,Hvigor都能确保构建过程的高效和一致性,为开发者带来更好的开发体验。
4、支持的语言
hvigor支持TS、JS等主流前端语言
二、构建生命周期
hvigor在执行任何任务之前都会构建任务依赖图,所有任务会形成一个有向无环图,如下:

(图片来自于鸿蒙官方)
hvigor生命周期有3个阶段,分为初始化、配置和执行,hvigor会按顺序运行这些阶段,每个阶段都有特定的任务和目的。
1、初始化
目的:初始化项目的编译参数,构造出项目结构的树形数据模型
步骤:
2、配置
目的:加载每个节点的插件(plugin)、任务(task)和任务依赖关系图(DAG图)
步骤:
3、执行
目的:执行选定的任务
步骤:

(图片来自于鸿蒙官方)
Hvigor构建工具通过以上这三个阶段的处理,确保了构建过程的有序和高效并对外提供了灵活的配置和扩展能力:
4、生命周期内Hook点
针对以上生命周期的3个阶段,有很多的hook点可以使用,下图所有绿色标记的线框都是可使用的hook点:

(图片来自于鸿蒙官方)
三、构建任务和产物
1、HAP基础任务流程图
使用run即可在build看到每个任务,或者在Terminal中使用hvigorw taskTree命令查看执行任务,在官方文档中可以查看每个任务的具体说明,但鸿蒙目前尚不支持对各Task产物进行修改
2、HAP构建产物说明
打出的Release包一般包含以下文件:
四、上手开发Task
编辑工程下hvigorfile.ts文件,使用HvigorNode节点对象注册任务
// 获取当前hvigorNode节点对象const node =getNode(__filename);
// 注册Task
node.registerTask({
name:'TaskName',//task名字
run(){
//实现run方法,在里面实现自定义操作
}});
//执行Task
hvigorw TaskName
五、上手开发Plugin
//1 在hvigorfile.ts中定义插件方法,实现HvigorPlugin接口
function customPlugin(): HvigorPlugin {
return{
pluginId:'customPlugin',
apply(node: HvigorNode){
// 插件主体
console.log('hello customPlugin!');
}
}}
//2 在导出声明中使用插件exportdefault{
system: appTasks,
plugins:[
customPlugin() // 应用自定义Plugin
]}
//3 执行
hvigorw --sync
如果只是针对单个工程开发一个简单的Plugin,可直接在工程或模块下hvigorfile.ts文件编写,要是想进行复用和多个工程共享,可以抽取成一个单独的typescript项目
六、开发一个路由插件
在使用Navigation系统路由时,需要配置路由表文件route_map和每个页面的入口函数Builder,而且函数名两者需要保持一致,这个操作可以通过自定义Plugin的方式来解决,但是配置文件多人协同开发时,自动生成产物修改频繁,冲突问题较为严重。目前鸿蒙官方也提供了HMRouter官方路由方案,功能更为齐全,后续大家可以使用体验。
1、介绍下AST
抽象语法树 (Abstract Syntax Tree,AST),是源代码语法结构的一种抽象表示。以树状的形式表现编程语言的语法结构,每个节点都表示源代码中的一种结构。可以看个例子:
let name ='jd'
转的语法树如下:
file: File{
type: File,
// 初始到结尾有几个字符
start:0,
end:18,
...
program: Program{
type: Program,
body:{// 所有的内容都存在body里面
VariableDeclaration:{// 变量定义
// 声明变量、运算符、标识符.....这些语法格式在树中都有一个对应
declarations:[
VariableDeclarator:{
// 初始化,字符串字面量
init: StringLiteral {
type :'StringLiteral',
start:11,
end:15,
// 值
value:'jd'
}
}
],
kind:'let'//类型
}
}
}}
2、开发思路
3、实现自定义装饰器
export function JRRouter(param:JRRouterParam){
return Object;
}
export interface JRRouterParam{
name: string;
routerMode: boolean;
extra?: string;
jumpCode?: string;
}
4、环境初始化
开发环境:Node.js 16 ~ 18 (推荐)
请先安装node.js并将可执行文件路径配置到环境变量PATH中
5、初始化typescript项目
5.1、创建一个空目录
在命令行工具中使用cd命令进入空目录下
5.2、安装typescript模块
# 全局安装TypeScript
npm install typescript -g
5.3、初始化npm项目
# 初始化一个npm项目
npm init
5.4、生成typescript配置文件
# 初始化typeScript配置文件
tsc --init
5.5、依赖配置
在用户目录下创建或打开.npmrc文件,配置如下信息:
registry=https://repo.huaweicloud.com/repository/npm/
@ohos:registry=https://repo.harmonyos.com/npm/
打开package.json添加devDependencies配置。
"devDependencies": {
"@ohos/hvigor": "4.0.2"
}
执行如下命令安装依赖
npm install
6、编写插件代码
创建JRouterPlugin.ts文件,编写插件代码,下面是详细代码和注释
/**
* 获取指定路径下所有文件的路径
* @param directoryPath - 要扫描的目录路径
* @returns 所有文件的路径数组
*/
function getAllFiles(directoryPath: string): string[] {
return readdirSync(directoryPath).reduce((files, file) => {
const filePath = join(directoryPath, file);
const isDirectory = statSync(filePath).isDirectory();
return isDirectory ? [...files, ...getAllFiles(filePath)] : [...files, filePath];
}, []);
}
/**
* 生成 Builder 文件
* @param templateModel - 模板数据模型
* @param config - 插件配置
*/
function createBuilderFile(templateModel: TemplateModel, config: RouterPluginConfig) {
const builderFilePath =