HAR / HSP 模块化拆分与跨包资源共享

前言

当工程从「单 Module Demo」长成「多业务线的大型 App」,把所有代码塞进一个 entry 会让编译变慢、耦合爆炸。HarmonyOS 提供两种可复用包:HAR(HarmonyOS Archive,静态共享包)HSP(HarmonyOS Shared Package,动态共享包)。本文讲清楚两者差异、何时用哪个,以及如何跨包共享资源与代码。

问题描述

  1. 多个业务模块都要用同一套网络层 / 工具函数,复制粘贴导致多份实现、改一处要改 N 处。
  2. 把公共代码抽成 HAR 后,包体积变大;抽成 HSP 后又遇到「资源找不到」「多个 HSP 重复打包」的问题。
  3. 跨包引用字符串、图片、ArkUI 组件时路径怎么写、怎么避免循环依赖。

细节解析

1. HAR vs HSP 怎么选

维度HARHSP
形态编译期静态链接进引用方运行时动态加载,多模块共享同一份
包体积每个引用方都含一份,体积偏大全局一份,体积更优
资源自带,编译进宿主共享,需通过 $r 正确寻址
适用纯工具库、组件库、可发布的三方库多个 feature 共用的业务公共层
限制不能包含 Ability不能独立上架,必须被 entry 依赖

经验法则:对外发布 / 无状态工具用 HAR;App 内部多模块共用的「重」公共层用 HSP

2. 跨包引用代码

在引用方的 oh-package.json5 里声明依赖:

{
  "dependencies": {
    "mylib": "file:../mylib"   // 本地源码依赖
  }
}

代码里直接 import { httpGet } from 'mylib'

3. 跨包引用资源

HSP 里定义 string.json / 图片后,引用方用带包名的 $r('mylib.string.key') 访问;HAR 资源则随编译进入宿主,使用方式相同。务必保证包名唯一且稳定,改名会导致所有 $r 失效。

4. 避免循环依赖

A 依赖 B、B 又依赖 A 会在编译期报错。解法:把共享部分下沉到第三个包 C,A、B 都只依赖 C。

示例代码

HSP 暴露一个公共网络函数(mylib/src/main/ets/network.ts):

// mylib/src/main/ets/network.ts
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

export interface ApiResp<T> { code: number; data: T; }

export function requestJson<T>(url: string): Promise<T> {
  return new Promise((resolve, reject) => {
    const req = http.createHttp();
    req.request(url, { method: http.RequestMethod.GET, connectTimeout: 10000 })
      .then((resp) => {
        if (resp.responseCode === 200) {
          resolve(JSON.parse(resp.result as string) as T);
        } else {
          reject(new Error('HTTP ' + resp.responseCode));
        }
      })
      .catch((e: BusinessError) => reject(e))
      .finally(() => req.destroy());
  });
}

引用方页面(entry):

import { requestJson } from 'mylib';
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button('拉取数据').onClick(async () => {
        try {
          const data = await requestJson<{ name: string }>('https://api.example.com/info');
          promptAction.showToast({ message: data.name });
        } catch (e) {
          promptAction.showToast({ message: '请求失败' });
        }
      })
    }.padding(20)
  }
}

总结

  • HAR 适合无状态工具/组件库与对外发布;HSP 适合 App 内部多模块共用的「重」公共层,节省体积。
  • 依赖写在 oh-package.json5,代码用 import { ... } from '包名'
  • 资源用带包名的 $r('包名.resource.key'),包名一旦确定不要改。
  • 出现循环依赖时,把共享逻辑下沉到第三个包。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