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

RequireJS is too big as a loader #1159

Closed
lsycxyj opened this issue Jul 1, 2014 · 19 comments
Closed

RequireJS is too big as a loader #1159

lsycxyj opened this issue Jul 1, 2014 · 19 comments

Comments

@lsycxyj
Copy link

lsycxyj commented Jul 1, 2014

RequireJS is an amazing loader, but it is too big in many cases. Is there a plan to make a smaller version of requirejs by less features, only supports dynamic loading js, not supports plugins and low version browswers etc, like jQuery to Zepto?

@kryger
Copy link

kryger commented Jul 1, 2014

There's one already: https://github.com/jrburke/almond

@lsycxyj
Copy link
Author

lsycxyj commented Jul 2, 2014

@kryger Doesn't it seem to support dynamic loading js(both page1.js and page2.js depend on common.js for example), does it?

@zm-kad
Copy link

zm-kad commented Jul 2, 2014

too big as a loader +1

@a-ignatov-parc
Copy link

@lsycxyj almond.js doesn't support dynamic loading. It just provides necessary mechanisms to start your modular app without having full require.js on the page.

But do you really need dynamic loading in production? It's definitely better for browser caching to compile everything in one file (with r.js) than have multiple files loading.

@lsycxyj
Copy link
Author

lsycxyj commented Jul 2, 2014

@a-ignatov-parc One file in production is not suitable for every place. Let's say you have a multiple page project, of which every page have long and distinctive logics(page A has A, B, C plugins or modules, page B has E, F, G), while all of them depend on the same basic common modules(jQuery, backbones, etc.). The common module is only needed to be downloaded once and 304 after that, instead of downloading all the same codes in the combined js in each page. Isn't it more reasonable, is it?

@a-ignatov-parc
Copy link

@lsycxyj common solution here is to create two packages for page. With global libs that will be cached for all pages and with app modules.

@lsycxyj
Copy link
Author

lsycxyj commented Jul 2, 2014

@a-ignatov-parc Do you mean to export all the libs to global by combining them instead of using requirejs to manage the dependencies? I think it is just going back to "the past style". And what about having sub-page modules, which more than having page modules sometimes?

@a-ignatov-parc
Copy link

All i want to say is until we have http 2.0 with resource multiplexing shipped to live we need to deal with browser's restriction for parallel recourse download limit for domain.

Of course you can use sharded domains for your static files but you still can reach limit for max open connection and all your requests will be placed in queue.

So, to optimize your modular code for production it will be better to:

  1. Compile and optimize your modules into one file with almond.js

    This will let you get rid of full require.js file.

  2. Create different almond packages for different pages

    This will reduce initial page loading time and weight.

  3. Package all your libs (jquery, backbone, underscore etc.) into different package for max caching on all of your pages.

While in development you still may/should use require.js and "all that modular staff".

P.S. Production optimization can vary from project to project but usually they are the same

@lsycxyj
Copy link
Author

lsycxyj commented Jul 2, 2014

@a-ignatov-parc Would you please give me a project structure example? I may not know your meaning clearly.

@a-ignatov-parc
Copy link

@lsycxyj depending on what you said earlier

page A has A, B, C plugins or modules, page B has E, F, G, while all of them depend on the same basic common modules(jQuery, backbones, etc.)

You should have build pipeline to create 3 packages:

  1. libs.js – contains jquery, backbones, etc.
  2. packageA.js – compiled with almond.js for page A and contains A, B, C plugins or modules.
  3. packageB.js – compiled with almond.js for page B and contains E, F, G plugins or modules.

P.S. Of course for SPA build should be different.

@lsycxyj
Copy link
Author

lsycxyj commented Jul 2, 2014

@a-ignatov-parc How could I load libs.js by almond.js? There may be some AMD modules(Some framework or plugins written by myself for example) in libs.js.

@a-ignatov-parc
Copy link

@lsycxyj you can't load files by almond but you can do it with your browser using <script>

If you have amd modules inside libs.js then you must change my scheme to this:

  1. Concat your libs into libs.js.
  2. Build packages for pages with r.js without using almond.js.
  3. Include into your page scripts in next sequence:
    1. almond.js.
    2. libs.js.
    3. packageA.js/packageB.js.

Everything will work fine and you don't need to use full require.js

If later you will need to load other package you just create <script> tag with src


Just be sure that package's require which is initing app is placed at the end after defining all modules.

@lagden
Copy link

lagden commented Jul 2, 2014

