React-Native-Remote-Update - 使用React-Native實現app熱更新的一次實踐

jopen 8年前發布 | 138K 次閱讀 移動開發 React-Native-Remote-Update

使用React-Native實現app熱部署的一次實踐

效果

原理

demo中執行熱部署的實現流程如下:

最新版本的React Native版本中,加入了如下支持:

/**
     * Path to the JS bundle file to be loaded from the file system.
     *
     * Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle}
     */
    public Builder setJSBundleFile(String jsBundleFile) {
      mJSBundleFile = jsBundleFile;
      return this;
    }

這是熱部署的突破口,由于React Native加載的js文件都打包在bundle中,通過這個方法,可以設置app加載的bundle來源。若檢測到遠端存在更新的bundle文件,下載好后重新加載即可。

為了在運行中重新加載bundle文件,查看ReactInstanceManager的源碼,找到如下方法:

private void recreateReactContextInBackground(JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
    UiThreadUtil.assertOnUiThread();

    ReactContextInitParams initParams = new ReactContextInitParams(jsExecutor, jsBundleLoader);
    if (!mIsContextInitAsyncTaskRunning) {
      // No background task to create react context is currently running, create and execute one.
      ReactContextInitAsyncTask initTask = new ReactContextInitAsyncTask();
      initTask.execute(initParams);
      mIsContextInitAsyncTaskRunning = true;
    } else {
      // Background task is currently running, queue up most recent init params to recreate context
      // once task completes.
      mPendingReactContextInitParams = initParams;
    }
  }

雖然這個方法是private的,不過不要緊,使用反射調用就行啦:

private void onJSBundleLoadedFromServer() {

    try {
            Class<?> RIManagerClazz = mReactInstanceManager.getClass();
            Method method = RIManagerClazz.getDeclaredMethod("recreateReactContextInBackground",
                    JavaScriptExecutor.class, JSBundleLoader.class);
            method.setAccessible(true);
            method.invoke(mReactInstanceManager,
                    new JSCJavaScriptExecutor(),
                    JSBundleLoader.createFileLoader(getApplicationContext(), JS_BUNDLE_LOCAL_PATH));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }

總結

使用React Native進行熱部署是可行的,只要遠程提供打包好的bundle,app下載后重新加載即可;

但是,這樣的方案也具有一定的局限性:

React Native在使用View的時候,這些View是要經過本地定制的,并且將相關方法通過RCT_EXPORT_METHOD暴露給js,js端才能正常使用。

比如,我們在新版本中使用了一個PullToRefreshListView,這個View必須在Native中被定制過,此時,單純的更新bundle就會報錯了,需要重新發包才能解決。

項目地址: https://github.com/fengjundev/React-Native-Remote-Update

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!