第2章:核心概念详解
1. Node节点体系
1.1 Node概述
Node是Hvigor构建系统中的基本单位,代表一个构建模块(如HAP/HAR/HSP)。每个Node都可以:
- 持有自己的构建配置
- 管理任务集合
- 维护与其他Node的依赖关系
1.2 HvigorNode API
interface HvigorNode {
// 获取节点名称
getNodeName(): string;
// 获取节点路径
getNodePath(): string;
// 获取上下文
getContext(pluginId: string): any;
// 注册任务
registerTask(taskOptions: TaskOptions): void;
// 获取任务
getTaskByName(name: string): Task | undefined;
// 遍历子节点
subNodes(callback: (node: HvigorNode) => void): void;
}
1.3 节点生命周期
export function myPlugin(): HvigorPlugin {
return {
pluginId: 'my-plugin',
apply(node: HvigorNode) {
// 配置评估阶段
hvigor.configurationEvaluated(() => {
console.log('配置评估完成');
});
// 节点评估阶段
hvigor.nodesEvaluated(() => {
console.log('所有节点评估完成');
});
// 构建完成阶段
hvigor.buildFinished(() => {
console.log('构建完成');
});
}
};
}
2. Context上下文系统
2.1 Context类型
Hvigor提供了三种主要的上下文类型:
// HAP模块上下文
interface OhosHapContext {
getModuleName(): string;
getModulePath(): string;
targets(callback: (target: Target) => void): void;
}
// HAR模块上下文
interface OhosHarContext {
getModuleName(): string;
getModulePath(): string;
}
// HSP模块上下文
interface OhosHspContext {
getModuleName(): string;
getModulePath(): string;
}
2.2 上下文使用示例
export function contextPlugin(): HvigorPlugin {
return {
pluginId: 'context-plugin',
apply(node: HvigorNode) {
// 获取HAP上下文
const hapContext = node.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosHapContext;
if (hapContext) {
// 获取模块信息
const moduleName = hapContext.getModuleName();
const modulePath = hapContext.getModulePath();
// 处理构建目标
hapContext.targets((target: Target) => {
const targetName = target.getTargetName();
const outputPath = target.getBuildTargetOutputPath();
console.log(`处理构建目标: ${targetName}, 输出路径: ${outputPath}`);
});
}
}
};
}
3. Task任务系统
3.1 任务定义
interface TaskOptions {
// 任务名称
name: string;
// 任务执行函数
run: () => void | Promise<void>;
// 依赖任务
dependencies?: string[];
// 后置任务
postDependencies?: string[];
// 是否启用
enabled?: boolean;
}
3.2 任务注册与配置
export function taskPlugin(): HvigorPlugin {
return {
pluginId: 'task-plugin',
apply(node: HvigorNode) {
// 注册自定义任务
node.registerTask({
name: 'customBuild',
// 任务执行逻辑
run: async () => {
console.log('开始自定义构建...');
// 执行构建逻辑
await someAsyncBuildOperation();
console.log('自定义构建完成');
},
// 前置依赖
dependencies: ['preBuild'],
// 后置依赖
postDependencies: ['postBuild']
});
// 禁用某个任务
node.getTaskByName('someTask')?.setEnable(false);
}
};
}
3.3 任务执行流程
- 依赖分析
- 拓扑排序
- 并行执行
- 错误处理
4. 最佳实践
4.1 插件设计原则
4.1.1 单一职责原则
- 每个插件专注于解决一个特定问题
- 通过组合多个小插件实现复杂功能
- 避免插件功能之间的耦合
// 好的实践
export function styleCheckPlugin(): HvigorPlugin { ... }
export function resourceOptimizePlugin(): HvigorPlugin { ... }
// 避免这样
export function styleAndResourcePlugin(): HvigorPlugin { ... }
4.1.2 可配置性设计
- 提供合理的默认配置
- 支持外部覆盖配置
- 配置项类型安全
interface StyleCheckConfig {
rules: {
[key: string]: 'error' | 'warn' | 'off';
};
ignorePatterns?: string[];
fix?: boolean;
}
export function styleCheckPlugin(config?: Partial<StyleCheckConfig>): HvigorPlugin {
const defaultConfig: StyleCheckConfig = {
rules: {
'no-console': 'warn',
'no-unused-vars': 'error'
},
fix: false
};
const finalConfig = { ...defaultConfig, ...config };
// 插件实现...
}
4.1.3 错误处理策略
- 提供清晰的错误信息
- 支持错误恢复机制
- 区分致命错误和警告
class PluginError extends Error {
constructor(
message: string,
public readonly severity: 'error' | 'warning' = 'error',
public readonly code?: string
) {
super(message);
}
}
function handlePluginError(error: PluginError, node: HvigorNode) {
if (error.severity === 'error') {
node.fail(`[${error.code}] ${error.message}`);
} else {
node.warn(`[${error.code}] ${error.message}`);
}
}
4.1.4 性能优化策略
- 实现增量构建
- 使用缓存机制
- 并行处理
- 懒加载资源
export class OptimizedPlugin {
private cache = new Map<string, any>();
async apply(node: HvigorNode) {
// 增量构建检查
const changedFiles = await this.getChangedFiles(node);
if (changedFiles.length === 0) {
console.log('No changes detected, skipping...');
return;
}
// 并行处理
await Promise.all(
changedFiles.map(async file => {
const cacheKey = this.getCacheKey(file);
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const result = await this.processFile(file);
this.cache.set(cacheKey, result);
return result;
})
);
}
}
4.2 代码组织最佳实践
4.2.1 模块化组织
// plugins/
// ├── core/
// │ ├── types.ts
// │ └── constants.ts
// ├── tasks/
// │ ├── styleCheck.ts
// │ └── resourceOptimize.ts
// ├── utils/
// │ ├── logger.ts
// │ └── cache.ts
// └── index.ts
// 统一导出
export * from './core/types';
export * from './tasks/styleCheck';
export * from './tasks/resourceOptimize';
4.2.2 插件生命周期管理
export class BasePlugin {
protected async beforeApply(node: HvigorNode) {
// 前置处理
}
protected async afterApply(node: HvigorNode) {
// 后置处理
}
async apply(node: HvigorNode) {
try {
await this.beforeApply(node);
await this.executePlugin(node);
await this.afterApply(node);
} catch (error) {
this.handleError(error);
}
}
protected abstract executePlugin(node: HvigorNode): Promise<void>;
}
4.2.3 依赖注入模式
interface Services {
logger: Logger;
cache: Cache;
config: Config;
}
export class ModernPlugin extends BasePlugin {
constructor(private services: Services) {
super();
}
protected async executePlugin(node: HvigorNode) {
const { logger, cache, config } = this.services;
// 使用注入的服务实现功能
}
}
4.3 调试与测试实践
4.3.1 日志管理
export class PluginLogger {
static debug(message: string, ...args: any[]) {
if (process.env.DEBUG) {
console.log(`[DEBUG] ${message}`, ...args);
}
}
static info(message: string, ...args: any[]) {
console.log(`[INFO] ${message}`, ...args);
}
static error(message: string, error?: Error) {
console.error(`[ERROR] ${message}`, error?.stack);
}
}
4.3.2 单元测试
describe('StyleCheckPlugin', () => {
let plugin: StyleCheckPlugin;
let mockNode: HvigorNode;
beforeEach(() => {
mockNode = createMockNode();
plugin = new StyleCheckPlugin({
rules: { 'no-console': 'error' }
});
});
it('should detect style violations', async () => {
const results = await plugin.checkStyle('test.ts');
expect(results.violations).toHaveLength(1);
});
});