Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In RequireJS - Cannot alias jQuery name in path

I'm a RequireJS noob. When I use "require.config" and include a path to jQuery with a name different than jQuery, results are not as expected.

Here's a very simple example to help explain my issue.

Structure of files

root
├── Index.htm
└── scripts
    ├── libs
    │   ├── jquery-1.7.1.js
    │   └── require.js
    ├── main.js
    └── someModule.js

index.htm

<html>
<head>
    <title>BackboneJS Modular app with RequireJS</title>
    <script data-main="scripts/main" src="scripts/libs/require.js"></script>
</head>
<body>
    <h3>BackboneJS is awesome</h3>
</body>
</html>

Here the script tag references require in scripts/libs. When require gets ran the JavaScript file called main.js in the scripts directory should be executed.

main.js

require.config({
   "paths": {
           "mod1": "someModule"
   }
});
require(["mod1"], function (sm) {
    console.log(sm.someValue);
});

In my experience the "mod1" can be anything as long as it's referenced the same in the require.config path and in the require method.

someModule.js

define([], function () {
    console.log();
    return { someValue: "abcd" };
});

Just for completeness I included someModule.js

The perceived inconstancy occurs when I include JQuery.

In the following main.js I added jQuery to the config and the require method.

Main.js

require.config({
    "paths": {
        "jquery": "libs/jquery-1.7.1"
        ,"mod1": "someModule"
    }
});

require(["mod1", "jquery"], function (sm, $) {
    console.log(sm.someValue);
    console.log($);
});

With the additional of jQuery everything seems to still works. The "console.log($)" writes the jQuery function.

Now the kicker. In the following code I change "jquery" to "jqueryA" in both the paths and require

require.config({
    "paths": {
        "jqueryA": "libs/jquery-1.7.1"
        ,"mod1": "someModule"
    }
});

require(["mod1", "jqueryA"], function (sm, $) {
    console.log(sm.someValue);
    console.log($);
});

Now "console.log($)" writes null.

Should this be expected? Is there a reason why the name must be jquery, but for mod1 it can be anything?

I can work-around this without a problem, but this issue seems odd. I know I can use the combined RequireJS and jQuery file, but when jQuery has an update I don't want to be dependent on RequireJS to include the new jQuery.

like image 373
Mike Barlow - BarDev Avatar asked Jan 04 '12 23:01

Mike Barlow - BarDev


People also ask

How does RequireJS load modules?

RequireJS uses Asynchronous Module Loading (AMD) for loading files. Each dependent module will start loading through asynchronous requests in the given order. Even though the file order is considered, we cannot guarantee that the first file is loaded before the second file due to the asynchronous nature.

What is Shim RequireJS?

shim: Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value. Here is an example. It requires RequireJS 2.1. 0+, and assumes backbone. js, underscore.

What is RequireJS config JS?

RequireJS is a JavaScript file and module loader. It improves perceived page load times because it allows JavaScript to load in the background. In particular, it enables asynchronous JavaScript loading.

What is the use of RequireJS?

RequireJS is a JavaScript library and file loader which manages the dependencies between JavaScript files and in modular programming. It also helps to improve the speed and quality of the code.


2 Answers

In jQuery 1.7 they decided to support AMD loading. To do this, it defines a module named 'jquery' which passes back a reference to the jQuery object. When you define your path to jquery with another name (eg 'jqueryA'), things aren't exactly breaking as you think they are.

The jquery script always defines itself as a module named 'jquery', which is registered with require for your app. When you named your path shortcut 'jquery' and 'jquery' was loaded as a dependency, require was actually referencing the 'jquery' module defined by jquery-1.7.1.js, which does pass back the correct reference. When you name your module shortcut jqueryA, you are now referencing an undefined reference, because the jquery script itself does not pass back a reference, except via the module named 'jquery'. It's silly, I know.

The jquery script defines the module as 'jquery' and expects that you will simply reference it as 'jquery'. If you want to reference it as another name (and as a bonus, keep it from conflicting with other loaded jquery libraries), use this method:

Use requirejs and jquery, without clobbering global jquery?

like image 160
Matt S Avatar answered Oct 15 '22 12:10

Matt S


Here's my workaround, based on the implementation I read of Require.JS 2.1.0:

define.amd.jQuery = false;

require.config({
    ...

    shim: {
        "jQuery-1.8.2": {
            exports: "jQuery"
        }
    }

    ...
});
like image 4
Pierre Voisin Avatar answered Oct 15 '22 13:10

Pierre Voisin