Экраны с отложенной загрузкой с React Native Router Flux - PullRequest
0 голосов
/ 22 сентября 2018

В моем приложении React Native есть несколько экранов.

Я использую React Native 0.56 и React Native Router Flux.

Есть ли способ для экрана, чтобы загрузить весь свой импорткогда экран действительно нужен, а не когда приложение запускается и пакет анализируется?

Из-за этого увеличивается время начальной загрузки приложения.

Я наткнулся на формат ОЗУ вРаздел Реагировать на родную производительность.https://facebook.github.io/react-native/docs/next/performance.html#enable-the-ram-format

Как уменьшить количество модулей в загруженных именах модулей ??

index.android.js

import { AppRegistry } from 'react-native';
import AppContainer from './src/';

const modules = require.getModules();
const moduleIds = Object.keys(modules);
const loadedModuleNames = moduleIds
  .filter(moduleId => modules[moduleId].isInitialized)
  .map(moduleId => modules[moduleId].verboseName);
const waitingModuleNames = moduleIds
  .filter(moduleId => !modules[moduleId].isInitialized)
  .map(moduleId => modules[moduleId].verboseName);

// make sure that the modules you expect to be waiting are actually waiting
console.log(
  'loaded:',
  loadedModuleNames.length,
  'waiting:',
  waitingModuleNames.length
);

// grab this text blob, and put it in a file named packager/modulePaths.js
console.log(`module.exports = ${JSON.stringify(loadedModuleNames.sort())};`);

AppRegistry.registerComponent('Roots', () => AppContainer);

navigation / index.js

/**
 * App Navigation
 *
 */
import React from 'react';
import { Actions, Scene, ActionConst, Stack } from 'react-native-router-flux';

// Consts and Libs
import { AppConfig } from '@constants/';

// Components

// Scenes
import Placeholder from '@components/general/placeholder/index';
import ExperiencesScenes from '@navigation/experiences';

import AuthScenes from '@navigation/auth';
import MediateScene from '@navigation/mediate';
import HomeScene from '@navigation/home';
import SearchScene from '@navigation/search';
import NoticesScene from '@navigation/notices';
// import ShortlistedMapScene from '@navigation/shortlisted_map';

import IntroScene from '@navigation/intro';
import AssistantScene from '@navigation/assistant';
import NotificationSettingsScene from '@navigation/notification_settings';
import HighlightScene from '@navigation/highlight';
import TransportScene from '@navigation/transport';
import HelpScene from '@navigation/help';
import FaqScene from '@navigation/faq';
import DynamicListScene from '@navigation/component_list';
import BrandCoverScene from '@navigation/brand_cover';
import ListingsScene from '@navigation/listings';
import ShorlistedScene from '@navigation/shortlisted_list';
import SettingsScene from '@navigation/settings';
import OnTheWayScene from '@navigation/on_the_way';
import ItinerariesScene from '@navigation/itineraries';
import TempScene from '@navigation/temp';
import TipsScene from '@navigation/tips';
import SimpleSwipe from '@navigation/simple_swipe';
import Cities from '@navigation/cities';
// import ReferralScene from '@navigation/referral';

/* Routes ==================================================================== */
export default Actions.create(
    <Stack key={'root'}>

        {MediateScene}

        {IntroScene}

        {HomeScene}

        {AssistantScene}

        {SearchScene}

        {NoticesScene}

        {ShorlistedScene}

        {SettingsScene}

        {ListingsScene}

        {TipsScene}

        {BrandCoverScene}

        {AuthScenes}

        {ExperiencesScenes}

        {NotificationSettingsScene}

        {HighlightScene}

        {TransportScene}

        {HelpScene}

        {FaqScene}

        {DynamicListScene}

        {OnTheWayScene}

        {ItinerariesScene}

        {SimpleSwipe}

        {Cities}
    </Stack>
);

Код навигации выглядит примерно так:

import React from 'react';
import { Scene, ActionConst } from 'react-native-router-flux';

