I'm having trouble understanding the benefit of require.js. Can you help me out? I imagine other developers have a similar interest.
From Require.js - Why AMD:
The AMD format comes from wanting a module format that was better than today's "write a bunch of script tags with implicit dependencies that you have to manually order"
I don't quite understand why this methodology is so bad. The difficult part is that you have to manually order dependencies. But the benefit is that you don't have an additional layer of abstraction.
Here's my current JS development work flow.
When in development-mode, all scripts have their own tag in the DOM.
<script src="depA1/dep1-for-module-A.js"></script>
<script src="dep2-for-module-A.js"></script>
<script src="moduleA/moduleA.js"></script>
<script src="dep1-for-module-B.js"></script>
<script src="module-B.js"></script>
<script src="moduleC/module-C.js"></script>
<script src="script.js"></script>
There is no abstraction layer. This allows me to better debug individual files. The browser reads separate files, so I can debug with Developer Tools. I like how it's straight-forward.
Dependencies are basically managed right here. depA1
needs to be listed before moduleA
. It's explicit.
Modules are 'transported' by attaching to the global namespace.
( function( global ) {
var dep1 = global.depA1;
var dep2 = global.depA2;
function ModuleA() {
// ...
}
// export
global.ModuleA = ModuleA;
})( this );
All scripts are concatenated and minified. One HTTP request on load.
<script src="site-scripts.js"></script>
The Concat + minify task is maintained separately. It's part of a build process. Makefile
or what-have-you. For dependency management, the ordering of scripts matches how they were listed in the HTML.
This can be done easily with some sort of configuration and templating. For example, by setting prod_env
config variable to true
or false
, the site is either in production, serving the one file, or development mode, serving every single file.
{% if prod_env %}
<script src="site-scripts.js"></script>
{% else %}
<script src="dep1/dep1-for-module-A.js"></script>
<script src="dep2-for-module-A.js"></script>
<script src="moduleA/moduleA.js"></script>
...
{% endif %}
- What benefit does require.js provide over this workflow?
- How does require.js address minimizing HTTP requests? Is this any better than concat/minifing all the scripts?
This thread made me think about my current practice and helped me decide to continue not using require.js.
I don't think require.js is bad. To me it seems more like a habit. You can use require.js to manage your dependencies or you can use something else or you can do it yourself. Doesn't seem to cause much issues either way.
If, and only if, your client side application actually consists of more than several dozen individual js files then automated dependency management will certainly have its benefits. On one project we currently have around 40 modules (some of them global, some only used on specific pages) and some of the meta modules are only supposed to be loaded (i.e. their factory function executed) when they are actually needed. For that purpose I wrote our own dependency manager which has less than 50 lines of js.
In order to get all the dependencies to the client we use grunt to uglify all the modules into one monolithic file. For development the files are simply concatenated without uglifying. The Gruntfile is the only place where all the modules are listed and it is pretty easy to figure out in which order they belong (core / meta modules first, page-specific modules at the end). Even if we wanted to include the source files individually we could do that relatively simply by extracting the module list into a json file and including them via our server side template engine.
Now this is only my setup for a bigger project. Obviously there are even larger projects out there, but considering how easy it was to set up our own dependency management, which is tailored to our particular needs, I doubt that an even larger project couldn't handle that.
However I have a lot of much smaller (client side) projects where I only need anywhere between 3 and maybe 20 js files. I assume that most projects on the web are of this scale, even though they don't like to admit this. After all, if your client side actually uses hundreds of non-trivial modules chances are your site will become slow as f*ck. For projects like that I hardly think your dependency graph will reach any significant complexity. Just create a single global object as your application's namespace (I usually give it a project-specific name to avoid collision with generic names like
app
). Wrap all your modules into an IIFE and inject the modules into your namespace. Looks like this:main.js
:SomeModule.js
You can also do the class-like approach like this:
SomeClass.js
I've done a fair few projects like this and I've never run into any issues.