首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >鸿蒙包体优化与构建配置实战 :从体积分析到分包治理

鸿蒙包体优化与构建配置实战 :从体积分析到分包治理

原创
作者头像
hunter android
发布2026-08-18 12:04:55
发布2026-08-18 12:04:55
250
举报

为什么要做包体优化

应用包体积直接影响三个关键指标:

  1. 下载转化率:包体每增加 6MB,下载转化率下降约 1%
  2. 更新意愿:大包更新用户更容易放弃,尤其是流量环境下
  3. 应用商店排名:部分应用市场将包体积作为推荐权重因素

HarmonyOS 的 HAP/APP 包结构与 Android APK 有相似之处,但也有独特的优化空间——本文从体积分析、资源压缩、代码优化到分包策略,给出完整的工程化方案。


HAP 包结构与体积分析

HAP 包基本结构

代码语言:javascript
复制
entry.hap
├── ets/                    # ArkTS 编译产物
├── resources/              # 资源文件
│   ├── base/
│   │   ├── element/       # 字符串、颜色等
│   │   ├── media/         # 图片、音频、视频
│   │   └── profile/       # 配置文件
│   ├── rawfile/           # 原始文件(不压缩)
├── libs/                   # 原生库(so)
├── module.json             # 模块配置
└── pack.info               # 打包信息

体积分析命令

代码语言:javascript
复制
# 解压 HAP 查看结构
unzip entry.hap -d hap_extracted

