English 中文(简体)
What s the difference between Require.js and simply creating a <script> element in the DOM? [closed]
原标题:
Closed. This question is opinion-based. It is not currently accepting answers.

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 6 years ago.

What s the difference between using Require.JS amd simply creating a <script> element in the DOM?

My understanding of Require.JS is that it offers the ability to load dependencies, but can this not simply be done by creating a <script> element that loads the necessary external JS file?

For example, lets assume I have the function doStuff(), which requires the function needMe(). doStuff() is in the external file do_stuff.js, while needMe() is in the external file need_me.js.

Doing this the Require.JS way:

define([ need_me ],function(){
    function doStuff(){
        //do some stuff
        needMe();
        //do some more stuff
    }
});

Doing this by simply creating a script element:

function doStuff(){
    var scriptElement  = document.createElement( script );
    scriptElement.src =  need_me.js ;
    scriptElement.type =  text/javascript ;
    document.getElementsByTagName( head )[0].appendChild(scriptElement);

    //do some stuff
    needMe();
    //do some more stuff
}

Both of these work. However, the second version doesn t require me to load all of the Require.js library. I don t really see any functional difference...

最佳回答

Here is the nice article on ajaxian.com as to why use it:

RequireJS: Asynchronous JavaScript loading

  • some sort of #include/import/require
  • ability to load nested dependencies
  • ease of use for developer but then backed by an optimization tool that helps deployment
问题回答

What advantages does Require.JS offer in comparison to simply creating a element in the DOM?

In your example, you re creating the script tag asynchronously, which means your needMe() function would be invoked before the need_me.js file finishes loading. This results in uncaught exceptions where your function is not defined.

Instead, to make what you re suggesting actually work, you d need to do something like this:

function doStuff(){
    var scriptElement  = document.createElement( script );
    scriptElement.src =  need_me.js ;
    scriptElement.type =  text/javascript ;

    scriptElement.addEventListener("load", 
        function() { 
            console.log("script loaded - now it s safe to use it!");

            // do some stuff
            needMe();
            //do some more stuff

        }, false);

    document.getElementsByTagName( head )[0].appendChild(scriptElement);

}

Arguably, it may or may not be best to use a package manager such as RequireJS or to utilize a pure-JavaScript strategy as demonstrated above. While your Web application may load faster, invoking functionality and features on the site would be slower since it would involve waiting for resources to load before that action could be performed.

If a Web application is built as a single-page app, then consider that people won t actually be reloading the page very often. In these cases, preloading everything would help make the experience seem faster when actually using the app. In these cases, you re right, one can merely load all resources simply by including the script tags in the head or body of the page.

However, if building a website or a Web application that follows the more traditional model where one transitions from page to page, causing resources to be reloaded, a lazy-loading approach may help speed up these transitions.

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.

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





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签