iOS端創建ReactNative容器第一步:打出jsbundle和資源包

react-native的打包流程是通過執行react-native bundle指令進行的。
 
添加構建指令
修改RN項目中的package.json文件,先其中添加構建命令build-release-ios和build-debug-ios
"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項目,執行下面的打包指令進行打包
npm run build-release-ios
或者
yarn build-release-ios

指令執行完成後,打包的產物是放置在了./dest/bundle/目錄之下

0
 
內置打包產物
將jsbundel包和assets資源包拖到項目中,放置到同一個目錄下。
0
然後修改jsbundle的讀取位置,將從服務器讀取改成從本地讀取。
- (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項目中,根據不同的業務類型加載不同的模塊名稱

  RNContainerController * containerVC = [[RNManager sharedInstance] loadWithModuleName:@"News" initialProps:@{}];
  [self presentModalViewController:containerVC animated:YES];

 

0
 
JSBundle產物介紹
 
RN 通過執行react-native bundle打包命令得到產物JSBundle。
"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.全局變量定義
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定義行中最後出現的那個數字。
 
 
 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章