这三段代码构成了一个完整的 React Native 多 Bundle 打包系统,专门用于 OpenHarmony 平台的混合应用开发。让我为您详细解析这个系统的架构设计和实现原理。

整体架构概述

这是一个基于 Metro 打包器的模块化构建系统,支持将大型 React Native 应用拆分为多个独立的 Bundle 文件,实现按需加载和资源优化。

系统组成
-‌ 模块ID生成器‌:为每个文件生成唯一的稳定标识符
-‌ ‌基础包配置‌:包含共享的公共模块
-‌ 业务包配置:针对特定功能模块的独立配置


公共moduleId:

const path = require('path');
const fs = require('fs');
const MD5 = require('crypto-js/md5');
const basicModuleIds = require('./map/basicModuleIds.json');
const businessModuleIds = require('./map/businessModuleIds.json');

function getModuleId(projectRootPath, modulePath, bundleName) {
  const pathRelative = modulePath.substr(projectRootPath.length + 1);
  const moduleIds = bundleName === 'basic' ? basicModuleIds : businessModuleIds;
  const moduleId = MD5(pathRelative).toString();
  moduleIds[pathRelative] = moduleId;
  fs.writeFileSync(path.resolve(__dirname, `./map/${bundleName === 'basic' ? 'basicModuleIds' : 'businessModuleIds'}.json`), JSON.stringify(moduleIds));
  return moduleId;
}

function createModuleIdFactoryWrap(projectRootPath, bundleName) {
  return () => {
    return (path) => {
      const pathRelative = path.substr(projectRootPath.length + 1);
      const moduleId = basicModuleIds[pathRelative] || businessModuleIds[pathRelative] || getModuleId(projectRootPath, path, bundleName);
      return moduleId;
    };
  };
}

function postProcessModulesFilterWrap(projectRootPath) {
  // 返回false则不打入bundle中
  return (module) => {
    const modulePath = module.path;
    const pathRelative = modulePath.substr(projectRootPath.length + 1);
    const moduleId = basicModuleIds[pathRelative];
    if (pathRelative.indexOf('__prelude__') >= 0 ||
      pathRelative.indexOf(`node_modules${path.sep}@react-native${path.sep}polyfills`) >= 0 ||
      pathRelative.indexOf(`node_modules${path.sep}metro-runtime${path.sep}src${path.sep}polyfills`) >= 0) {
      return false;
    }
    return !moduleId
  };
}

module.exports = { createModuleIdFactoryWrap, postProcessModulesFilterWrap };

在这里插入图片描述
这个模块是整个打包系统的基石,它通过精密的算法设计实现了模块的稳定标识和智能过滤。在模块ID生成系统中,MD5哈希算法发挥着核心作用。基于模块相对路径生成固定长度的哈希值,这种设计确保了同一文件在不同构建会话中能够获得完全一致的ID,这对于增量构建和缓存机制至关重要。

路径相对化处理是整个流程的第一步,它将绝对路径转换为相对于项目根目录的路径表示。这种转换不仅简化了路径表示,更重要的是为后续的哈希计算提供了统一的输入基准。通过精确的字符串裁剪操作,系统能够准确地提取出模块在项目中的位置信息。

哈希计算阶段采用MD5算法,虽然现代加密领域MD5已不再被认为是安全的,但在这种应用场景下,它的碰撞概率完全满足模块标识的需求。MD5(pathRelative).toString()调用将路径字符串转换为32位的十六进制哈希值,这个值具有足够的唯一性来标识不同的模块。

缓存机制是这个系统的智能化体现。系统维护两个独立的模块ID映射表:basicModuleIds用于基础模块,businessModuleIds用于业务模块。每次生成新的模块ID时,系统都会立即更新对应的JSON映射文件,这种实时持久化策略确保了即使在构建过程中断的情况下,已生成的ID信息也不会丢失。

createModuleIdFactoryWrap函数采用了工厂模式设计,这种三层嵌套的架构允许配置的高度复用和参数的预先绑定。当Metro打包器调用这个工厂函数时,它会返回一个专门用于处理模块路径的函数,这个函数内部实现了智能的ID查找逻辑。


