Requirejs vs browserify vs webpack for js loading order: am I just moving the situation from one side to another?

Jorge Arévalo picture Jorge Arévalo · Mar 25, 2016 · Viewed 9.2k times · Source

Ok, it's 2016. Webpack looks like a winner against requirejs and browserify. I've been reading about those 3 technologies, to solve a very specific problem. I want to avoid this in my HTML file (part of an AngularJS application)

<script src="some-file.js"></script>
<script src="some-file2.js"></script>
<script src="some-file3.js"></script>
<!-- Dozens of similar lines here... -->

Of course, the order of those lines in my HTML file matters. Bootstrap will ask for jQuery, etc.

First thing I found: requirejs. You just specify something like this:

<script src="my-bundled-file.js"></script>

And then, you solve the dependency problem with JS. Going further, I found 2 approaches here:

  • CommonJS (browserify)
  • AMD (require.js)

Webpack works with both approaches, which sounds nice.

At the end, the 3 tools can be used for the same thing: bundle several files in only one. But what I'm worried about is the order in which those files are bundled.

I don't want to care about this, and looks like using those solutions (or even gulp + gulp-concat, like is suggested here), I'm just moving the problem: now, I specify the modules which my application uses with JS code, but I still need to put the modules in the correct order, even with WebPack (an example here: require calls must be in the correct order)

So, my questions:

  • am I misunderstanding these tools? I just want to solve the loading order problem, and looks like I'm not doing it
  • do these tools solve a different problem (lack of native modules in ES5, which drives to contaminate the global scope)?

Answer

JMM picture JMM · Mar 25, 2016

am I misunderstanding these tools? I just want to solve the loading order problem, and looks like I'm not doing it

I think so, yes. With CommonJS and tools that bundle it load order largely becomes irrelevant, something you don't need to manage. You just require() what you need where you need it. There are some cases where it's still relevant, but mostly having to do with things like global side effects and circular dependencies. Using CommonJS and bundling it is totally different from concatenating a series of scripts.

do these tools solve a different problem (lack of native modules in ES5, which drives to contaminate the global scope)?

The CommonJS module system is designed to address the lack of native modules in JavaScript and a version of it is used in Node. The headline on Browserify is "bundle node modules for the browser", though in practice it's also used for creating bundles to run in Node and for bundling modules only intended for running in the browser.

In Node bundling modules isn't necessary because Node wraps the code you execute and provides an implementation for its module semantics. To run modules using that system in browsers you need to bundle it because the browser doesn't wrap the code to provide it with the things that make up the module interface, like require(), module, exports. That's part of what a bundler does for you: wraps the code to provide that interface.

Another thing it does for you, that addresses your question about ordering, is recursively discover dependencies. So like I said, you require() what you need where you need it and point the bundler at an entry script. The bundler will analyze the script to find any require()s and include the modules they reference in the bundle. It will repeat that for those modules, ad infinitum.

I think you'll find a lot more traction for CommonJS over AMD, but I'd say there's far from a clear win for Webpack over Browserify. Both are popular. Browserify is widely used, including to build parts of projects like Babel and React.

My advice would be to start with Node-style CommonJS modules and Browserify (note: I am a maintainer of Browserify).

Until you understand this better I would suggest not using anything involving Angular as a reference for how things should be done in terms of CommonJS modularization. I think they had a lot of troubling just getting the Angular npm package into proper CommonJS shape.