Using RequireJs with Sitecore 8 - Update

Estimated reading time:

This update has been a long time in coming! Last year I blogged about using Require.js to organize your Sitecore JavaScript. In the post we looked at setting up require js with jQuery. This was the main.js config file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require.config({
baseUrl: "/assets/js",
paths: {
jquery: "vendor/jquery.min",
"jquery.migrate": "vendor/migrate",
"jquery.mobile.events": "vendor/mobile.events",
"jquery.royalslider": "vendor/jquery.royalslider",
},
shim: {
"jquery.migrate": {
deps: ["jquery"]
},
"jquery.mobile.events": {
deps: ["jquery"]
},
"jquery.royalslider": {
deps: ["jquery"]
},
}
});
// Now run any initialization javascript for the site:
require(["jquery"], function($) {
// Init code here
});

This worked great in Sitecore 7.x, but in Sitecore 8 the page editor started breaking, lots of JavaScript errors. The reason for this is that the Prototype JavaScript library was used by the Experience Editor and conflicts with jQuery. See this KB Article

The obvious answer is to run jQuery in no-conflict mode. But how does that work with RequireJs?

One option would be to take jQuery out of the require dependencies and load it at the top of the page, put it in no-conflict mode and use an IIFE to load jQuery into to the module:

1
2
3
(function($) {
// plugin load code here
})(jQuery);

Credits: Sitecore preview mode and loading jQuery

But that kinda goes against the benefits and reasons for using RequireJs in the first place. Fortunately it is pretty easy to run jQuery in no-conflict mode using Require.

jQuery as an AMD Module

The first thing we need to do is define a new AMD module that puts jQuery into no conflict mode:

jquery.no-conflict.js

1
2
3
define(["jquery"], function(jq) {
return jq.noConflict(false);
});

Now we can add that module to our requirejs paths and then map it to our jquery path that we setup earlier in the post:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require.config({
baseUrl: "/assets/js",
paths: {
jquery: "vendor/jquery.min",
"jquery-private": "modules/jquery.no-conflict",
"jquery.migrate": "vendor/migrate",
"jquery.mobile.events": "vendor/mobile.events",
"jquery.royalslider": "vendor/jquery.royalslider",
},
shim: {
"jquery.migrate": {
deps: ["jquery"]
},
"jquery.mobile.events": {
deps: ["jquery"]
},
"jquery.royalslider": {
deps: ["jquery"]
},
},
map: {
// '*' means all modules will get 'jquery-private'
// for their 'jquery' dependency.
'*': {
'jquery': 'jquery-private'
},
// 'jquery-private' wants the real jQuery module
// though. If this line was not here, there would
// be an unresolvable cyclic dependency.
'jquery-private': {
'jquery': 'jquery'
}
}
});
// Now run any initialization javascript for the site:
require(["jquery"], function($) {
// Init code here
});

Notice that everything else still references the jquery path. Its the map that does the magic here!

So now you can still use jQuery and the Experience Editor without going and changing all your existing AMD Modules!

Happy coding!

–Richard

References: Mapping Modules to Use NoConflict