1.新建测试项目
react-native init subpackage_test
2.添加公共组件库
{
"name": "subpackage_test",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.6.3",
"react-native": "0.58.6",
"react-native-fast-image": "5.1.2",
"react-native-cz-alertview": "git+https://github.com/chenzhe555/react-native-cz-alertview.git",
"react-native-cz-alipay-calendar": "git+https://github.com/chenzhe555/react-native-cz-alipay-calendar.git",
"react-native-cz-button": "git+https://github.com/chenzhe555/react-native-cz-button.git",
"react-native-cz-calendar": "git+https://github.com/chenzhe555/react-native-cz-calendar.git",
"react-native-cz-common-modal": "git+https://github.com/chenzhe555/react-native-cz-common-modal.git",
"react-native-cz-flatlist": "git+https://github.com/chenzhe555/react-native-cz-flatlist.git",
"react-native-cz-image-placeholder": "git+https://github.com/chenzhe555/react-native-cz-image-placeholder.git",
"react-native-cz-inputtext": "git+https://github.com/chenzhe555/react-native-cz-inputtext.git",
"react-native-cz-loading": "git+https://github.com/chenzhe555/react-native-cz-loading.git",
"react-native-cz-navigationview": "git+https://github.com/chenzhe555/react-native-cz-navigationview.git",
"react-native-cz-pack-element": "git+https://github.com/chenzhe555/react-native-cz-pack-element.git",
"react-native-cz-panel": "git+https://github.com/chenzhe555/react-native-cz-panel.git",
"react-native-cz-permission": "git+https://github.com/chenzhe555/react-native-cz-permisson.git",
"react-native-cz-reddot": "git+https://github.com/chenzhe555/react-native-cz-reddot.git",
"react-native-cz-scroll-tab": "git+https://github.com/chenzhe555/react-native-cz-scroll-tab.git",
"react-native-cz-toast": "git+https://github.com/chenzhe555/react-native-cz-toast.git"
},
"devDependencies": {
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "24.3.1",
"jest": "24.3.1",
"metro-react-native-babel-preset": "0.53.0",
"react-test-renderer": "16.6.3"
},
"jest": {
"preset": "react-native"
}
}
3.打基础包
3.1 首先了解下rn打包到基础命令
react-native bundle [options]
builds the javascript bundle for offline useOptions:
--entry-file <path> Path to the root JS file, either absolute or relative to JS root
--platform [string] Either "ios" or "android" (default: "ios")
--transformer [string] Specify a custom transformer to be used
--dev [boolean] If false, warnings are disabled and the bundle is minified (default: true)
--minify [boolean] Allows overriding whether bundle is minified. This defaults to false if dev is true, and true if dev is false. Disabling minification can be useful for speeding up production builds for testing purposes.
--bundle-output <string> File name where to store the resulting bundle, ex. /tmp/groups.bundle
--bundle-encoding [string] Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer). (default: "utf8")
--max-workers [number] Specifies the maximum number of workers the worker-pool will spawn for transforming files. This defaults to the number of the cores available on your machine.
--sourcemap-output [string] File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map
--sourcemap-sources-root [string] Path to make sourcemap's sources entries relative to, ex. /root/dir
--sourcemap-use-absolute-path Report SourceMapURL using its full path
--assets-dest [string] Directory name where to store assets referenced in the bundle
--verbose Enables logging
--reset-cache Removes cached files
--read-global-cache Try to fetch transformed JS code from the global cache, if configured.
--config [string] Path to the CLI configuration file
-h, --help output usage information
各个命令注释已经写得很清楚了,对我们有用的主要就是entry-file 和 bundle-output了,还有后面自定义的时候用到的config 参数
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./bundles/index.ios.bundle --assets-dest ./assets/
此时我们就能打一个正常的js bundle文件。
但是我们发现,我们的业务代码也在里面
3.2 Metro bundle自定义config
这个时候,需要了解到RN从0.46.0版本开始,就将RN的打包模块packager分离出来,单独创建了一个项目用于RN的打包,Metro Bundler:https://facebook.github.io/metro
要对打包进行自定义处理,需要用到metro打包命令中的config参数(https://facebook.github.io/metro/docs/en/configuration),其中对我们有用的主要是
由于Metro打包的时候,会给每个模块都分配一个ID,在后面文件都调用时直接调用对应都ID即可,所以我们必须保证基础包的ID唯一,不然再有其它模块改动的时候,会因为ID变化导致找不到module,此处需要用到createModuleIdFactory函数。
在打基础和业务包的时候,有些模块我们不希望打入到bundle文件中,所以需要筛选器函数processModuleFilter,过滤那些我们不希望打入bundle中的包。
3.3 新增config文件
在项目工程路径下新建 basic.js 和 basic.config.js文件:
basic.js
basic.config.js
3.4 打包基础包
react-native bundle --entry-file basic.js --platform ios --dev false --bundle-output ./bundles/basic.ios.bundle --assets-dest ./assets/ --config /Users/yunshan/Desktop/Project/RN/subpackage_test/basic.config.js
config要写绝对地址,因为执行环境是在CLI目录下,不在当前目录,./basic.config.js 的话是找不到这个文件的
4.打业务包
4.1 新建业务测试文件detail.js 和 detail.config.js,还有业务页面 ./src/pages/detail/index.js
detail.js
detail.config.js
./src/pages/detail/index.js
4.2 打包业务bundle
react-native bundle --entry-file detail.js --platform ios --dev false --bundle-output ./bundles/detail.ios.bundle --assets-dest ./assets/ --config /Users/yunshan/Desktop/Project/RN/subpackage_test/detail.config.js
5.按需加载bundle
现在分包已经基本完成,>=1个基础包,>=1个业务包。
以下测试Demo只建1个基础包和1个业务包
5.1 将打包的基础包basic.ios.bundle和业务包detail.ios.bundle添加到项目中
5.2 在App启动的时候预加载基础包
5.3 在详情页VC加载的时候加载业务包
5.4 输出信息证明先加载了基础包,然后加载了业务包
PS:其中iOS端改动较小,只需要对RCTBridge进行扩展暴露接口:
-(void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync;