Using private jquery with RequireJS - issue after

2019-02-19 10:44发布

问题:

I'm putting together a framework using requireJS with a CDN version of jQuery (as is now the recommended approach) and having some issue when optimizing the code. The output is namespaced and I'm specifying that each module use a private version of jquery as outlined in the documentation:

require.config({
    // Add this map config in addition to any baseUrl or
    // paths config you may already have in the project.
    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' }
    }
});

// and the 'jquery-private' module, in the
// jquery-private.js file:
define(['jquery'], function (jq) {
    return jq.noConflict( true );
});

The problem I'm seeing after optimization is that "jq" is undefined in the "jquery-private.js" file.

Any ideas? I've tried setting jq = $ but that seems to destroy the global.

Thanks.

回答1:

Here is what I did to get the jQuery CDN & optimization sample linked from the RequireJS jQuery Instructions page to work with the Mapping Modules to use noConflict section that you pasted in your original question.

1 - Forked the sample

2 - Created file www/js/lib/jquery-private.js with this content

define(['jquery'], function (jq) {
    return jq.noConflict( true );
});

3 - Modified www/js/app.js to paste the map section so the require.config now looks like this:

requirejs.config({
    "baseUrl": "js/lib",
    "paths": {
      "app": "../app",
      "jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
    },
    map: {
      '*': { 'jquery': 'jquery-private' },
      'jquery-private': { 'jquery': 'jquery' }
    }    
});

4 - Modified www/js/app/main.js to use jqlocal instead of $ (just to prove to myself that it's not the global jQuery:

define(["jquery", "jquery.alpha", "jquery.beta"], function(jqlocal) {
    jqlocal(function() {
        jqlocal('body').alpha().beta();
    });
});

5 - Changed to the tools folder and ran:

node r.js -o build.js

6 - Changed to the www-build folder that was created and ran servedir (doesn't really matter what web server but that's what I use for dev)

7 - Browsed to the local address & port number of the app (in my case http://localhost:8000/app.html) and saw:

Alpha is Go!

Beta is Go!

You can see the end result here



回答2:

To get this working I changed the way I was using Require (possibly how I should have been doing it all along). This information might prove useful to others, so I thought I'd put it out there.

Previously I was specifying any dependencies in the defined module:

define( [ "dep1", "dep2", "jquery" ], function( var1, var2, jq ) {

This worked fine initially, but failed when optimized. I moved the dependencies to the require function call including this module and it then started to work OK both pre and post optimisation, with jquery being used privately:

require( [ 'jquery', 'dep1', 'dep2' ], function( jq, var1, var2 ) {
    formValidator.formValidationInit( jq( el ) );
});

I wouldn't have thought this would have made a difference, but it seemed too.

It is also worth noting that I had to change the jquery-private file as it was still throwing up an issue concerning "jq" not being defined. I am now setting jq equal to the global $ and returning it so it can be used pivately:

define(['jquery'], function () {
    var jq = $;
    return jq.noConflict( true );
});