Search code examples
javascriptjqueryrequirejsr.js

require.js shim option does not work when using r.js and `empty:`


I'm using jquery 1.11.3、require.js 2.1.18 and r.js 2.1.18

I want to put jquery.js outsite in order to use browser cache.

//file js/main.js
require.config({
        baseUrl: 'js',
        paths: {
                'jquery': '//cdn.bootcss.com/jquery/1.11.3/jquery.js'
        },
        shim: {
                'p': ['jquery']
        }
});

require(['jquery', 'p'], function($) {
        alert(222);
});


//file js/p.js
//this is an jquery plugin which does not support AMD
alert($().jquery);


//file build.js
({
        baseUrl: "js",
        name: "main",
        out: "app.js",
        paths: {jquery: "empty:"}
})

It will cause an error

`Uncaught ReferenceError: $ is not defined(anonymous function) @ app.js:1`

But the following code can work,alert("1.1.13") and then alert(222)

//file js/main.js
require.config({
        baseUrl: 'js',
        paths: {
                'jquery': 'jquery.js'
        },
        shim: {
                'p': ['jquery']
        }
});

require(['jquery', 'p'], function($) {
        alert(222);
});


//file js/p.js
alert($().jquery);


//file build.js
({
        baseUrl: "js",
        name: "main",
        out: "app.js",
        paths: {jquery: "jquery"}
})

What's wrong with the first section of code?Thanks~


Solution

  • RequireJS won't allow to do what you are trying to do. The notes on shim spell it out:

    Do not mix CDN loading with shim config in a build. Example scenario: you load jQuery from the CDN but use the shim config to load something like the stock version of Backbone that depends on jQuery. When you do the build, be sure to inline jQuery in the built file and do not load it from the CDN. Otherwise, Backbone will be inlined in the built file and it will execute before the CDN-loaded jQuery will load. This is because the shim config just delays loading of the files until dependencies are loaded, but does not do any auto-wrapping of define. After a build, the dependencies are already inlined, the shim config cannot delay execution of the non-define()'d code until later. define()'d modules do work with CDN loaded code after a build because they properly wrap their source in define factory function that will not execute until dependencies are loaded. So the lesson: shim config is a stop-gap measure for non-modular code, legacy code. define()'d modules are better.

    (Emphasis added.)

    Unless you rewrite p to be a proper AMD module, you have to abandon the CDN.