// Consts and Libs
import { AppConfig } from '@constants/';
import { AppStyles, AppSizes, AppColors } from '@theme/';
// Scenes
import BrandCoverScreen from '@screens/brand_cover/index';


const navbarPropsTabs = {
    ...AppConfig.navbarProps,
    hideNavBar: true,
};

/* Routes ==================================================================== */
const scenes = (
    <Scene 
        {...navbarPropsTabs}
        key={"brand_cover"} 
        component={BrandCoverScreen} >
    </Scene>
);

export default scenes;

1 Ответ

0 голосов
/ 25 сентября 2018

Это немного сложнее, чем кажется - и это не относится только к реагирующему нативному маршрутизатору - потребуется поддержка metro, чтобы разбить JS-пакет на более мелкие части и правильно загрузить его.

Кажется, что Expo может сделать что-то подобное с активами, но для кода JS я видел только что-то близкое к этому, взламывая код react-native в этой статье:

Lazy Bundle Загрузка вReact Native от Karan Thakkar https://medium.com/react-native-training/lazy-bundle-loading-in-react-native-5f717b65482a

А вот репозиторий GitHub с кодом, использованным в статье: https://github.com/karanjthakkar/RNLazyBundleLoading

В случае, если статья или репозиторий переходит в автономный режим, вот разницаон также показал в статье (это разница между оригинальным react-native и его форком:

diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h
index 1995801ffcaa..cf1609bc9614 100644
--- a/React/Base/RCTBridge+Private.h
+++ b/React/Base/RCTBridge+Private.h
@@ -90,6 +90,12 @@ RCT_EXTERN void RCTVerifyAllModulesExported(NSArray *extraModules);
  */
 - (void)start;

+/**
+ * Called on the child bridge to run the executor and start loading
+ * the partial bundle
+ */
+- (void)lazyStart;
+
 /**
  * Used by RCTModuleData to register the module for frame updates after it is
  * lazily initialized.
diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h
index 5222a15b5ca7..d0be4652f4f5 100644
--- a/React/Base/RCTBridge.h
+++ b/React/Base/RCTBridge.h
@@ -223,4 +223,9 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
  */
 - (BOOL)isBatchActive;

+/**
+ * Load a custom bundle into an existing bridge instance
+ */
+- (void)loadCustomBundle:(NSString *)bundleName;
+
 @end
diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m
index cee9aa0463e1..c1b3ae107599 100644
--- a/React/Base/RCTBridge.m
+++ b/React/Base/RCTBridge.m
@@ -319,6 +319,13 @@ - (void)setUp
   RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
 }

+-(void)loadCustomBundle:(NSString *)bundleName
+{
+  _bundleURL = [NSBundle.mainBundle URLForResource:bundleName withExtension:@"jsbundle"];
+
+  [self.batchedBridge lazyStart];
+}
+
 - (BOOL)isLoading
 {
   return self.batchedBridge.loading;
diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm
index 4b7aaf375e5b..32df68ac43ec 100644
--- a/React/CxxBridge/RCTCxxBridge.mm
+++ b/React/CxxBridge/RCTCxxBridge.mm
@@ -382,6 +382,29 @@ - (void)start
   RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
 }

+- (void)lazyStart
+{
+  __weak RCTCxxBridge *weakSelf = self;
+
+  __block NSData *sourceCode;
+  [self loadSource:^(NSError *error, RCTSource *source) {
+    if (error) {
+      [weakSelf handleError:error];
+    }
+
+    sourceCode = source.data;
+    RCTCxxBridge *strongSelf = weakSelf;
+    if (sourceCode) {
+      [strongSelf executeSourceCode:sourceCode sync:NO];
+    }
+  } onProgress:^(RCTLoadingProgress *progressData) {
+#if RCT_DEV && __has_include("RCTDevLoadingView.h")
+    RCTDevLoadingView *loadingView = [weakSelf moduleForClass:[RCTDevLoadingView class]];
+    [loadingView updateProgress:progressData];
+#endif
+  }];
+}
+
 - (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad onProgress:(RCTSourceLoadProgressBlock)onProgress
 {
   NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
...