Hacker News new | past | comments | ask | show | jobs | submit login
Can you help me understand the benefit of require.js? (gist.github.com)
105 points by SanderMak on July 22, 2013 | hide | past | favorite | 48 comments



This post doesn't contain an argument so much against require.js as against module systems as a whole. I think that is short-sighted for any project where performance is important because the fact is, most projects of that kind are still using Closure Compiler which in spite of being slow, produces much smaller, more efficient code than does Uglify. Particularly, the project will be compiled with ADVANCED_OPTIMIZATIONS which can break code that will work when uncompressed (when literal property names are not written as strings or externs are not defined properly, mainly). I think any compiler with really high quality output will probably be somewhat finicky with its inputs, so Closure Compiler is not unique in that regard.

But if you don't buy into compilation as a step in your frontend development cycle, I'm not sure there's much point in using require.js, goog.provide/require, or any other module system.


It's interesting that you see module systems and optimizing compilers as two parts of a whole. My impression of the two systems has always been that they're at best complimentary, with some impedances between the two.

For example, in the last large js project I was on, we found that the closure compiler by itself - even without ADVANCED_OPTIMIZATIONS - did well enough at optimizing the code that a separate module system wasn't worth it in terms of additional time to refactor.


Could you expand on that please?

You had a set of modules and compiled them into one file and did not use a module system - I am still naive on modern JavaScript work so any guidance gratefully etc.


We had a large codebase already, written with just script tags in mind, and we were being murdered by blocking loads of the javascript. I looked into refactoring to use something like require or labjs that loads without blocking, but would have taken a substantial amount of development time (this was a problem with the existing codebase of 8k lines or so, not the tools.)

While we were looking at that, I found that we could make our performance target by concatenating all the source together, running them through closure, and just serving up one monster js file a little under 1MB in size.

This was an enterprise system, so we could assume certain levels of client performance that cat picture industry applications probably can't, as well as having a lower bar for performance in the first place - a five second load time on a low performing system was firmly ok, so YMMV.


Use browserify — http://browserify.org

Compared to require.js browserify has the following benefits:

* CommonJS module format which is less verbose than AMD

* it uses node_modules/ dir to load dependencies from so

* ... you can use npm to install dependencies

* ... and if you use Node.js then that facilitates code sharing between your client and server


The downside of this approach is all of the bootstrapping for running and developing your project is now a new environment on the server side. Don't forget that all of this tech carries a lot of mass and now you're having to maintain a number of different tools!

If this is an open source project, you just went from:

python -m SimpleHTTPServer || open index.html

To:

npm install && grunt build && grunt run

... And now as a person wanting to work on your code I have a whole slew of new tools to learn!

It's not always as cut and dry of a decision...


Not that this invalidates what you said, but NPM and Grunt (and just enough Node.js to use them) are required learning for JavaScript developers nowadays IMO.


I didn't downvote you, but I use nodejs and I've never needed to use grunt.

I don't think grunt is as pervasive as npm in the world of node.js.


Grunt is just generally a helpful little task runner and good for automating many things in general web development - running tests, concatenation / minification, linting, HTML / CSS / JS preprocessing and so on, if that floats your boat. It really is worth giving it a go.


Well, makefiles have worked fine for me so far.


You might like Jake, then. It's a Node.js version of Rake (which is a ruby version of make).


Maybe that's where the confusion was. I was talking about browser development. Thanks.


Does whoever downvoted me care to explain why or offer another opinion?


None of that addresses the complaints raised in the article.


My single biggest aversion to build tools like browserify and r.js is this... how do I package portions of a site into separate files?

Generally I have something like the following...

    init.js - in the head, modernizr, css-browser shims etc
    jquery.js - before /body
    site.js - site-wide functionality
    section.js - functionality for a section of the site
    page.js - functionality for that specific page
This allows me to cache/reuse common functionality and still have a limited number of http requests for js... how would I accomplish this with requirejs, browserify and the rest?

From what I've seen you can't. Ideally, I'd like to be able to package harmony-style modules.. there's some transpilers for that structure already. It would just be nice to be able to reliably package sections for downlevel reuse without having one huge script per page in a site that is expressly not single page.


You can do this with build layers. There's an example project showing how: https://github.com/requirejs/example-multipage


you can do that with [1] browserify bundles. Basically you tell the script not to package modules that get required and instead use ones defined elsewhere, like in another include.

1. https://github.com/substack/node-browserify#multiple-bundles


As much as I'd love to explore require.js more, the documentation web site just doesn't seem to be compatible with my mind. I don't have a lot of time to test it out and there's something about the docs that just isn't making me feel like I'd know how to use it.


