Skip to content

Commit c1fb504

Browse files
authored
chore: release 3.0 (#67)
1 parent 7fe1680 commit c1fb504

23 files changed

+1003
-1
lines changed

docs/docusaurus.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ const config = {
4646
'2.x': {
4747
label: '2.x',
4848
},
49+
'3.x': {
50+
label: '3.x',
51+
},
4952
},
5053
},
5154
blog: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"label": "API reference",
3+
"position": 4,
4+
"link": {
5+
"type": "generated-index"
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# isCached
6+
7+
### `isCached` - check if screen/component was already preloaded
8+
9+
Call this function if you need to check whether the component was already loaded or not:
10+
11+
`isCached(componentName: string)` => `boolean`
12+
13+
- `componentName` - name of the component/screen that was registered in `register` function
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# preload
6+
7+
### `preload` - as an optimization, you can also decide to preload a component before it gets rendered.
8+
9+
You can select what you'd like to load:
10+
- `preload().component(componentName: string)` => `Promise`
11+
12+
- `componentName` - name of your component, that was registered via `register` function
13+
14+
- `preload().group(groupName: string)` => `Promise`
15+
16+
- `groupName` - name of your group, that was specified in `register` function
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# register
6+
7+
### `register` - allow you wrap your component/screen into separate bundle
8+
9+
`register<P>(params: Object)` - return react component (`P` - component props type, use only in TypeScript projects).
10+
11+
Params:
12+
- `name` (optional) - you need to specify this param only if you will call `preload` function for this screen
13+
- `require` - function, that return your presentation component. Example: `() => require('./Presentational.js')` (**DEPRECATED - will be removed in future releases. Use `loader` instead**)
14+
- `loader` - function, that return your presentation component. Example: `() => import('./View')`
15+
- `group` (optional) - You need specify it, only if you need to `preload` entire group of screens
16+
- `static` (optional) - all static members from your presentational component.
17+
- `cached` (optional) - Default: `true`. Set to `false` if you don't need cache your screens. _**Warning:**_ it may decrease performance of your application.
18+
- `placeholder` (optional) - React component which will display during screen loading. Should specify if you don't use `preload` for this screen.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"label": "Fundamentals",
3+
"position": 1,
4+
"link": {
5+
"type": "generated-index"
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# Basic usage
6+
7+
This library contains pretty minimalistic API. And we will look on this a little bit later.
8+
Let's assume we have next folder structure
9+
10+
.
11+
├── ...
12+
├── Login # Folder with your screen
13+
│ ├── View.jsx # Your presentational component
14+
│ ├── styles.ts # Your styles for the component
15+
│ └── index.ts # Your entry point to the screen
16+
└── ...
17+
18+
And your `index.ts` file looks like this:
19+
20+
```js
21+
import View from './View';
22+
23+
export default View;
24+
```
25+
26+
You can easily rewrite it with this library!
27+
28+
```js
29+
import { register } from 'react-native-bundle-splitter';
30+
31+
export default register({ loader: () => import('./View') });
32+
```
33+
34+
That's all! You can reload your application to see the results and guarantee this changes will not break anything.
35+
36+
:::tip
37+
If you are using TypeScript in your project, then you may want to specify `Props` for your lazily loaded component. You can do it in this way:
38+
39+
```ts
40+
import { register } from 'react-native-bundle-splitter';
41+
import type {Props} from './types';
42+
43+
export default register<Props>({ loader: () => import('./View') });
44+
```
45+
:::
46+
47+
:::caution Avoid direct references to lazy-loaded file
48+
Please, be sure, that you have such `index.ts` file. This library works only in case if you don't have any `import` statements which refers to your file. In other words: be sure that you do **NOT** import this file (`View`) from anywhere in your code.
49+
:::
50+
51+
To assure, that you are doing everything in correct way this library provides a way for checking the performance.
52+
53+
In order to capture your metrics you should change your `App.js` file:
54+
55+
```diff
56+
import React, { Fragment, PureComponent } from 'react';
57+
...
58+
+import { investigate } from 'react-native-bundle-splitter/dist/utils';
59+
60+
+console.log('Bundle Info: ', investigate());
61+
62+
class App extends PureComponent {
63+
...
64+
}
65+
```
66+
67+
Usually your output from log will look like `Bundle Info: { loaded: 2731, waiting: 141 }`. Such way allows to understand is your changes make sense or not. After adding new screen to this library count of loaded files should be decreasing. Of course, ideal way is when you load as minimum modules as you can. For example only one page with login. In this case your startup time will be almost the same as just created application. And splash screen will not take a lot of time.
68+
But it depends absolutely on you and yours architecture solutions. Feel free to play around this library and find suitable way for separating your files.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# Enabling Ram Bundle
6+
7+
## RAM... What is it? About RAM Bundle format
8+
9+
### RAM Bundle format
10+
11+
[Metro](https://facebook.github.io/metro/) bundler for react-native offers special format - RAM (Random Access Memory). RAM bundle is a new format of React Native application packaging that helps to optimize load times of your app.
12+
13+
You can read [more](https://facebook.github.io/metro/docs/bundling) about this bundle format.
14+
15+
### Context and motivation
16+
17+
React Native is a still JS application. In the browser all your JavaScript and modules have to be bundled (combined, minified, and maybe even uglified) before deploying. As a result, you drastically reduce the number of files (usually down to one) along with the total size of the code you’re serving by removing all information not necessary for production, i.e., mercilessly rewriting function and variables names, deleting code comments, and so on.
18+
19+
The whole procedure stays pretty much the same when you’re developing a React Native app. It’s still (React-flavored) JavaScript you write there, right?
20+
21+
But here’s a problem: when your app grows, so does the bundle size, and let’s just say that React Native apps are usually more than a few kilobytes in size. The heavier your app bundle is, the more time it needs to be fully loaded into memory, parsed, and executed, before even showing you a splash screen!
22+
23+
However, the difference is that a React Native app is executed in a different environment — on your mobile device running Android or iOS (coming soon on Windows devices) rather than in your browser. This allows React Native to be smarter about what it loads to memory and when. And this is when RAM bundles come into play: they define a new bundling format that enables on-demand loading of individual app modules, resulting in a smoother user experience.
24+
25+
### Formats
26+
27+
The official way to bundle your React Native apps at the moment is using Metro Bundler, which currently supports the following bundling formats:
28+
29+
- **Plain**: Good old, pure JavaScript bundle. This is the default type that doesn’t offer any optimizations.
30+
31+
- **Indexed RAM Bundle**: This format defines a binary file with a header that can be used for quickly finding a specific module. For example, the header can tell us that module number 23 (all JavaScript modules in React Native apps are given numerical identifiers) can be found at offset 320 in the RAM bundle file, and has a length of 430 bytes. How does this help us? React Native runtime now doesn’t need to read the entire bundle file into memory, and can load specific modules only when they are needed (e.g., via inline requires).
32+
33+
- **File RAM Bundle**: With this approach, every module is stored in a separate file with the name `js-modules/${id}.js`, where `${id}` is the module’s ID. This format is used by default on Android devices but has the same purpose: to have fast access to individual modules in your bundle.
34+
35+
## Enabling RAM Bundle feature in your application
36+
37+
For enabling this format in your application you need to do pretty simple steps for each platform.
38+
39+
:::tip Enable per platform
40+
Although enabling RAM Bundle format is recommended for both platforms, you can only enable it for one if necessary.
41+
:::
42+
43+
### Android
44+
45+
Open `android/app/build.gradle` and edit your file in the following way.
46+
47+
```diff
48+
project.ext.react = [
49+
entryFile : "index.js",
50+
+ bundleCommand : "ram-bundle",
51+
+ extraPackagerArgs : ["--indexed-ram-bundle"]
52+
...
53+
```
54+
55+
:::info
56+
You can choose between formats, since Android support both format (indexed and file). But since iOS support only `indexed` format, would be reasonable to keep both platform in consistent and use `indexed` format. But if you decided for some reasons to use `file` format, you don't need to add `extraPackagerArgs: ["--indexed-ram-bundle"]` line. By default android uses `file` format.
57+
:::
58+
59+
:::caution Hermes enabled
60+
If you are trying to enable this feature with Hermes engine, you may faced with application crash. It's a known [issue](https://github.com/facebook/react-native/issues/25730). As a temporary solution you can don't activate this bundle format for Android, since Hermes is using similar [mechanism](https://github.com/facebook/react-native/issues/25730#issuecomment-514115115).
61+
:::
62+
63+
### iOS
64+
65+
For enabling RAM format for iOS you need to open XCode, select the project, go to `Build Phases`, and edit phase `Bundle React Native code and images`. Before `../node_modules/react-native/scripts/react-native-xcode.sh` you need to add `BUNDLE_COMMAND="ram-bundle"`:
66+
67+
```diff
68+
+export BUNDLE_COMMAND="ram-bundle"
69+
export NODE_BINARY=node
70+
../node_modules/react-native/scripts/react-native-xcode.sh
71+
```
72+
73+
### macOS
74+
75+
Enabling `RAM Bundles` on macOS should be done exactly in the same way as for `iOS`
76+
77+
Just open macOS specific project and repeat the same steps.
78+
79+
### web
80+
81+
No extra steps for `web` as there is no such term as "RAM bundles". Webpack itself will be able to split your JS bundle into small parts and will load them as soon as they are needed.
82+
83+
## Summary
84+
85+
Basically you have completed native set up and now you are ready for using this library!
86+
87+
:::tip
88+
To be sure, that your application isn't broken after all manipulations you can rebuild your application and see, that it works correctly.
89+
:::
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# Getting started
6+
7+
## What to expect
8+
9+
Splitting your bundle into small pieces allows you reduce size of main bundle, which is loaded on application startup. It means, that you can load only necessary things, such as login pages, which user inevitably will see if open an application. And only "necessary" things will be in main bundle. Thus, this means that **the time of initial launch of the application will be minimized** and **memory consumption will be decreased**, since often in applications is a lot of code (components and screens) that the user may simply not see.
10+
11+
import BundleSplittingImageUrl from "@site/static/img/bundle-splitting.png";
12+
13+
<p style={{ textAlign: "center" }}>
14+
<img src={BundleSplittingImageUrl}></img>
15+
<i>
16+
On green part of this picture, you can see that all components/screens are
17+
divided into different groups. It allows you to load the application much
18+
faster, because instead of loading the entire bundle (red picture), you can
19+
load only the parts that you need.
20+
</i>
21+
</p>
22+
23+
## What does this package do?
24+
25+
This package is built on top of **RAM** bundles. In addition to the base functionality provided by React Native, it allows you to:
26+
27+
- avoid boilerplate code (you don't need to write code as per react-native docs - you can simply wrap your component into `register` function);
28+
- use `preload` API (when you can load screens in advance and the transition to them will be as if the entire bundle was loaded at once);
29+
- and has web support.
30+
31+
## Features
32+
33+
This library is add-on on react-native API. But this library has some features, and here is list of them:
34+
35+
- **Enhanced cache management**. This library provide a way for caching yours components. This mechanism allows you to improve performance of your application and help to avoid unnecessary reloading yours components, which were already loaded.
36+
- **Ability to preload component**. You can preload components in background, which user may see in the nearest future. It allows to make UI experience more smooth and use your components from cache without any intermittentions.
37+
- **Supporting all navigation libraries**. This library is compatible with all most known navigation libraries, such as [react-navigation](https://reactnavigation.org/), [react-native-navigation](https://wix.github.io/react-native-navigation/#/) and more others.
38+
39+
## Installation
40+
41+
Install the react-native-bundle-splitter package in your React Native project.
42+
43+
```bash
44+
yarn add react-native-bundle-splitter
45+
# or with npm
46+
# npm install react-native-bundle-splitter --save
47+
```
48+
49+
This module does not use any native (platform) dependencies and does not need to be linked. So installation process basically is finished. But you also need to enable `RAM bundles` feature in your application. To see how to do it, please read [the guide](./enabling-ram-bundle).
50+
51+
:::tip Minimal react-native version
52+
You need to use react-native 0.60 or higher, since feature with inline requires is available out-of-box only from this version.
53+
:::
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"label": "Guides",
3+
"position": 2,
4+
"link": {
5+
"type": "generated-index"
6+
}
7+
}

0 commit comments

Comments
 (0)