# 查看各目录大小
du -sh hap_extracted/*

# 详细分析(递归显示前 20 大文件)
du -ah hap_extracted | sort -rh | head -20

常见占比: - resources/base/media:40%-60%(图片、动画) - ets:20%-30%(代码) - libs:10%-20%(原生库) - rawfile:0%-10%(不压缩资源)


资源优化

图片压缩与格式选择

代码语言:javascript
复制
// build-profile.json5
{
  "apiType": "stageMode",
  "buildOption": {
    "arkOptions": {
      "runtimeOnly": false
    }
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS",
      "buildOption": {
        "compileMode": "esmodule",
        // 启用资源压缩
        "enableObfuscation": true,
        "enableMinification": true
      }
    }
  ]
}

图片格式选型

格式

适用场景

压缩率

透明通道

WebP

通用位图

30%-50% 优于 PNG

支持

PNG

需要无损透明

基准

支持

JPG

照片、渐变

比 PNG 小 50%-80%

不支持

SVG

图标、简单图形

极小

支持

批量转换 WebP

代码语言:javascript
复制
# 安装 cwebp(macOS)
brew install webp

# 批量转换
for img in resources/base/media/*.png; do
  cwebp -q 85 "$img" -o "${img%.png}.webp"
done

移除未使用资源

代码语言:javascript
复制
// 启用资源收缩(build-profile.json5)
{
  "buildOption": {
    "shrinkResources": true  // 移除未引用资源
  }
}

手动排查未使用资源

代码语言:javascript
复制
# 搜索所有资源引用
grep -r "R.media" ets/ > used_resources.txt
grep -r "\$r('app.media" ets/ >> used_resources.txt

# 对比 resources/base/media 中的文件,移除未引用的

压缩音频与视频

代码语言:javascript
复制
# 音频转 Opus(比 MP3 小 20%-40%)
ffmpeg -i input.mp3 -c:a libopus -b:a 64k output.opus

# 视频降码率
ffmpeg -i input.mp4 -vcodec h264 -b:v 1M -acodec aac -b:a 128k output.mp4

代码优化

混淆与压缩

代码语言:javascript
复制
// build-profile.json5
{
  "buildOption": {
    "enableObfuscation": true,      // 混淆
    "enableMinification": true,     // 压缩
    "enableSourceMap": false        // Release 关闭 SourceMap
  }
}

混淆规则(obfuscation-rules.txt):

代码语言:javascript
复制
# 保留入口和导出
-keep-global-name
entry

# 保留接口和数据类
-keep class com.example.data.**
-keep interface com.example.api.**

# 保留原生互调方法
-keep class com.example.bridge.** { *; }

移除调试日志

代码语言:javascript
复制
// 使用条件编译移除 Debug 日志
const DEBUG = false; // Release 构建设为 false

function log(msg: string) {
  if (DEBUG) {
    console.log(msg);
  }
}

构建时移除(通过宏定义):

代码语言:javascript
复制
// build-profile.json5
{
  "buildOption": {
    "arkOptions": {
      "defines": {
        "DEBUG": false
      }
    }
  }
}

Tree Shaking

HarmonyOS SDK 默认启用 Tree Shaking,但需要注意:

代码语言:javascript
复制
// ❌ 全量导入(整个库都会打包)
import * as utils from './utils';

// ✅ 按需导入(未使用的函数会被移除)
import { formatDate, parseUrl } from './utils';

原生库优化

ABI 分包

代码语言:javascript
复制
// build-profile.json5
{
  "buildOption": {
    "abiFilters": ["arm64-v8a"]  // 仅保留 ARM64(现代设备)
  }
}

多 ABI 分发(应用市场支持时):

代码语言:javascript
复制
{
  "targets": [
    {
      "name": "arm64",
      "buildOption": {
        "abiFilters": ["arm64-v8a"]
      }
    },
    {
      "name": "arm32",
      "buildOption": {
        "abiFilters": ["armeabi-v7a"]
      }
    }
  ]
}

移除未使用的 SO

代码语言:javascript
复制
# 检查 SO 依赖
readelf -d libs/arm64-v8a/libexample.so | grep NEEDED

# 移除未引用的库
# 在 CMakeLists.txt 中删除对应 target_link_libraries

分包策略

Feature HAP 按需加载

代码语言:javascript
复制
app.app
├── entry.hap          # 主包:核心功能
├── feature1.hap       # 特性包:高级功能
└── feature2.hap       # 特性包:离线资源

配置 Feature HAP(module.json5):

代码语言:javascript
复制
{
  "module": {
    "name": "feature1",
    "type": "feature",              // 类型为 feature
    "deliveryWithInstall": false,   // 不随主包安装
    "installationFree": false
  }
}

动态加载 Feature HAP

代码语言:javascript
复制
import bundleManager from '@ohos.bundle.bundleManager';

async function loadFeature() {
  try {
    await bundleManager.installModule('feature1');
    console.log('Feature 加载成功');
  } catch (err) {
    console.error('Feature 加载失败', err);
  }
}

按需加载大资源

代码语言:javascript
复制
// 将大文件放入 rawfile/online/
// 首次使用时下载

import request from '@ohos.request';
import fs from '@ohos.file.fs';

async function downloadResource(url: string, savePath: string) {
  const downloadTask = await request.downloadFile(this.context, {
    url: url,
    filePath: savePath
  });

  downloadTask.on('complete', () => {
    console.log('资源下载完成');
  });
}

构建配置最佳实践

Release 构建完整配置

代码语言:javascript
复制
// build-profile.json5
{
  "apiType": "stageMode",
  "buildOption": {
    "enableObfuscation": true,
    "enableMinification": true,
    "enableSourceMap": false,
    "shrinkResources": true,
    "abiFilters": ["arm64-v8a"],
    "arkOptions": {
      "runtimeOnly": false,
      "defines": {
        "DEBUG": false
      }
    }
  },
  "targets": [
    {
      "name": "default",
      "runtimeOS": "HarmonyOS"
    }
  ]
}

签名与证书

代码语言:javascript
复制
# 生成密钥对
keytool -genkeypair -alias release -keyalg RSA -keysize 2048 \
  -validity 10000 -keystore release.p12 -storetype PKCS12

# 配置签名(hvigorfile.ts)
export default {
  signingConfigs: {
    release: {
      storeFile: 'release.p12',
      storePassword: '******',
      keyAlias: 'release',
      keyPassword: '******'
    }
  }
}

实战案例

优化前后对比

某应用初始包体 45MB,优化后 18MB(减少 60%):

优化项

减少体积

图片转 WebP + 压缩

-12MB

移除未使用资源

-5MB

代码混淆与压缩

-3MB

仅保留 ARM64 ABI

-7MB

持续监控

代码语言:javascript
复制
// 构建后自动检查包体积
// 在 CI 脚本中添加
const fs = require('fs');
const MAX_SIZE_MB = 20;

const stats = fs.statSync('build/entry.hap');
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);

if (sizeMB > MAX_SIZE_MB) {
  console.error(`包体积超标: ${sizeMB}MB > ${MAX_SIZE_MB}MB`);
  process.exit(1);
}

小结

优化方向

关键手段

预期收益

资源

WebP、移除未使用、压缩音视频

30%-50%

代码

混淆、Tree Shaking、移除日志

10%-20%

原生库

ABI 分包、移除未使用 SO

10%-30%

分包

Feature HAP、动态资源

20%-40%

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 为什么要做包体优化
  • HAP 包结构与体积分析
    • HAP 包基本结构
    • 体积分析命令
  • 资源优化
    • 图片压缩与格式选择
    • 移除未使用资源
    • 压缩音频与视频
  • 代码优化
    • 混淆与压缩
    • 移除调试日志
    • Tree Shaking
  • 原生库优化
    • ABI 分包
    • 移除未使用的 SO
  • 分包策略
    • Feature HAP 按需加载
    • 按需加载大资源
  • 构建配置最佳实践
    • Release 构建完整配置
    • 签名与证书
  • 实战案例
    • 优化前后对比
    • 持续监控
  • 小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档