I think I can explain how to get started with require.js pretty quickly. I've attempted to do so with a short gist: https://gist.github.com/willurd/6054834 (much shorter than the OP and a higher code/text ratio).


Thanks, that actually helps. Also having a demo helped me clarify that I can still use the Chrome debugger on require.js sources. I used Dojo a couple of years ago and lost a lot of debugging capabilities due to the way it evals the loaded scripts.


No problem at all :) Glad I could help you out.


I don't mean to troll, but isn't exploration and figuring things out a huge part of creating software. There are require.js examples apps on github , Q and As on Stackoverflow, and open source code that's available for digging deep. It only took me ~2 Days to get the gist of require.

Is it no longer good enough that the open source community builds great free things for us to use? Do they now have to upload the know how of these tools to the users brains in a Matrix like fashion?


Getting things done in a timely manner and under budget is an even bigger part of it. Having to learn "new" things (this is distinct from "different" things and "better" things) leaves significantly less time to achieve productivity.

In terms of developer time, 2 days is rather expensive.

If this is your own pet project, then by all means spend the time necessary to learn it. Or if you intend to "Move Fast and Break Things", then spending time to learn things is also good. But if you're running a business with "x" which has worked efficiently for years and isn't broken, "y" is not necessary.


> But if you're running a business with "x" which has worked efficiently for years and isn't broken, "y" is not necessary.

You are using words like efficiently and phrases like "isn't broken" without quantification. Having only done things one way, and it doing it's job does not mean it's efficient or not broken. Only that you don't know a more efficient way or it hasn't been proven to break yet.

While getting things out the door is important, it's also just as important to not base assumptions without actually quantifying. And you can't do that if you assume the mantra of "if it ain't broke, don't fix it."

It's a balance that, as a professional, you have to manage.


On the contrary, efficiency is quantifiable. As is determining whether or not something is broken or prone to breaking. I.E. Brittleness becomes obvious under heavy load.

