Skip to content

Async loading of bundles #59

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

Closed
tinganho opened this issue Aug 2, 2015 · 9 comments
Closed

Async loading of bundles #59

tinganho opened this issue Aug 2, 2015 · 9 comments
Labels

Comments

@tinganho
Copy link

tinganho commented Aug 2, 2015

Hi, I want to propose async loading of bundles. I don't know if the spec already cover this or if you already have discussed this. Though cannot find similar discussion anywhere. Just some heads up, I'm having some difficulty understanding the current spec. So I use my own code example below.

Problem

Because of load time sometimes it is not suitable to bundle everything into one file. One solution is to bundle your application into multiple bundles instead. Another solution is to use http2 with server push. But you can still use server push and bundle at the same time(since you already need to uglify your application code, adding another build step for the bundling won't be that big). Also bundling saves the client from decoding a lot of http2 headers. But also cache-aware server push might need SW support to know which files to be pushed(Here is one discussion in h2o/h2o#421 (comment)), so setting up server push correctly isn't the most trivial task.

Proposal

One solution to above problems is to let the loader being able to load bundles. Since bundles need at least one root file(not necessarily) to traverse all files and bundle them — we can add a map to the loader, that maps root files to bundle files.

In example code(sorry, don't know the whole loader spec and have some difficult to understand it):

Loader.bundles({
    '/page1.js': 'page1.bundle.js', 
    '/page2.js': 'page2.bundle.js', 
})

All root files defines(not necessarily) an API interface to interact with so we can use the same code for dev and production environment.

if (url === '/page1') {
    var page1  = await Loader.import('/page1.js'); // loads bundle page1.bundle.js instead of page1.js on production
    page1.init();
}
@guybedford
Copy link

It is certainly possible to implement something like this via the loader hooks. SystemJS has exactly this kind of an implementation in https://github.com/systemjs/systemjs/blob/master/docs/config-api.md#bundle.

@tinganho
Copy link
Author

tinganho commented Aug 2, 2015

@guybedford great totally missed that systemjs supported this.

@caridy caridy added the question label Aug 3, 2015
@matthewp
Copy link

matthewp commented Aug 5, 2015

Bundling is not part of this specification. I do believe that a common bundling format needs to emerge to accommodate the needs of ES2015 modules (and Guy's System.register could very well be that format but it needs to be discussed as an independent proposal outside of Systemjs).

Sadly http2 and ES2015 module format does not solve the need for bundling even in a development environment. But the loader spec might not be the place for that discussion.

@caridy
Copy link
Contributor

caridy commented Aug 5, 2015

Bundling and folding mechanism will emerge for sure, but not in this repo.

@caridy caridy closed this as completed Aug 5, 2015
@matthewp
Copy link

matthewp commented Aug 5, 2015

@caridy I've noticed you use the term "folding" a bit but I'm not familiar with what you mean by that, can you explain?

@caridy
Copy link
Contributor

caridy commented Aug 5, 2015

@matthewp

main.js

import foo from "foo"';
export default function () {
    foo();
    return 'ready...';
}

foo.js

export default function () {
    console.log('do something...');
}

If you application only relies on main.js (importing it and calling its default export), it doesn't really matter if main.js uses foo.js or not, all that can be abstracted, we can have tools that will produce a new es6 module called main.js with the following content:

function foo__default__() {
    console.log('do something...');
}

export default function () {
    foo__default__();
    return 'ready...';
}

and everything will continue to work as expected, because the public interface of main.js (its default and named exports) remains the same, but its dependencies were folded into its own source code. I haven't get a chance to work on any tool to achieve this, but I will, or will be happy to help others :)

advantages of this over bundling:

  • code elimination can be achieve easily.
  • no perf penalty when exploding the number of modules you use in your app (no live bindings for main.js since it doesn't have any external dep)
  • no perf penalty when executing hundreds or thousand of modules (you can fold them all into one, or few, preserving the public APIs of those that you try to import imperatively).
  • no perf penalty when looking on exotic objects (thru getters) for imported entries, they can simply be variables in the scope (e.g.: foo__default__).

these are, from the top of my head, some of the stuff related to what I call folding of modules.

@guybedford
Copy link

Nice, I also really like the name fold here.

@caridy
Copy link
Contributor

caridy commented Aug 5, 2015

image

@electricessence
Copy link

electricessence commented May 20, 2016

Super Lazy :)

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

No branches or pull requests

5 participants