iOS端创建ReactNative容器第一步:打出jsbundle和资源包
react-native的打包流程是通过执行react-native bundle指令进行的。
添加构建指令
修改RN项目中的package.json文件,先其中添加构建命令build-release-ios和build-debug-ios
1 2 3 4 5 6 7 8 9 | "scripts" : { "android" : "react-native run-android" , "ios" : "react-native run-ios" , "lint" : "eslint ." , "start" : "react-native start" , "test" : "jest" , "build-release-ios" : " react-native bundle --platform ios --entry-file index.js --bundle-output ./dest/bundle/index.jsbundle --assets-dest ./dest/bundle --dev false " , "build-debug-ios" : " react-native bundle --platform ios --entry-file index.js --bundle-output ./dest/bundle/index.jsbundle --assets-dest ./dest/bundle --dev true " }, |
说明如下;
react-native的打包是使用的命令react-native bundle, 然后再根据需要添加对应的参数。
--entry-file ,ios或者android打包入口的js文件名称,比如index.js(如果要根据不同的平台添加不同的功能,则需要将安卓和iOS的打包入口分开创建index.ios.js, index.android.js)
--platform ,平台名称(ios或者android)
--dev ,设置为false的时候表示为发布包,true为测试包,发布包会对JavaScript代码进行优化处理。
--bundle-output, 生成的jsbundle文件的名称,比如 ./dest/bundle/index.jsbundle
--assets-dest 图片以及其他资源存放的目录,比如./dest/bundle, 注意这里导出的资源是在jsbundle中通过引用使用的资源。
开始打包
打开RN项目,执行下面的打包指令进行打包
1 2 3 | npm run build-release-ios 或者 yarn build-release-ios |
指令执行完成后,打包的产物是放置在了./dest/bundle/目录之下

内置打包产物
将jsbundel包和assets资源包拖到项目中,放置到同一个目录下。

然后修改jsbundle的读取位置,将从服务器读取改成从本地读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { return [[NSBundle mainBundle] URLForResource: @"index" withExtension: @"jsbundle" ]; // return [self getBundleURL]; } - (NSURL *)getBundleURL { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot: @"index" ]; #else return [[NSBundle mainBundle] URLForResource: @"main" withExtension: @"jsbundle" ]; #endif } |
在iOS项目中,根据不同的业务类型加载不同的模块名称
1 2 | RNContainerController * containerVC = [[RNManager sharedInstance] loadWithModuleName: @"News" initialProps:@{}]; [self presentModalViewController:containerVC animated:YES]; |

JSBundle产物介绍
RN 通过执行react-native bundle打包命令得到产物JSBundle。
1 | "build-debug-ios" : " react-native bundle --platform ios --entry-file index.js --bundle-output ./dest/bundle/index.jsbundle --assets-dest ./dest/bundle --dev true " |
因为我们平时写的RN模块中会使用到图片,git,json文件这些资源,所以打出的产物也包含了js文件和资源文件。
产物JSBundle内容组成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | //1.全局变量定义 var __BUNDLE_START_TIME__= this .nativePerformanceNow?nativePerformanceNow():Date.now(),__DEV__= true ,process= this .process||{},__METRO_GLOBAL_PREFIX__= '' ,__requireCycleIgnorePatterns=[/(^|\/|\\)node_modules($|\/|\\)/];process.env=process.env||{};process.env.NODE_ENV=process.env.NODE_ENV|| "development" ; //2.require, clear全局函数声明 (function (global) { "use strict" ; global.__r = metroRequire; global[`${__METRO_GLOBAL_PREFIX__}__d`] = define; global.__c = clear; global.__registerSegment = registerSegment; var modules = clear(); var EMPTY = {}; var CYCLE_DETECTED = {}; var _ref = {}, hasOwnProperty = _ref.hasOwnProperty; if (__DEV__) { global.$RefreshReg$ = function () {}; global.$RefreshSig$ = function () { return function (type) { return type; }; }; } })() //3.RN模块定义(包括RN框架自己的,第三方库的,用户自定义的) __d(function (global, _$$_REQUIRE, _$$_IMPORT_DEFAULT, _$$_IMPORT_ALL, module, exports, _dependencyMap) { xxx xxx xxx },544,[1,262,306,21,50,91], "node_modules/react-native/Libraries/NewAppScreen/components/ReloadInstructions.js" ); __d(function (global, _$$_REQUIRE, _$$_IMPORT_DEFAULT, _$$_IMPORT_ALL, module, exports, _dependencyMap) { var _interopRequireDefault = _$$_REQUIRE(_dependencyMap[0], "@babel/runtime/helpers/interopRequireDefault" ); Object.defineProperty(exports, "__esModule" , { value: true }); exports. default = News; var _react = _interopRequireDefault(_$$_REQUIRE(_dependencyMap[1], "react" )); var _reactNative = _$$_REQUIRE(_dependencyMap[2], "react-native" ); var _jsxRuntime = _$$_REQUIRE(_dependencyMap[3], "react/jsx-runtime" ); var _jsxFileName = "/Users/admin/Documents/MyFile/react-native-container/src/News.tsx" ; function News( params ) { return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactNative.View, { children: /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_reactNative.SafeAreaView, { children: [ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactNative.Text, { style: { color: 'red' }, children: "Hello ReactNative" }), /*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactNative.Switch, { children: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_reactNative.Text, { children: "\u5F00\u5173" }) })] }) }); } },545,[1,50,2,91], "src/News.tsx" ); __d(function(global, require, _importDefaultUnused, _importAllUnused, module, exports, _dependencyMapUnused) { module.exports = { "name" : "AwesomeProject" , "displayName" : "AAAAA" } ; },546,[], "app.json" ); //4.require方法调用 __r(54); __r(0); |
从上面内容可知,jsbundle有四部分组成:
1.var 全局变量声明,包括对当前运行环境的定义,bundle 的启动时间、Process进程环境相关信息;
2.在(function() { })() 闭包中定义了对 define(__d)、 require(__r)、clear(__c) 的支持,以及 module(react-native及第三方dependences依赖的module) 的加载逻辑;
3.使用__d定义的模块信息,包括RN框架源码 js 部分、自定义js代码部分、图片资源信息,供 require 引入使用;
4.通过require执行模块代码,找到 __d 定义的代码块并执行,其中require中的数字即为 __d定义行中最后出现的那个数字。
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-03-15 iOS转场之present与dismiss的使用