Que treta do capeta!!!

It is very simple... RTFM!!!

https://github.com/requirejs/example-multipage-shim
https://github.com/requirejs/example-multipage
https://github.com/cloudchen/requirejs-bundle-examples

And when you build, use almond...

@jrburke
Copy link
Member

jrburke commented Jul 2, 2014

As to the original question, the bulk of the loader is handling configuration options and dynamic loading of modules. If something smaller is desired, it normally means either cutting configuration option support or dynamic loading. If cutting dynamic loading, then almond is a choice.

If cutting configuration option support, I do not have a specific plan for that, but since others have made AMD loaders ideally someone could create one if needed.

alameda is an option for modern browsers, and it is a bit smaller than requirejs. It can get even smaller if a browser supports Promises natively in the future. For any future requirejs 3.0+ work, alameda, or similar concepts to its internals, will likely be the baseline for future requirejs versions.

The goal is to shrink the size over time, but it also depends on better base capabilities in browsers. Ideally, I also would want any major version release of requirejs to work well with ECMAScript 6 modules and its module loader, but that work is still incomplete, so hard to know yet how that will turn out.

So closing this as there is a general desire to make it smaller, but it will take time and will be part of larger efforts, not this particular bug. However, feel free to continue discussion here.

@jrburke jrburke closed this as completed Jul 2, 2014
@lagden
Copy link

lagden commented Jul 2, 2014

Hi @jrburke

I have a similar problem... maybe a little different...
I made a module that depend on facebook library, but my app have a offline mode.

So, I did a pretty crazy "workaround" to solve.

You talked about alameda on the post above... It's a pretty awesome stuff!!!

Can I use alameda without problem?
Do you have an example?

Could be some thing like this:

require(['//connect.facebook.net/pt_BR/all', 'myModule']).then(function(FB, UserFacebook) {
    var user = new UserFacebook(FB);
    //...
}).fail(function(err) {
    err.forEach(function(obj, idx, arr) {
        if (obj.fail === true)
            console.error(obj.moduleName, obj.message);
    });
});

define('myModule', function() {
    'use restrict';

    function UserFacebook(FB) {
        FB.init({
            appId: 'xxxxxxxxxxxxxxx',
            status: false,
            cookie: true,
            xfbml: false,
            version: 'v2.0'
        });
    }

    //...

    return UserFacebook;
});

@lsycxyj
Copy link
Author

lsycxyj commented Jul 3, 2014

@a-ignatov-parc As to libs.js, that is exactly "the pass style" what I mean.
Firstly, libs.js is simply concatenated. In addition, all the frameworks have to be exported as global variables and all the dependencies have to be managed manually.
Secondly, let's say pageA has A, B, C, D, E modules. A, B will be used 100%, while C, D, E will be used 10% in different circumstances. Should the users always load C, D, E modules?
Thus, I think dynamic loading is still nessasary.

@jrburke Thank you for your reply. Well... alameda is still too big. Do you know any other less options AMD loaders?

@a-ignatov-parc
Copy link

@lsycxyj almond will make global require and define constructions, so there is no need to export libs that are amd-compatible.

About rare used modules you should analyze how big impact they will make on package size. If modules C, D, E are lightweight (100kb total) than i would suggest you to build them in package. They will be minified and gzipped and impact on overal size will be minimal. But you will eliminate initialization latency because there will be no loading.

Also you should understand that for desktop users 100kb of extra code (minified + gzipped) is not a big deal. I don't think that this will be your performance bottleneck place.

P.S. If you haven't already checked this performance checklist you definitely should do this before considering about reducing codebase size.

@lsycxyj
Copy link
Author

lsycxyj commented Jul 8, 2014

@a-ignatov-parc Great conclusion site, thank you very much.

Do you mean what I return in define will be made as global variables after I use optimizer and almond, so that it won't work when I want to require these modules in page module? And if I want to use almond, do I have to make all modules in libs not be amd-compatible? If do, all dependencies have to be managed by arranging order. I may be a little difficult when there are quite a few complicated dependent modules in libs.

I am going to apply it to a mobile app website, so it means a lot to me, both dynamic loading and loader size.

@a-ignatov-parc
Copy link

@lsycxyj no. When you using almond.js and r.js your amd modules not changing at all. Almond only gives you lightweight require.js globals (require and define) without module loading and some other stuff.

To work properly all dependencies and modules should be resolved before requiring main app.

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

No branches or pull requests

6 participants