This isn't a "if it ain't broke, don't fix it" either. You push things to the breaking point and see if that's projected in your growth (maybe a bit beyond what's projected), but maintainability and efficiency don't hinge on what's new. It hinges on what works and if what works is what you have, you don't waste time with new things.

But back to the point... You learn "new" things when you figure existing things aren't up to the task or you try to see if amending x will get you further. y Is still not necessary if it will.


> On the contrary, efficiency is quantifiable

Contrary to what? I said as much. The problem is that you need to quantify that efficiency. You can't just say "x is efficient."

> But if you're running a business with "x" which has worked efficiently for years and isn't broken, "y" is not necessary.

So, x has worked efficiently for years? Based on what? How are you quantifying that? And how can you say it's efficient without having some yardstick to measure against? By not looking at other technologies, you can't really say whether it is still efficient or not.

Efficiency is a moving target.


>> but isn't exploration and figuring things out a huge part of creating software

Absolutely, but each developer will make that judgement and require.js shouldn't be victims of those who give up at the first hurdle.

>> There are require.js examples apps on github , Q and As on Stackoverflow, and open source code that's available for digging deep

That's good to hear. I will at some point give it another shot and it's good to know there are examples and support out there. It was a couple of years ago when I did look into it, I remember getting confused and the on site documentation didn't really steer me in the right direction. The documentation doesn't appear to have changed much in that time. It can be hard work and time consuming having to dig deep to solve a problem.

>> Do they now have to upload the know how of these tools to the users brains in a Matrix like fashion?

The OSC are not obliged to provide a better user experience in getting new users to adopt their software. Of course not. But if they want to have as many developers appreciating their hard work, then you know, it doesn't hurt.

>> It only took me ~2 Days to get the gist of require.

2 days to learn how to use it is something I cannot afford for a workflow improvement over a show-stopper problem. If it was something I could do in a hour to get an understanding and start porting my application with the knowledge that I'm not going to be stuck for 2 days, then that would be a different situation.


Learning is one thing, getting frustrated to the point of yelling "Why the hell doesn't this work?" is another. I would say Backbone is an example of the former and requireJS an example of the latter, but that's just me.


I found this gist while modularizing our medium sized Angular application. It was a day's work to get the requireJS basics going for our app. That was a pleasant surprise. The additional r.js optimization step cost a bit more time, and that was indeed partly due to documentation issues.


Care to elaborate? As far as i know. Angular has modularization built into its API and recommended paradigms? Why use require.js if angular already supports creating and importing modules?


Sure. True, Angular has modules and dependency injection which we use (both before and after RequireJS). However Angular modules are more namespace than true modules. When you split your Angular app over multiple files you'll still have to manage these dependencies by yourself.

The real trigger for introducing RequireJS was our need to optimize our JS by concatenating and minifying it. And to do that in the right order, you need to know your dependencies very well. That's when I decided I didn't want to do that by hand. Not now, and not in the future. So I took https://github.com/tnajdek/angular-requirejs-seed as an example and started defining modules and dependencies. Now I can easily run the r.js optimizer as a build step before releasing and now I'll get a correct and concatenated/minified JS for production.

The nice thing is that RequireJS not only manages our Angular modules (defined in separate files), but also their dependencies on vendor scripts (JQuery, Hammer.js etc.) I really have the feeling I'm in control again.


I used requireJS for a project about a year and a half ago, and I agree that the documentation is not good. The error messages are also not good. When I couldn't figure out the right way to configure something, I had to use trial and error. Basically, everything about using it kinda sucked, but we wanted the dependency resolution for our scripts.

I haven't looked into alternatives (mainly Browserify) and don't know if I will use JS modules in my future development. The idea seems neat, but it really adds a lot of pain in my opinion. Perhaps there is a threshold of webapp complexity, past which the pain is worth it.


this is my main problem with it.

it's an astounding amount of complexity to introduce into a project, just to be able to get the bare minimum of functionality.

if something breaks, and something always breaks, I simply don't want to be responsible for debugging it.




javascript "module" dependencies are written in javascript, not in html renderer.

in development:

    <script data-main="your-module.js" src="require.js"></script>
in production:

    <script src="your-module.min.js"></script>
One problem I haven't solved is when html renderer writes inputs to your javascript module. I can either print my module's main body in html:

    <script>
        require(['yourModule'], function(yourModule) {
            var config = {% server template vars %};
            yourModule.start(config);
        });
    </script>
Or use global config variable and shim.


Yeah, I've run into this as well. I would say avoid doing this if you can and use an AJAX call from inside the javascript to pull the data in that you need. Sometimes this isn't feasible/ideal though (especially if the data is slow to get/calculate and is already used on the html page...). If you can cache the results of the calculation on the server-side, that would mitigate the performance implications a bit and then you just have the overhead of the request itself.


This example production website uses require.js to dynamically load only the static files needed for the current View, so initial page loads are fast. After a user has loaded the static files, they will be cached by the user's browser. This means a page transition will be ONLY 1 api call to retrieve the View's data.

view-source:https://www.wakati.me/

https://www.wakati.me/static/js/router.js

This also allows changing 1 version number to invalidate the user's cached static files. I don't know if the OP's build script supports that or not.

Above site was built using conventions found here:

http://ahamlett.com/Backbone.localStorage/


For a larger web app, I'd use Require, Browserify, or Component, but not for small-to-medium size websites. All you usually need for those is jQuery, and several plugins which only depend on jQuery.


I have never worked on a large Web app that required an unmanageably large JavaScript code base. They were simply built with one due to 1. too much structural code, 2. cramming too much in one page, or 3. cramming too much in one site. All of these are mistakes of poor design and architecture and using require.js won't solve that problem.

My current project uses require and after several months of working with the legacy code, I have not been convinced that it has improved maintainability. I would not use it again if given the choice.


I used to think the same thing, but then I ran into the problem where my large app had circular dependencies which require.js/AMD does not support. Naturally, AMD supporters blame you and your project's architecture, but it is not uncommon to have some circular dependencies in a large app.

The work-around is to use require.js in commonjs style or to add hacks into your architecture. Not fun.


Circular dependencies ARE a problem with your architecture. You've got two modules that are strongly coupled. They should either be in one module or you should rethink things. It is impossible to need one without the other in that case, so including one without the other makes no sense, so just merge them.


> Circular dependencies ARE a problem with your architecture

This whole thread reminds me of the PHP days before namespaces. If you have circular dependencies within your own codebase, you have an architecture problem. If they are introduced by third-party libraries, maybe the usage of the library should be questioned.


Here's a trivial example:

I have a Modal class which depends on some utilities in a Utility class, but the Utility class depends on the Modal class because there are some utilities that show Modals.

This is not a broken architecture and is handled just fine by other programming languages/dependency handlers.


You want to use inversion of control in your Utility class. Just pass function, which will operate on Modal class instance (not Modal class instance itself but function) as argument to its utilities that show Modals.


The concept of a "Utility Class" is normally a sign that there is something else going on!

What are the utilities contained in this module?


In large projects, and especially legacy ports, you don't have that luxury.

Hence, careful selection of projects to work on is key.


Not one convincing argument in that thread.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: