What's the difference between Require.js and simply creating a – maxedison Feb 06 '11 at 18:53

  • 37
    "ease of use for developer" could not be farther from the truth. It definitely has a steep learning curve for you and anyone else who will come to work in that project. – Sahat Yalkabov Sep 30 '13 at 03:06
  • 3
    @TwilightPony I consider myself not that bright and requirejs wasn't really a hard thing for me to get. It removes you having to worry about dependancies and speeds up the page. Your code becomes more inline with server-side programming in how you declare your dependancies which I personally find refreshing and simple. The syntax was minimal and closure-fied by design then sets the roadmap for production to easily combine your scripts. On top of that debugging is just like static declarations. Not sure what is easier than that. Much harder the other way as I've done the other way. – King Friday Aug 03 '14 at 16:43
  • I'm struggling. Especially with modules that try to attach themselves to global objects. (React modules)... – geilt Mar 03 '15 at 04:33
  • 1
    The comments on that page actually left me feeling that one should run away from and not towards require. Especially the one near the bottom that links to http://stevesouders.com/tests/require.php – Raydot Sep 29 '15 at 22:35
  • that stevesounders example is missing the point. If script 2 depends on symbols from script 1 then script 2 should be requiring script 1. That's the whole point of declaring dependencies. If you don't declare them of course it's not going to do the right thing. Ideally you should never be magically passing symbols between modules. If you are magically passing symbols between modules and putting stuff on window/global then you need to manually declare your dependencies. – gman Jan 06 '17 at 05:39
  • 9

    Some other very pointed reasons why using RequireJS makes sense:

    1. Managing your own dependencies rapidly falls apart for sizable projects.
    2. You can have as many small files as you want, and don't have to worry about keeping track of dependencies or load order.
    3. RequireJS makes it possible to write an entire, modular app without touching window object.

    Taken from rmurphey's comments here in this Gist.

    Layers of abstraction can be a nightmare to learn and adjust to, but when it serves a purpose and does it well, it just makes sense.

    jamesmortensen
    • 33,636
    • 11
    • 99
    • 120
    • 9
      You still have to manage all of those require and define statements, configuration files, collisions with other systems and libraries that haven't implemented the AMD specification, etc. I tried using Require.JS in a node-webkit project, and Require.JS fought me every step of the way... Contrast that with simply ordering scripts in a certain manner... Of course, you gain lazy-loading with Require.JS, which is why I tried making it work. :) – jamesmortensen Jun 20 '14 at 14:47
    • I totally agree with @jmort253, it was a struggle at the beginning, but now I like it very much. All three points are correct! And AMDifying a library should not be that difficult... or use the shim. – Legends Jan 06 '17 at 02:23
    0

    Here's a more concrete example.

    I'm working in a project with 60 files. We have 2 different modes of running it.

    1. Load a concatenated version, 1 large file. (Production)

    2. Load all 60 files (development)

    We're using a loader so we just have one script in the webpage

    <script src="loader.js"></script>
    

    That defaults to mode#1 (loading the one large concatenated file). To run the in mode#2 (separate files) we set some flag. It could be anything. A key in the query string. In this example we just do this

    <script>useDebugVersion = true;</script>
    <script src="loader.js"></script>
    

    loader.js looks something like this

    if (useDebugVersion) {
       injectScript("app.js");
       injectScript("somelib.js");
       injectScript("someotherlib.js");
       injectScript("anotherlib.js");
       ... repeat for 60 files ...
    } else {
       injectScript("large-concatinated.js");
    }
    

    The build script is just an .sh file that looks like this

    cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
    

    etc...

    If a new file is added we'll likely be using mode#2 since we're doing development we have to add an injectScript("somenewfile.js") line to loader.js

    Then later for production we also have to add somenewfile.js to our build script. A step we often forget and then get error messages.

    By switching to AMD we don't have to edit 2 files. The problem of keeping loader.js and the build script in sync goes away. Using r.js or webpack it can just read the code to build large-concantinated.js

    It can also deal with dependencies, for example we had 2 files lib1.js and lib2.js loaded like this

    injectScript("lib1.js");
    injectScript("lib2.js");
    

    lib2 needs lib1. It has code inside that does something like

    lib1Api.installPlugin(...);
    

    But as the injected scripts are loaded asynchronously there's no guarantee they'll load in the correct order. These 2 scripts are not AMD scripts but using require.js we can tell it their dependencies

    require.config({
        paths: {
            lib1: './path/to/lib1',
            lib2: './path/to/lib2',
        },
        shim: {
            lib1: {
                "exports": 'lib1Api',
            },
            lib2: {
                "deps": ["lib1"],
            },
        }
    });
    

    I our module that uses lib1 we do this

    define(['lib1'], function(lib1Api) {
       lib1Api.doSomething(...);
    });
    

    Now require.js will inject the scripts for us and it won't inject lib2 until lib1 has be loaded since we told it lib2 depends on lib1. It also won't start our module that use lib1 until both lib2 and lib1 have loaded.

    This makes development nice (no build step, no worrying about loading order) and it makes production nice (no need to update a build script for each script added).

    As an added bonus we can use webpack's babel plugin to run babel over the code for older browsers and again we don't have to maintain that build script either.

    Note that if Chrome (our browser of choice) started supporting import for real we'd probably switch to that for development but that wouldn't really change anything. We could still use webpack to make a concatenated file and we could use it run babel over the code for all browsers.

    All of this is gained by not using script tags and using AMD

    gman
    • 100,619
    • 31
    • 269
    • 393