How to separate js bundle to frameworkBundle and appBundle?
js bundle is more 500k+, but business code is less then 10%
@satya164
Hey Richard-Cao, thanks for reporting this issue!
React Native, as you've probably heard, is getting really popular and truth is we're getting a bit overwhelmed by the activity surrounding it. There are just too many issues for us to manage properly.
react-native
or for more real time interactions, ask on Discord in the #react-native channel.Wow, I just wanna fix this issue, and have tried https://github.com/mjohnston/react-native-webpack-server/ but failed.
Also I tried to get a dev version bundle and copy the framework code as framework.jsbundle, but when I package the business code, I cannot analysis the correct dependencies.
Looking forward this solutions~~~~
@Richard-Cao IOS also have this issue~~
@Creemli Looking forward……
@Richard-Cao Help to remove the [Android] tag and then more people can search this issue.
@Creemli ok
What's the purpose of splitting the bundle? Is it just to make incremental app updates lighter weight, or is there some runtime goal you're trying to accomplish?
both @corbt
To help me understand the scope of this, what are the use cases for this beyond just making lighter-weight app updates (which I get)?
@corbt Yeah, this can make user download less code when updating.
And if we can separate them, we maybe not have to bundle the whole codes, we can combine any business project with the framework code, it's lighter, I think.
I think @martinbigio was looking into this.
Yeah, we were looking into this mostly to help on TTI but decided to pursue another approach, namely unbundling
. To make code downloading faster it's not actually necessary to have multiple bundles but to use a "more clever" protocol (i.e.: one that could send diffs only).
@martinbigio cool
If the main use case for this is just to have smaller updates, then I don't think bundle-splitting is the best solution. There should just be some library that manages updating the JS bundle file using versioned diffs. Such a solution would perform strictly better than bundle-splitting in the size of the updates it would need to send, and would also require less user intervention (in deciding where to split the bundle) to get right.
This would probably make more sense in something like Code Push than in React Native core.
Another possible use is to lazy load parts of a (bigger) app at runtime to reduce startup time. Or is that unlikely to make a difference?
I can give an example of what is being talked about here.
I have a tabbed UI app that already has a bunch of native code already written (iOS and Android). React Native tabs exist side by side with other webview and native tabs. For this scenario, I am having to load all of the app code (core + tab 1 + tab 2 + tab 3) for each tab. Splitting the bundle would mean that:
Also, what is unbundling
?
ref #570
any solution?
any updates?
Ah, try this: https://github.com/ctripcorp/moles-packer
any progress?
looking forward to updates
Looking forward...and...what is unbundling?
@Creemli moles-packer only resolve the propblem separate js bundle, but how to load them in native module?
Hi @martinbigio, @corbt,
Our guys have been develop APPs with RN Integration for a long time. And we think bundle-splitting is also usefull in these scenarios (maybe not limited to Integration).
ReactRootView
in our App, currently we should bundle out two _jsbundle_ files both independent and overall with base codes, it includes many duplicated. (In order to save space, I omit the --platform
, .ios
, .android
here)
This simple way seems like the DllPlugin in webpack:
Build _base.jsbundle_. Meanwhile records it's dependecies list and save it, for example, named by _base.manifest.json_ (output to --manifest-output
by cli
).
Build _index1.jsbundle_ with the _base.manifest.json_ passed through --manifest-file
. When resolve modules, use their id from _base.manifest.json_ and skip their definition if they has recorded in the manifest. So a clear business bundle has done!
Build antoher business bundle like the above (We can set a --id-prefix
for module id to prevent override).
Run _base.jsbundle_ in JSContext at a good time (e.g. Native App launch done, enter to a parent Activity/Controller ).
Run _index1.jsbundle_ when user click/open and will enter to this React Native partition.
Run _index2.jsbundle_ or other when user will enter to another React Native partition.
Update business bundle from CDN if needed.
How do you think ? 😄
android can try unbundle. this will separate mian.jsbundle into pieces of js files。
code like:
react-native unbundle --platform android --dev false --entry-file index.ios.js --bundle-output main.jsbundle
@njafei unbundle is not a good design, too many small files in output bundles.
it's very easy to split main.jsbundle to base.bundle.js and business.bundle.js, but you need modify the native code for RN to load different parts.
@mc-zone Amazing!
@jimzhao2012 I don't is a good idea to modify RN code. Mybe could eval business.bundle.js at base.bundle.js?
I hava package react-native code using webpack,https://github.com/yoution/rn-pack ;also support hot load; and split code using commonChunk plugin,also can fix module id in chunk; but I do not know how to load the splited bundle
We are trying to load base bundle & business bundle in IOS, Android. I will update this when succeed using in production.
@jimzhao2012 is there any resource to look deeper into it?
Also, how could we use and pack with unbundle
? I can produce the unbundle files, but I don't know yet how to install and run the unbundle
result and I don't find many resources on how to do it.
For those who wants to try out unbundle, there's a PR documenting it:
https://github.com/facebook/react-native/pull/15317/files
I'm working on an existing app rewrite, to separate js bundles and hot reload are two important feature for me to investigate, reasons are:
Beyond that, we are also interested in bundle encryption/decryption, and file patching, which makes it more useful for commercial app.
+1 mark
Also that can speed up ci/server-side builds. Most of builds has same versions of libs, only code of app changes. We can --reset-cache
for app bundle only.
For example: we have project with 1200 npm packages. android ci build takes about 3m, ios 5. 80% of build time takes building of bunde.js
Also we can bundle it with two package processes to speed up.
Would this be the equivalent to webpack DDL plugin? I made the following question in stackoverflow about the unbundle speed for rebuilds and I am interested in finding a guide to follow the same strategy for react-native.
Maybe it won't be possible for code-push updates or faster app initialization, but I am interested in improving the DX.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.
I never saw a resolution of this issue. it's a very important question and a valuable use-case. unbundling is not a solution and not the same thing as splitting the framework from app. is anyone working on this?
Was anybody able to use unbundling in combination with CodePush?
Most helpful comment
Hi @martinbigio, @corbt,
Our guys have been develop APPs with RN Integration for a long time. And we think bundle-splitting is also usefull in these scenarios (maybe not limited to Integration).
If we could split some initial and definition codes to a _base.jsbundle_ and run it in JSContext previously before users really enter React Native partition, it can decrease user's waiting time .
Just like @Creemli said. If we just use a lock version RN(or update infrequently) , the most of changes and updates is about our business codes. We can also separate some framework code (i.e. React, RN Components, APIs, and even with some other framework) into a base bundle, but business codes in business bundle. So we can fetch business bundle standalone from network and get smaller size with download to hot update. Even without diff it's not too bad. I mean, maybe it's easier to implement than integrate a diff algorithm to the entire work flow.
If we had the _base.jsbundle_ like the above mentioned, we also can make multiple bundle share it as a common library (it's Just like DllPlugin usecase in webpack). Suppose we have two
ReactRootView
in our App, currently we should bundle out two _jsbundle_ files both independent and overall with base codes, it includes many duplicated.Let me generalize my opinion through this picture:
(In order to save space, I omit the
--platform
,.ios
,.android
here)This simple way seems like the DllPlugin in webpack:
Build _base.jsbundle_. Meanwhile records it's dependecies list and save it, for example, named by _base.manifest.json_ (output to
--manifest-output
bycli
).Build _index1.jsbundle_ with the _base.manifest.json_ passed through
--manifest-file
. When resolve modules, use their id from _base.manifest.json_ and skip their definition if they has recorded in the manifest. So a clear business bundle has done!Build antoher business bundle like the above (We can set a
--id-prefix
for module id to prevent override).Run _base.jsbundle_ in JSContext at a good time (e.g. Native App launch done, enter to a parent Activity/Controller ).
Run _index1.jsbundle_ when user click/open and will enter to this React Native partition.
Run _index2.jsbundle_ or other when user will enter to another React Native partition.
Update business bundle from CDN if needed.
How do you think ? 😄