/** * LocalBundleManager - Bundle 管理接口封装 * - 开发环境:从开发服务器获取 manifest(HTTP 模式) * - 生产环境:从 Native CodePush 模块获取 manifest(直接返回 JSON 对象) */ import { BundleManifest } from './ModuleRegistry'; import { Platform, NativeModules } from 'react-native'; import { getDevMode, type DevMode } from './DevModeConfig'; import { getGlobalConfig } from './config'; /** * 获取当前激活包的根目录 * HTTP 模式:返回空字符串(不需要 root path) */ async function getCurrentPackageRootPath(): Promise { // HTTP 模式:不需要 root path return ''; } /** * 将 Native 返回的 WritableMap 转换为 BundleManifest */ function convertNativeManifestToBundleManifest(nativeManifest: any): BundleManifest { // Native 可能返回字符串或对象,需要先处理 let manifestObj: any; if (typeof nativeManifest === 'string') { // 如果是字符串,先解析为 JSON 对象 try { manifestObj = JSON.parse(nativeManifest); } catch (error) { console.error('[LocalBundleManager] Failed to parse native manifest string:', error); throw new Error('Invalid manifest format: failed to parse JSON string'); } } else { // 如果已经是对象,直接使用 manifestObj = nativeManifest; } return { formatVersion: manifestObj.formatVersion || 1, main: { file: manifestObj.main?.file || '', version: manifestObj.main?.version || '1.0.0', }, modules: (manifestObj.modules || []).map((m: any) => ({ id: m.id, file: m.file, version: m.version || '1.0.0', dependencies: m.dependencies || [], lazy: m.lazy !== false, })), }; } /** * 获取当前激活包的 manifest * - 优先从 Native 模块获取(支持 CodePush 等热更新场景) * - 如果 Native 返回 null,在开发环境下降级到开发服务器获取 * - 生产环境下如果 Native 返回 null,抛出异常 */ async function getCurrentBundleManifest(): Promise { // 生产环境:从 Native 模块获取 manifest // if (!__DEV__) { // try { // const nativeManifest = await NativeModules.ModuleLoader.getCurrentBundleManifestContent(); // if (nativeManifest) { // return convertNativeManifestToBundleManifest(nativeManifest); // } else { // // Native 模块返回 null 或 undefined // throw new Error( // '[LocalBundleManager] Native module returned null manifest. ' + // 'Please ensure bundle-manifest.json exists in the app bundle.' // ); // } // } catch (error) { // console.error( // `[LocalBundleManager] Failed to get manifest from Native: ${error}` // ); // // 生产环境无法获取 manifest 时抛出异常 // throw new Error( // `[LocalBundleManager] Failed to get manifest from Native module: ${error}` // ); // } // } console.log("ReactNativeJS","nativeManifest getCurrentBundleManifestContent") const nativeManifest = await NativeModules.ModuleLoader.getCurrentBundleManifestContent(); console.log("ReactNativeJS","nativeManifest "+nativeManifest) if (nativeManifest) { return convertNativeManifestToBundleManifest(nativeManifest); } else { // Native 模块返回 null 或 undefined throw new Error( '[LocalBundleManager] Native module returned null manifest. ' + 'Please ensure bundle-manifest.json exists in the app bundle.' ); } // 开发环境:从开发服务器获取 manifest const config = getGlobalConfig(); const devServer = config?.devServer; if (devServer) { try { const protocol = devServer.protocol || 'http'; const platform = Platform.OS; const manifestUrl = `${protocol}://${devServer.host}:${devServer.port}/bundle-manifest.json?platform=${platform}`; const response = await fetch(manifestUrl); if (response.ok) { const manifest: BundleManifest = await response.json(); return manifest; } else { console.warn( `[LocalBundleManager] Failed to fetch manifest: HTTP ${response.status} ${response.statusText}` ); } } catch (error) { console.warn( `[LocalBundleManager] Failed to fetch manifest from dev server: ${error}` ); } } else { // 降级到默认配置(向后兼容) try { const host = Platform.OS === 'android' ? '10.0.2.2' : 'localhost'; const platform = Platform.OS; const manifestUrl = `http://${host}:8081/bundle-manifest.json?platform=${platform}`; const response = await fetch(manifestUrl); if (response.ok) { const manifest: BundleManifest = await response.json(); return manifest; } else { console.warn( `[LocalBundleManager] Failed to fetch manifest: HTTP ${response.status} ${response.statusText}` ); } } catch (error) { console.warn( `[LocalBundleManager] Failed to fetch manifest from dev server: ${error}` ); } } // 所有尝试都失败,抛出异常 throw new Error( '[LocalBundleManager] Failed to get bundle manifest: ' + 'Unable to fetch manifest from dev server or Native module. ' + 'Please ensure Metro server is running and bundle-manifest.json is accessible.' ); } /** * 获取当前开发模式 */ function getCurrentDevMode(): DevMode { return getDevMode(); } export const LocalBundleManager = { getCurrentPackageRootPath, getCurrentBundleManifest, getCurrentDevMode, };