React Native 0.31 Bundle 預載入優化

markzhai發表於2016-08-23

使用 React Native 開發混合應用的過程中,我們在打完 bundle 進 release 包後,會發現第一次進入頁面(React 的 Activity)會有一個短暫的白屏過程(在真機上近 1秒,在模擬器上比較快,在 200毫秒 左右),而且在完全退出後再進入,仍然會有這個白屏。

仔細檢視載入過程(其實猜猜都能知道)後可以發現,這個過程就是在載入我們的 js bundle,通常即便是一個小的 RN 應用(混合應用中的子業務),也會動輒到 1MB 的大小,除非是完整的 RN 應用,可以把這個當做是啟動速度,否則這樣的載入速度都是對使用者體驗的很大傷害。

於是我們決定進行 Bundle 預載入的優化。

專案原始碼上傳在:markzhai/react-native-preloader,稍後會上傳到 maven,版本號會和 rn 保持一致。

耗時操作

ReactActivityonCreate 方法:

打點後可以發現耗時的其實是

  • createRootView();
  • startReactApplication();

這兩個操作,所以考慮只需要提前建立 ReactRootView 進行 render,之後直接掛載該 view 上去即可。

預載入

建立預載入類 ReactPreLoader

在 init 操作中,我們通過 ReactInfo 快取把 view 快取在本地的 ArrayMap

值得注意的是 onDestroy,在 ReactActivity 銷燬後,我們需要把 view 從 parent 上解除安裝下來。

使用預載入的 view

使用預載入的 View,就需要侵入 activity 的建立過程,我們無法再使用 RN 庫提供的 ReactActivity,只能建立自己的,以下列出修改的方法,其他方法照抄 ReactActivity

使用

在進入該 RN activity 的上一個 activity 呼叫:

ReactCardActivity 繼承我們自己的 ReactActivity:

優化後可以達到瞬間載入。

已知的坑

由於進行了預載入,目前已知的問題是 Modal 無法顯示 —— 因為 Modal 在 Android 的實現使用了 Dialog,而該 View 將建立 ReactRootView 的 context 作為引數傳給了 Dialog,而不是實際執行時所在的 Activity context。檢視原始碼可以驗證(com.facebook.react.views.modal)。

TimePickerAndroid 這類 picker 則沒有問題。見 issue 9496

作為規避方案,目前使用 MutableContextWrapper 進行 context 替換。見 GitHub 上的具體實現(感謝評論裡的 Lovecraft 提供的方案)。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

React Native 0.31 Bundle 預載入優化 React Native 0.31 Bundle 預載入優化

相關文章