Need help with react-native-lazy-index?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

microsoft
166 Stars 10 Forks MIT License 128 Commits 1 Opened issues

Description

RAM bundle friendly, bundle-time generated `index.js`

Services available

!
?

Need anything else?

Contributors list

react-native-lazy-index

Node CI npm version

react-native-lazy-index
is a RAM bundle friendly, bundle-time generated
index.js
. Improve your app startup time by only loading features you'll use on demand.

For information on RAM bundles and inline requires, see React Native Performance.

If you use Haul, also take a look at their documentation.

Installation

npm install --save react-native-lazy-index

Usage

react-native-lazy-index
uses
babel-plugin-codegen
, so you'll need to configure Babel to include it. The recommended way is to add it to your
.babelrc
:
{
  "plugins": ["codegen"]
}

In your

package.json
, add a section called
"experiences"
with the features that should be lazy loaded. In the example below, we've listed four packages:
{
  "name": "my-awesome-app",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@awesome-app/some-feature": "*",
    "@awesome-app/another-feature": "*",
    "@awesome-app/yet-another-feature": "*",
    "@awesome-app/final-feature": "*",
    "react": "16.13.1",
    "react-native": "0.63.4",
    "react-native-lazy-index": "^2.0.0"
  },
  "experiences": [
    "@awesome-app/some-feature",
    "@awesome-app/another-feature",
    "@awesome-app/yet-another-feature",
    "@awesome-app/final-feature"
  ]
}

That's it!

Why

With a naive

index.js
, all features will be loaded when your app starts and React Native is initialized for the first time.
import "@awesome-app/some-feature";
import "@awesome-app/another-feature";
import "@awesome-app/yet-another-feature";
import "@awesome-app/final-feature";

By loading features on demand, we can improve app startup time.

With

react-native-lazy-index
, we no longer load all features up front. Instead,
index.js
wraps calls to
AppRegistry.registerComponent
and
BatchedBridge.registerCallableModule
, deferring the import of a feature until it is used. Features that are never used, are never loaded.

When you import

react-native-lazy-index
, something similar to below is generated:
const { AppRegistry } = require("react-native");
const BatchedBridge = require("react-native/Libraries/BatchedBridge/BatchedBridge");

AppRegistry.registerComponent("SomeFeature", () => { // We'll import the module the first time "SomeFeature" is accessed. require("@awesome-app/some-feature"); // "SomeFeature" is now overwritten and we can return the real component. // Subsequent calls to "SomeFeature" will no longer go through this wrapper. return AppRegistry.getRunnable("SomeFeature").componentProvider(); });

BatchedBridge.registerLazyCallableModule("AnotherFeature", () => { // We'll import the module the first time "AnotherFeature" is accessed. require("@awesome-app/another-feature"); // "AnotherFeature" is now overwritten and we can return the real component. // Subsequent calls to "AnotherFeature" will no longer go through this // wrapper. return BatchedBridge.getCallableModule("AnotherFeature"); });

AppRegistry.registerComponent("YetAnotherFeature", () => { // We'll import the module the first time "YetAnotherFeature" is accessed. require("@awesome-app/yet-another-feature"); // "YetAnotherFeature" is now overwritten and we can return the real // component. Subsequent calls to "YetAnotherFeature" will no longer go // through this wrapper. return AppRegistry.getRunnable("YetAnotherFeature").componentProvider(); });

AppRegistry.registerComponent("FinalFeature", () => { // We'll import the module the first time "FinalFeature" is accessed. require("@awesome-app/final-feature"); // "FinalFeature" is now overwritten and we can return the real component. // Subsequent calls to "FinalFeature" will no longer go through this wrapper. return AppRegistry.getRunnable("FinalFeature").componentProvider(); });

Troubleshooting

If you're having trouble with undetected components, there are a couple of things you should look out for.

First parameter must be a string literal

react-native-lazy-index
cannot evaluate the name passed to
AppRegistry.registerComponent()
or
BatchedBridge.registerCallableModule()
unless it is a string literal. For instance, if you have something like this in code:
const appName = "MyApp";

AppRegistry.registerComponent(appName, () => { ... });

You'll need to inline the string:

AppRegistry.registerComponent("MyApp", () => {
  ...
});

react-native-lazy-index
outputs warnings when it detects these instances. If changing the code is not feasible, you can also manually declare all entry points.

My components are still not found

react-native-lazy-index
avoids scanning dependencies too deeply to reduce its impact on the build time. If your registrations lie too deep within a dependency, it may have bailed out before reaching them. There are a couple of things you can do to help
react-native-lazy-index
find your components:
  1. If you have access to the source code, you can move your registrations further up, closer to the entry point of your dependency.
  2. You can increase the max depth by setting the environment variable
    RN_LAZY_INDEX_MAX_DEPTH
    . The default is currently set to 3. Note that changing this setting may significantly impact your build time.
  3. If neither is feasible, you can also manually declare all entry points.

I want to manually declare all entry points myself

You can skip scanning by manually declaring entry points. The below configuration will generate the same code as the earlier example output:

  "experiences": {
    "SomeFeature": "@awesome-app/some-feature",
    "callable:AnotherFeature": "@awesome-app/another-feature",
    "YetAnotherFeature": "@awesome-app/yet-another-feature",
    "FinalFeature": "@awesome-app/final-feature"
  }

By default, a call to

AppRegistry
is generated using the key as the app key, and the value is the name of the module containing the app. If the key is prefixed with
callable:
, a call to
BatchedBridge
will be generated.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.