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

Make a packer for browserify #2

Closed
andreypopp opened this issue Jan 31, 2014 · 12 comments
Closed

Make a packer for browserify #2

andreypopp opened this issue Jan 31, 2014 · 12 comments

Comments

@andreypopp
Copy link

Looking facebook/react#1002, wow, this is a really great improvement over browserify packer.

I'm wondering if it's possible using techniques pure-cjs employs to build a replacement for browser-pack (which is used by browserify) so everyone who use browserify in their build system would benefit with no change required to their code?

@RReverser
Copy link
Owner

I'm not sure that's possible.

You see, browserify is complex solution that allows you to use bundled modules outside the built file with require(...) call, to use Node.js modules and variables, to require(...) external modules dynamically, and much more other stuff that allows you to reuse and write code for browser just like you used to write it for Node.js, and due to that complexity it heavily relies on preserving string paths of modules.

And here comes the main difference (disadvantage and benefit in one) of pure-cjs - it gives you only the minimal required subset of CommonJS Modules w/o providing Node.js-like environment and thus with no need to preserve any paths at all outside the built file - but only using IDs for internal cross-module communication (which can be optimized even more in future).

That's why it's called Pure CommonJS builder after all :P

@andreypopp
Copy link
Author

Well, looking at browserify bundles now, it seems without explicit configuration there's no globally unique string paths for modules but only local ones which can be replaced by integers.

@RReverser
Copy link
Owner

And so any dynamic resolution will be broken :)

@andreypopp
Copy link
Author

@RReverser hm... I don't really know what dynamic resolution is, can you point me to the section of browserify README which describes this feature?

@RReverser
Copy link
Owner

Dynamic resolution is how I name require call with anything different from string constant in argument. In pure-cjs it's strictly defined that such calls are not supported, but browserify does allow stuff like require(condition ? 'a' : 'b'), require(moduleNameInVariable), etc.

@andreypopp
Copy link
Author

@RReverser ah, browserify doesn't support this as well, it just doesn't throw an error when encounters this. So if you do

var modName = 'x';
require(modName);

browserify won't bundle x module for you. Dependency resolution is completely static.

@RReverser
Copy link
Owner

Such code would work, you just need to explicitly put modules using bundle.require(...) so it can find this module (or expression might result in string path that resolves to already bundled one). That's why they use string resolution - user can easily combine modules - found by browserify itself, added manually, emulated from Node.js natives - any of them, w/o different handling of each type in generated code but using standard require algorithm similar to used in Node.js. That's also a reason why browserify build is faster then with pure-cjs - it doesn't modify JS AST (while custom through-transformers may to) but only looks for and collects require calls to detect those modules that can be detected automatically (in this sense similar to r.js Simplified CommonJS Wrapper lookup).

@andreypopp
Copy link
Author

@RReverser yeah, only if user called bundle.require(...) on some module that module (and only that) could be exposed with a string id

@RReverser
Copy link
Owner

Not only those added with bundle.require(...) but actually any - bundled automatically, bundled manually, external Node.js module. That's one of reasons why browserify needs to store path names so in runtime, when such dynamic require(...) is called, it can distinguish if called module is already bundled so require(...) call will be internal or is it external one and loading should be delegated outside this bundle (for example, check out https://github.com/substack/node-browserify#multiple-bundles). Such decision can't be done based on integer IDs which have no meaning outside the packed JavaScript.

@RReverser
Copy link
Owner

After all, I see browserify as complex solution for much wider set of tasks and needs which can't be easily changed to new module handling and packing without losing some parts of functionality or complicating heuristics. So for me it looks more reasonable to support and maintain package that does only one task - but does it well, and doesn't try to become part of big swiss knife.
worlds_largest_swiss_army_knife_wenger_giant_knife

If you can take this idea and bring it to browserify to reduce size of it's bundle - of course, I wouldn't mind and would be happy that idea worked and helped, but that's definitely not issue of nor scope of pure-cjs discussion.

It will be developed, gaining more features and, probably, optimizations, but still doing only one task and with only one purpose - build CommonJS into one file with minimal overhead.

@andreypopp
Copy link
Author

Ok, thanks for clarification of your position.

Apparently there's already an optimizer for browserify bundles which does exactly that. According to browserify/browserify#296 it might be included in browserify.

@RReverser
Copy link
Owner

As you can see from optimizer commits, it's created 7 days ago (later than pure-cjs) so "already" is not exactly correct word ;)

But yes, if it will be included, that would be great.

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

2 participants