主体文件basic.config.js:

const path = require('path');
const { mergeConfig, getDefaultConfig } = require('@react-native/metro-config');
const { createHarmonyMetroConfig } = require('@react-native-oh/react-native-harmony/metro.config');
const moduleId = require('./build/moduleId');

const projectRootPath = path.join(__dirname);

const config = {
  serializer: {
    createModuleIdFactory: moduleId.createModuleIdFactoryWrap(
      projectRootPath,
      'basic',
    ),
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({
  reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}), config);

在这里插入图片描述

@react-native/metro-config提供了官方的默认配置,这些配置包含了React Native项目运行所需的基本设置。而@react-native-oh/react-native-harmony则提供了鸿蒙平台特有的适配配置。通过mergeConfig函数,系统能够将这些配置与用户自定义设置无缝集成。

在基础包配置中,系统专门为’basic’包名称配置了模块ID工厂函数。这个工厂函数基于项目根路径和包名称参数,为每个模块生成稳定的标识符。这种稳定性对于增量构建和热重载功能至关重要。

项目根路径的动态获取通过path.join(__dirname)实现,这种方法确保了配置在不同环境下的适应性。无论项目部署在哪个目录,系统都能够准确地确定根路径位置。

序列化器配置是Metro打包流程中的关键环节。它负责将模块依赖图转换为可执行的JavaScript代码。createModuleIdFactory参数指定了用于生成模块ID的具体实现逻辑。


页面级flight.config.js:

const path = require('path');
const { mergeConfig, getDefaultConfig } = require('@react-native/metro-config');
const { createHarmonyMetroConfig } = require('@react-native-oh/react-native-harmony/metro.config');
const moduleId = require('./build/moduleId');

const projectRootPath = path.join(__dirname);

const config = {
  serializer: {
    createModuleIdFactory: moduleId.createModuleIdFactoryWrap(
      projectRootPath,
      'flight',
    ),
    processModuleFilter: moduleId.postProcessModulesFilterWrap(
      projectRootPath,
    ),
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({
  reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}), config);

在这里插入图片描述

航班业务包配置在基础包的基础上增加了更精细的控制策略。除了模块ID生成功能外,还集成了模块过滤机制,这使得业务包能够实现更优化的资源打包。

在业务包配置中,系统同时配置了createModuleIdFactory和processModuleFilter两个关键参数。这种双重配置机制允许对模块进行更精确的筛选和控制。

processModuleFilter参数通过postProcessModulesFilterWrap函数实现,这个函数返回一个过滤函数,用于决定哪些模块应该包含在最终的Bundle中。

模块过滤逻辑基于模块路径的特征匹配。系统会检查模块路径是否包含特定的关键词,如果匹配到预定义的排除模式,就会将该模块从Bundle中移除。


这三段代码是React Native Metro打包器的配置文件,用于构建和打包React Native应用到OpenHarmony平台。

在这里插入图片描述

第一段代码:模块ID生成工具

功能‌:为每个模块生成唯一的、稳定的ID标识符

具体实现‌:

  • 使用MD5哈希算法基于模块相对路径生成ID
  • 维护两个独立的模块ID映射表:basicModuleIds和businessModuleIds
  • 将生成的ID缓存到JSON文件中,避免重复计算

第二段代码:基础包Metro配置

功能‌:配置基础包的打包参数,主要用于共享的基础模块

配置特点‌:

  • 使用’basic’作为包名称
  • 仅配置createModuleIdFactory,不包含模块过滤

第三段代码:航班业务包Metro配置

功能‌:配置航班业务模块的打包参数

配置特点‌:

  • 使用’flight’作为包名称
  • 同时配置createModuleIdFactory和processModuleFilter
  • 代码关系说明

这种配置允许将应用拆分为多个独立的Bundle,实现按需加载和更好的性能优化。


接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。
在这里插入图片描述
最终实现效果是:

请添加图片描述

Logo

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

更多推荐