Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code splitting & OTA #70

Closed
zimo888 opened this issue Mar 31, 2017 · 25 comments
Closed

Code splitting & OTA #70

zimo888 opened this issue Mar 31, 2017 · 25 comments

Comments

@zimo888
Copy link

zimo888 commented Mar 31, 2017

How to separate js bundle into framework bundle and user code bundle?
and then ,When we publish a single file to user's cell phone ,We Just need combine a single file to the base bundle.

@grabbou
Copy link
Member

grabbou commented Mar 31, 2017

CC: @axemclion

@grabbou grabbou changed the title How to separate js bundle Code splitting & OTA Mar 31, 2017
@guysegal
Copy link

guysegal commented Apr 4, 2017

so currently haul does not support code splitting? my app had large bundle size (4MB) and it effects app load time. I thought that because haul is based on webpack and webpack supports code splitting that it will be possible to load only what's necessary when app loads and the rest afterwards

@satya164
Copy link
Member

satya164 commented Apr 4, 2017

Webpack needs the DOM to insert script tags when doing code splitting. Since we don't have DOM, it's not possible.

Also, as an app user I'm already used to download large apps, probably lazy loading code will not improve the experience at all.

@axemclion
Copy link

@satya164 Why not use something similar to react-native unbundle. React Native already supports code splitting, we may jsut have to write a custom plugin to insert the hash file to indicate that this is an unbundle operation.

@satya164
Copy link
Member

satya164 commented Apr 4, 2017

Yeah, I think eventually we want to do that. I was just saying that we probably cannot use webpack's code splitting feature as is right now.

@satya164
Copy link
Member

@zamotany
Copy link
Contributor

@satya164 Not sure if it might help, but this #182 changes target to webworker and polyfills importScripts so you can download anything you want and it will be eval'ed.

@timwangdev
Copy link

Is there a way to lazy load modules by using webpack dynamic import() but not result splitted bundles?

@TheLarkInn
Copy link

Wait, even if webpack requires the DOM, that is just for the target: web, if you use target: node, webpack will use just require statements! Has anyone played with this yet?

@thymikee
Copy link
Member

We use web workers target as closest to what plays nice with RN. While migrating to webpack 4 however, we feel like creating our own custom target to get rid of some nasty hacking

@TheLarkInn
Copy link

Besides the importScripts and eval, is there a reason the generic node target wasn't sufficient.

@satya164
Copy link
Member

satya164 commented Feb 15, 2018

@TheLarkInn not that I know of. The only reason is the script loading mechanism. You can check the comments here #182 (comment)

We haven't tried node yet though.

@zamotany
Copy link
Contributor

zamotany commented Feb 15, 2018

Here are the considirations I have when it comes to using node target:

  • RN doesn't have any require, module, __filename, __dirname variables defined, so there cannot be even single require call (unless we provide a async polyfill for it)
  • How would node target download hot-update{.json,.js}?
  • JS engine on Android is ancient and supports only ES5, so no new syntax/APIs in bootstrap code, unless we inject polyfills before it

And most importantly it still has to work properly in webworker, since with attached debugger the JS bundle will be executed in worker context.

@TheLarkInn
Copy link

TheLarkInn commented Apr 24, 2018

Okay so after taking some time to read the dist.unbundle.bundle generated runtime code that RN/Metro created with the --unbundle feature, and discovered. It's not code splitting in the way that we understand it whatsoever.

Rather this works like just splitting out (for no particular rhyme or reason), the module graph into x bundles that access the same globally defined runtime on self.

Turns out webpack.optimize.AggressiveSplittingPlugin() is the exact thing we need to create these splits.

Here is an example of me using a contrived sample:

image

This stiches the runtime with other loaded chunks using self["webpackChunk"](chunkId) which means they really aren't async at all or deferred but rather just separated into a separate file. My guess is that RN handles the file serving when the bundle is needed?

Is there a way to lazy load modules by using webpack dynamic import() but not result splitted bundles?

This is exactly what webpack does with the webworker target!

@TheLarkInn
Copy link

So if you all know how to take this output, and stiched together set of bundles, "unbundled", and do whatevers needed for RN to consume it the right way, then we would be golden.

@krizzu
Copy link
Contributor

krizzu commented Apr 24, 2018

@TheLarkInn Great findings.
Regarding RN, AFAIK, it requires a single bundle, meaning we cannot do multiple fetches for bundle and then join it together.
Maybe we could generate separate chunks, and join them together at bundle request? In that case, we could separate vendors from user code, am I thinking correct?

@TheLarkInn
Copy link

These are separate files but just loaded sequentially? According to RN docs it says its bin encoded blobs or something?

@zamotany
Copy link
Contributor

If the unbundle feature exists, which generates multiple files, then there must be some way to make the RN to load all of those files. So the questions would be:

  1. What files does unbundle generate (filenames and extensions specifically)?
  2. Is there any entry bundle, which requests other unbundled bundles? If so, how is it done?

@krizzu
Copy link
Contributor

krizzu commented Apr 26, 2018

@zamotany Did that unbundle feature was introduced recently? That might be delta bundles feature

@TheLarkInn
Copy link

@zamotany they basically wrote a webpack require runtime and a custom chunk wrapper why I'm not sure still but it looks just like webpack had generated about x small common chunks that are sync loaded.

@zamotany
Copy link
Contributor

@krizzu no, it was there for months but undocumented. Delta bundles are another thing, which we should investigate because the concept is pretty neat.

@TheLarkInn Ok, so the bundles are requested from JS side. Curious how they load it, since XMLHttpRequest is async in RN.

@abhijeetskadam
Copy link

Hola, any update on this?

1 similar comment
@stylehuan
Copy link

Hola, any update on this?

@TheLarkInn
Copy link

@zamotany Hey, sorry for taking so long to get back on this.

Okay, from what I understand, this is the equivalent of adding 8 scripts to your head and they all load. (With the unbundled one first). Basically each file executes sequentially and adds their modules on self (as seen above). Building it in the webworker target allows for this to happen.

@zamotany
Copy link
Contributor

Due to the nature of React Native, code splitting can be achieved using:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests