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

Multi-bundle support #146

Open
cguinnup opened this issue Jan 4, 2017 · 4 comments
Open

Multi-bundle support #146

cguinnup opened this issue Jan 4, 2017 · 4 comments

Comments

@cguinnup
Copy link

cguinnup commented Jan 4, 2017

I'd like to propose support for multiple LiveReactload bundles in separate browserify/watchify processes:

Reasoning

I'm developing HTML5 GUIs in a large codebase with a number of internal libraries. Hot-reloading needs to occur quickly for both lib changes and changes to the GUI code itself, but presently watchify is not quick to incrementally build one giant bundle. When we split the code into several smaller bundles, watchify is much quicker to rebundle code changes. Additionally, building the bundles in separate processes allows us to speed up the initial non-incremental build.

I believe this is also a step toward #107 (Support factory-bundle), though multiple-entry support is beyond the scope of my proposal here.

Method

  • Only the entry bundle launches a WebSocket server & receives its messages.
  • On any change, the entry bundle patches and reloads all relevant bundles. It does this through a descending chain of exposed functions (akin to how Browserify resolves modules in external bundles).
  • Lib bundles communicate their changes to the WebSocket server (since isolated in a separate process).
  • Lib bundles expose their patch(), evaluate(), and load() on a global __livereactload_export object. Before assigning to that global, any existing __livereactload_export is assigned to a loader()-scoped variable previousBundle, which creates the descending chain of exposed functions I mentioned above.
  • LiveReactload needs a unique bundleId for each bundle. This also signifies that we're using multi-bundle mode. (Better way to do this? Plugin access to dest filename?)
  • HTML must include bundles in order of their dependency.
  • No changes to the current single-bundle LiveReactload API.

Usage Example

var entryBundle = browserify({entry: ...});
entryBundle.plugin(livereactload, {
  bundleId: "myEntryBundle", port: port});

// in a separate process:
libNBundle.plugin(livereactload, {
  bundleId: "myLibNBundle", port: port, server: false, client: false});

I've been working up to this change with the previous smaller issues. Any suggestions on the API? I'm mostly finished the capability, and making this issue to check whether you wish to integrate these changes. I would rather help maintain this as part of the official LiveReactload, but I respect that it's your call to make.

@milankinen
Copy link
Owner

milankinen commented Jan 5, 2017

Hi! Just trying to understand the use case:

  • What kind of content do those "library bundles" export? Are they exporting React components or functions or something else?
  • How are you using the bundles in your web page? Separate <script> tags + UMD? AMD? window.SomeGlobal?
  • What kind of interdependencies do you have in those bundles?

@cguinnup
Copy link
Author

cguinnup commented Jan 10, 2017

Looking over my initial proposal, I see I didn't clearly state the primary objective. So to clarify...

Primary use case:
Scales LiveReactload to large projects, while keeping the ability to hot-reload all library modules. Does so by allowing multiple bundles, which leads to 1) smaller bundles to rebuild on incremental changes (thus quicker) and 2) the ability to use multiple cores on the initial watchify builds.

To answer your questions:

  • The library bundles export anything from "class" functions to React components to 3rd-party Node modules.
  • All bundles are loaded in <script> tags. No UMD beyond what LiveReactload and Browserify already use. (The library bundles are also wrapped in LiveReactload's loader.)
  • Modules can require either 1) modules within the same bundle or 2) modules in a bundle that was loaded with a previous <script> tag.

If anything's unclear, let me know.

@EugeneZ
Copy link
Contributor

EugeneZ commented Jan 21, 2017

I also have a project this change would help a lot. I am building multiple Browserify bundles from different repositories, and currently only use LiveReactload in the primary package, so I lose development cycles on the submodules. Looking over @pizza2code's proposal, I believe it would work for me, too, as I can specify a bundleId for my container project, and I can then add LiveReactload to the submodules.

@milankinen
Copy link
Owner

milankinen commented Jan 22, 2017

Hmmm, interesting. I'm definitely interested in this if we manage to get this working properly. 👍

How are the inter-bundle dependencies solved? I.e. when I change something in the bundle x, how does the system know whether or not I need to reload also bundles y and z (and from which modules the reloading should start / which modules from those bundles use the exposed and reloaded functionality of x)?

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

3 participants