-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
shim not working? #358
Comments
and then a further question. if i have a scenario where i wanted to apply a patch to Backbone and have it always applied when I require |
sorry one more addition, in anonymous define calls requiring
|
The only thing I can think of is to make sure you are using requirejs 2.0.2, at the very least 2.0, since shim is new for 2.0. But at first glance it looks correct. Feel free to pass me a test link though for more thorough debugging. The link can be sent to me off-list. |
I have a problem with dependencies too. Shimmed scripts are loaded before their shimmed dependencies. Running 2.0.2 |
I don't know if it is relevant but the scripts I am trying to load are inside a self executing function
|
@chchrist an example that I can try would be helpful. The self executing functions should not be a problem. The point of shim is to be able to use older scripts that do not call define(). I have some unit tests for shim, and I believe it is used in a backbone boilerplate, so the general mechanism works. The issue is likely an edge case I am not aware of. One caveat, mentioned in the docs (near the end of that section): if these errors are occurring after a build, and because one of the shimmed libraries is excluded in the build, that will fail -- for the shimming to work, all the shimmed libraries need to be included in the built file. |
I'll upload an example somewhere to test. I have the problem before the build |
I have problems with shim too. require.config({
paths: {
'jquery.mobile-config': 'libs/jqm/jquery.mobile-config',
jquery: 'libs/jquery/jquery',
'jquery.mobile': 'libs/jqm/jquery.mobile',
Underscore: 'libs/underscore/underscore',
Backbone: 'libs/backbone/backbone',
// jquery: 'http://code.jquery.com/jquery-1.7.2.min',
// 'jquery.mobile': 'http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min',
// Underscore: 'http://underscorejs.org/underscore-min',
// Backbone: 'http://backbonejs.org/backbone-min'
},
shim: {
'Underscore': {
exports: '_'
},
'Backbone': {
deps: ['Underscore', 'jquery'],
exports: 'Backbone'
},
'jquery.mobile-config': ['jquery'],
'jquery.mobile': ['jquery', 'jquery.mobile-config']
}
});
require(['app', 'jquery.mobile'], function(App) {
App.initialize();
}); I need some settings for jQuery Mobile, so I have additional jquery.mobile-config module: define(['jquery'], function ($) {
console.log('jquery.mobile-config');
$(document).on('mobileinit', function () {
console.log('mobileinit');
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.autoInitializePage = false;
$('div[data-role="page"]').live('pagehide', function (event, ui) {
$(event.currentTarget).remove();
});
});
}); It works just fine without RequireJS optimization step and writes to browser console
But with optimization jquery.mobile-config module doesn't execute and browser console is empty. ({
appDir: 'src',
baseUrl: '.',
dir: 'build',
mainConfigFile: 'src/main.js',
name: 'main'
}) I found three ways to fix problem.
require(['app', 'jquery.mobile-config', 'jquery.mobile'], function(App) {
App.initialize();
});
define( [ "jquery" ], function ( $ ) {
factory( $, root, doc );
return $.mobile;
}); List of dependencies can be extended by 'jquery.mobile-config' entry.
({
appDir: 'src',
baseUrl: '.',
optimize: 'none',
dir: 'build',
mainConfigFile: 'src/main.js',
paths: {
'jquery.mobile': 'empty:', // <---
},
name: 'main'
}) |
@kodemi: the test zip file's build config is this: ({
appDir: 'src',
baseUrl: '.',
optimize: 'none',
dir: 'build',
mainConfigFile: 'src/main.js',
paths: {
jquery: 'empty:',
// 'jquery.mobile': 'empty:',
Underscore: 'empty:',
Backbone: 'empty:'
},
modules: [
{
name: 'main',
}
]
}) which will not work -- shim dependencies need to be included in the build, but that build config does not include jquery, backbone or underscore, so that causes one type of error. The need to include shim dependencies in a build is listed in the shim config section of the docs, although it is near the bottom of it. However, including them does not completely fix the issue, because the shim config is ignored if the module already calls define() to set its dependencies. jquery.mobile calls define, just with a dependency of 'jquery'. Before a build though, jquery.mobile has not been loaded, so it is not known if it calls define, so the shim config, which mentions jquery.mobile-config is used, an jquery.mobile-config is loaded. However after a build, jquery.mobile is in the file and its define is seen, so the shim config is ignored. Since no other module in the build file depends on jquery.mobile-config, that module is not executed. That explains the after build behavior. I would think the way to fix it: remove the shim config for jquery.mobile, and then have your main.js require() call also load jquery.mobile-config. Also, jquery.mobile.config does not need a shim config, since it calls define() itself. There also seems to be a bug in jquery mobile that will be (is?) fixed in 1.1.1 for jquery mobile, some details here (read the group thread mentioned in the bug): |
If anyone has a test case that shows shim failing, please feel free to point me to it. So far, I have not seen something that is a bug in shim, but more about the restrictions in the situations where it is useful. Those scenarios are discussed in the shim config doc section. I am going to close this ticket for now, but please feel free to continue any discussion, and post any test cases. We can reopen or file specific bugs as needed. |
FWIW the limitation of shims that they their dependencies cannot be excluded in a build is not incredibly clear from the docs. It's in a CDN loading paragraph at the very end. I wasn't doing CDN loading so I didn't think it applied to me until I got here and read this thread. Something explicit about multi-file builds would be helpful I think. |
Thanks for the feedback, I added this info to that section: |
No problem. I can't quite wrap my head around how doing an outer require would work in an optimized build like you mention in that section. The outer require would actually have to happen outside of the file that needs it, so if you had a Is there a reason you can't wrap shimmed scripts in a |
What would be even better (and i should probably open another issue for this or start a mailing list discussion, let me know if you'd like me to) is if the optimizer was smart enough to do an outer require around everything for anything that is excluded and actually needed. As it is now in the multipage example you need to do |
Shim config tries to preserve the scope of the scripts being shimmed, because some make global names by just doing If you want to avoid an extra script to have the nested require() calls, put them inline in the HTML as shown in this example-multipage-shim example: |
That makes sense about the globals, thanks. And thanks for the example, that's helpful and a good idea. |
Could you do something like this to wrap and capture them for an r.js build? define('{{defineName}}', {{dependencies || []}}, function({{dependencyNames}})){
var {{exportName}} = null; //--ensure {{exportName}} is local
{{scriptContents}}
if(window.{{exportName}} !== {{exportName}}){
if({{exportName}} !== null){ //--handle module with locally scoped export
{% if must export global %}
window.{{exportName}} = {{exportName}};
{% endif %}
}else{ //--handle module that attaches to window explicitely
{{exportName}} = window.{{exportName}};
}
}
return {{exportName}};
}); {{defineName}} being the name the module is defined as and {{exportName}} being the name it is configured to export in the shim configuration. The {{dependencyNames}} perhaps might be hard, either:
For items without an {{exportName}}, the callback would consist only of {{scriptContents}}. |
Ticket #623 introduces a |
Is that the right ticket number? I don't see anything define('{{defineName}}', {{dependencies || []}}, function({{dependencyNames}})){
var fn = function(){
var {{exportName}} = null; //--ensure {{exportName}} is local
{{scriptContents}}
if(this.{{exportName}} !== {{exportName}}){
if({{exportName}} !== null){ //--handle module with locally scoped export
{% if must export global %}
this.{{exportName}} = {{exportName}};
{% endif %}
}else{ //--handle module that attaches to window explicitely
{{exportName}} = this.{{exportName}};
}
}
return {{exportName}};
};
return fn.apply(window, arguments);
}); |
Sorry, wrong repo, thought I was in r.js. Here is the wrapShim: |
Cool. Glad that's going in. I will give it a try. |
Shim dependency doesn't work with the optimized build. See requirejs/requirejs#358 for some more info. This seems like the best way and what jburke recommends requirejs/requirejs#358 (comment)
Shim dependency doesn't work with the optimized build. See requirejs/requirejs#358 for some more info. This seems like the best way and what jburke recommends requirejs/requirejs#358 (comment) Conflicts: js/main.js
i'm not sure if it's not working or i'm not getting the API right. here's what my paths looks like:
and here's my shim:
but if i put in breakpoints,
hephaestus.min
gets run beforebackbone-custom.min
ever does.The text was updated successfully, but these errors were encountered: