欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

在这里插入图片描述

前言

随着项目规模的扩大,项目中往往会堆积大量未使用的资源(如图片、字体、JSON 文件)。这些“僵尸文件”不仅增加了鸿蒙 HAP 包的体积,还可能导致混淆。

relic 是一个虽然小众但极具潜力的 Dart 静态分析工具库。它可以帮助你扫描代码库,分析资源引用情况。
(注:relic 在 Dart 生态中可能指代多个项目,此处我们将其定义为通用的“代码/资源遗留分析”概念的工具类库,或假设为一个辅助进行项目健康度检查的工具库进行讲解,侧重于静态分析思想)。

对于 OpenHarmony 开发者,控制 HAP 包大小是头等大事。任何多余的 KB 都是对用户流量的浪费。

一、核心原理

资源分析工具通常的工作流:

未被引用

被引用

扫描 assets 目录

建立文件列表

扫描 lib 目录

正则通过 build runner 或 AST 分析引用

比对

输出警告: Unused Asset

标记为 Active

二、OpenHarmony 适配说明

2.1 依赖关系分析 (Dependency Graph)

在鸿蒙项目中,由于模块化程度较高(如使用 HSPHAR),引用关系可能变得非常复杂。建议将资源放在 base 模块或对应的功能模块内。

  • 知识点:工具应支持跨模块(Cross-module)扫描,以防误删被其他原子化服务或 HAP 引用的资源。
// 示例:模拟跨模块扫描逻辑
void scanCrossModules() {
  final modules = ['entry', 'feature_login', 'common_utils'];
  for (var module in modules) {
    print('正在分析模块:$module 的资源依赖关系...');
    // 逻辑:建立每个模块的资源索引表
  }
}

在这里插入图片描述

2.2 静态元数据提取

由于鸿蒙的部署文件 module.json5 中定义了应用的元数据。

  • 知识点:一个专业的资源分析工具应当能够自动解析鸿蒙项目的 oh-package.json5module.json5,从中提取出显式注册的资源路径,确保分析的准确性。
// 示例:解析鸿蒙配置文件中的资源路径
import 'dart:convert';
import 'dart:io';

void parseOhosMetadata(String path) {
  final file = File('$path/module.json5');
  if (file.existsSync()) {
    final Map<String, dynamic> data = jsonDecode(file.readAsStringSync());
    final abilities = data['module']['abilities'] as List;
    print('从 module.json5 中提取到 ${abilities.length} 个 Ability');
  }
}

在这里插入图片描述

这类工具通常作为 DevDependencies 运行在构建机或开发者的 Mac/PC 上,并不打包进最终的 APP。
因此,它天然支持 OpenHarmony 项目,只要你的项目结构遵循 Dart/Flutter 标准布局。

三、实战示例:编写一个简单的未使用图片扫描器

由于 relic 库的具体 API 可能随版本变动较大,这里我们用 Dart 原生能力(结合 fileglob)实现一个类似 relic 功能的脚本,教你如何为鸿蒙项目做“瘦身”检查。

这本身就是一种 “relic hunting”(遗迹搜寻)。

import 'dart:io';
import 'package:glob/glob.dart';
import 'package:glob/list_local_fs.dart';
import 'package:path/path.dart' as p;

void main() {
  print('🔍 开始扫描鸿蒙项目僵尸资源...');
  
  // 1. 获取所有 Asset 图片
  // 假设图片放在 assets/images 下
  final assetsDir = Directory('assets/images');
  if (!assetsDir.existsSync()) {
    print('❌ assets/images 目录不存在');
    return;
  }
  
  final allImages = assetsDir
      .listSync(recursive: true)
      .whereType<File>()
      .where((f) => ['.png', '.jpg', '.svg'].contains(p.extension(f.path)))
      .map((f) => f.path)
      .toSet();

  print('📦 发现 ${allImages.length} 张图片资源');

  // 2. 扫描所有 Dart 代码
  final dartFiles = Glob('lib/**.dart').listSync();
  final usedImages = <String>{};

  for (var entity in dartFiles) {
    if (entity is File) {
      final content = entity.readAsStringSync();
      
      // 3. 简单的字符串匹配
      // 检查每张图片路径是否出现在代码中
      for (var imgPath in allImages) {
        // assets/images/icon.png -> images/icon.png (处理可能的简写引用)
        // 这里简化逻辑:只要文件名出现就算引用
        if (content.contains(p.basename(imgPath))) {
          usedImages.add(imgPath);
        }
      }
    }
  }

  // 4. 计算差集
  final unused = allImages.difference(usedImages);

  print('\n=== 扫描结果 ===');
  if (unused.isEmpty) {
    print('🎉 完美!没有发现未使用的图片。');
  } else {
    print('⚠️ 发现 ${unused.length} 个未使用文件 (建议删除):');
    unused.forEach((path) => print('  - $path'));
  }
}

在这里插入图片描述

四、总结

虽然这个示例是一个简化的脚本,但它传达了 relic 类工具的核心价值:代码库的持续健康监控

在 OpenHarmony 项目开发周期中,建议定期运行此类脚本(或集成到 CI/CD 流水线中)。
保持代码库的清爽,不仅能减小包体积,还能提升编译速度,让项目维护更加轻松。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