RequireJS multipleversion dependencies - requirejs

I have a couple of different apps in my application. Some newer with Backbone only and older with Marionette, since Marionette uses Backbone both uses Underscore.
Now I want to update Underscore, 1.6.0 -> 1.8.3.
So I make a legacy underscore in my require.config
paths: {
'underscore': 'vendor/underscore/underscore',
'underscore-1.6.0': 'vendor/underscore-1.6.0/underscore',
'backbone': 'vendor/backbone/backbone',
'backbone-1.1.2': 'vendor/backbone-1.1.2/backbone',
'marionette': 'vendor/marionette/lib/core/amd/backbone.marionette',
'backbone.wreqr': 'vendor/backbone.wreqr/lib/backbone.wreqr',
'backbone.babysitter': 'vendor/backbone.babysitter/lib/backbone.babysitter',
},
shim: {
'underscore-1.6.0': {
exports: 'underscore'
},
'backbone-1.1.2': {
deps: ['underscore-1.6.0'],
exports: 'backbone'
},
'backbone.babysitter': {
deps: ['backbone-1.1.2', 'underscore-1.6.0']
},
'backbone.wreqr': {
deps: ['backbone-1.1.2', 'underscore-1.6.0']
},
'marionette': {
deps: ['backbone-1.1.2']
}
},
Marionette depends on both Wreqr and Babysitter, which in turn depending on underscore 1.6.0 (and Backbone 1.1.2). My solution is to add deps for both of them.
My problem is when im trying to require('marionette'); as both wreqr and babysitter are asking for 'underscore' and 'backbone' they are getting the none-legacy not 'underscore-1.6.0' and 'backbone-1.1.2'.
Can I some how decide which version of underscore and backbone "backbone" and "underscore" Wreqr and Babysitter should use?
Is there any other good way to this?
Thank!
Johan

All the packages you mention are proper AMD modules. For each package that does not have a version number, I checked the sources of the latest version. For versioned names, I checked the specific version in the name. In all cases, they check for the existence of define.amd and call define. Therefore, they are proper AMD modules. Consequently, you cannot use shim with them. The shim configuration is only for modules that are not really AMD modules (do not call define).
Now, the problem is that packages that need Backbone will require backbone and those that need Underscore will require underscore. They do not distinguish by version. You can force them to use specific versions by using the map configuration:
map: {
'backbone-1.1.2': {
underscore: 'underscore-1.6.0'
},
'backbone.babysitter': {
backbone: 'backbone-1.1.2',
underscore: 'underscore-1.6.0'
},
'backbone.wreqr': {
backbone: 'backbone-1.1.2',
underscore: 'underscore-1.6.0'
},
marionette: {
backbone: 'backbone-1.1.2'
}
}
Everywhere in your application if backbone or underscore are required then the modules backbone or underscore are loaded. The map establishes exceptions to this rule. When backbone.babysitter requires backbone then backbone-1.1.2 is loaded instead. When it requires underscore then underscore-1.6.0 is loaded instead. Similarly for the other modules in the map.

Related

How to add AMD/legacy dependency (leaflet) with sub dependencies in requirejs

I installed a AMD module called leaflet and successfully using it as "L".
Next I need a plugin called leaflet.draw but I get confused about the dependencies. Consider the following code:
requirejs.config({
baseUrl: 'bower_components',
paths: {
leaflet: 'leaflet/dist/leaflet-src',
leafletdraw: 'leaflet-draw/dist/leaflet.draw-src'
...
requirejs(["leaflet", "leafletdraw"], function(L, leafletdraw) {
var map = new L.Map('map');
...
This gives a referenceError: L is not defined at Leaflet.draw.js:4. So I guess it needs the leaflet (L) as a dependency, right? I then tried to add it in the shim config:
shim: {
leafletdraw: {
deps: 'leaflet'
}
}
This results in a "Invalid require call". So my question is: How do I properly require a plugin with subdependencies?
The modules are installed with "bower install leaflet" and "bower
install leaflet-draw" respectivily. But im not sure if leaflet-draw
is AMD enabled. Why isnt that stated in repos docs? Can I assume it
is enabled by default?
This is what I try to achive:
http://codepen.io/osmbuildings/pen/LVJzWw, but with requirejs.
Solution: shim leaflet itself, and let it export 'L'. Then putting the deps in plugins will work. My full config:
requirejs.config({
baseUrl: 'bower_components',
paths: {
jquery: 'jquery/dist/jquery.min',
leaflet: 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet',
'leaflet-draw': 'http://cdn.osmbuildings.org/Leaflet.draw/0.2.0/leaflet.draw',
OSMBuildings: ['http://cdn.osmbuildings.org/OSMBuildings-Leaflet']
},
shim: {
leaflet: {
exports: 'L'
},
'leaflet-draw': {
deps: ['leaflet']
},
OSMBuildings: {
deps: ['leaflet'],
exports: 'OSMBuildings'
}
}
});
requirejs(["jquery", "leaflet", "leaflet-draw", "OSMBuildings"], function($, L, dummy, OSMBuildings) {
var map = new L.Map('map');

Bootstrap library with requirejs

I am trying to use bootstrap with require js. So far jquery, underscore and boostrap are loading fine, but I am having issues with one library not loading: bootstrap-tagsinput. How can I debug requirejs and see whether this library is loading or not?
Here is my common.js
requirejs.config({
shim: {
'jquery': {
exports: '$'
},
'underscore': {
exports: '_'
},
'bootstrap': {
deps: [ "jquery" ]
},
'bootstrap-tagsinput': {
deps: [ "bootstrap" ]
}
},
baseUrl: "/",
paths: {
'jquery': [
'//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min',
'jquery/jquery.min'
],
'underscore': [
'//underscorejs.org/underscore-min',
'underscore/underscore-min'
],
'bootstrap': [
'//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min',
'bootstrap/dist/js/bootstrap.min'
],
'bootstrap-tagsinput': 'bootstrap-tagsinput/dist/bootstrap-tagsinput.min'
}
});
Require.js is invented to handle dependencies between modules, so it is quite clear that you specify those dependencies in the modules where you use it like you said in your own answer already. The function given as the second parameter to define() gets handles to those modules in the order they are given.
As $ is normally used for jQuery library, it is not a good idea to use $ for something else, because this would create a lot of confusion. But normally you need jQuery in a module as well, so your define() call will most probably look like
define['jquery', 'bootstrap-tagsinput'], function($) {
...
});
In this case $ is bound to jQuery, not to bootstrap-tagsinput. It is instead called via the jQuery mechanisms, so you don't need a second parameter in the function.
I figured out that 'bootstrap-tagsinput' needs to be defined where it's being used. For example, in a page that makes use of this library:
define(['bootstrap-tagsinput'], function() {
// js for the page here
});
And in order to auto-load modules that should always be available (eg. bootstrap or jquery) we can do the same.
define(['bootstrap'], function() {
// main.js contents
});

Automatically load postrequisite files

I'm looking to automatically load dependant files, similarly to how deps works however these files need to be loaded AFTER the initially requested.
For example:
require.config({
baseUrl: '/',
paths: {
jquery: '/assets/components/jquery/dist/jquery.min',
highcharts: '/assets/components/highcharts/highcharts.js',
'highcharts.more': '/assets/components/highcharts/highcharts-more.js'
},
shim: {
jquery: { exports: 'jQuery' },
highcharts: { deps: ['jquery'] },
'highcharts.more' : { deps: ['highcharts'] },
}
});
define(function (require) {
var app = require('assets/js/app');
app.start();
});
When requiring highcharts, jQuery will automatically be loaded as a dependant, however Highcharts requires that you load two files.
Does anyone know how I can load postrequisite files, i.e. after loading highcharts to automatically load highcharts.more.
I could simply set highcharts a dependency of highcharts-more and load highcharts-more however hoped there was a cleaner way?
Hope this makes sense?!
Thanks
Gav
Loading highcharts.more and making it a dependency of highcharts is the way to go. You can also hide highcharts.more from your modules by using a map configuration:
map: {
"*": {
highcharts: "highcharts.more"
},
"highcharts.more": {
highcharts: "highcharts"
}
}
The mapping above says "in all modules (*) when highcharts is requested, load highcharts.more instead, but in highcharts.more when highcharts is requested load highcharts".
With this, you can just list highcharts as a dependency in your actual modules.

How to use hammer.js plugins with require.js

I am trying to use hammer.js plugins with require.js but I have no luck.
Here is my code:
requirejs.config({
paths: {
"jquery": ('__proto__' in {}) ? "lib/zepto" : "lib/jquery",
"hammer-jquery": "lib/jquery.hammer",
"hammer-showtouches": "lib/hammer.showtouches",
"hammer-fakemultitouch": "lib/hammer.fakemultitouch"
},
shim: {
"jquery": {
exports: "$"
},
"hammer-showtouches": {
deps: [ "hammer-jquery" ],
exports: "Hammer.plugins.showTouches"
},
"hammer-fakemultitouch": {
deps: [ "hammer-jquery" ],
exports: "Hammer.plugins.fakeMultitouch"
}
},
waitSeconds: 30
});
requirejs(["jquery","hammer-jquery","hammer-showtouches","hammer-fakemultitouch"], function ($,Hammer) {
$(function(){
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
Hammer.plugins.showTouches();
Hammer.plugins.fakeMultitouch();
}
});
});
And here is the error:
Uncaught TypeError: Cannot read property 'plugins' of undefined hammer.showtouches.js:7
Uncaught TypeError: Cannot read property 'plugins' of undefined require.js:8
Uncaught TypeError: Cannot read property 'plugins' of undefined hammer.fakemultitouch.js:7
Uncaught TypeError: Cannot read property 'plugins' of undefined require.js:8
I have tried to include Hammer in shim config with no luck (It's not necessary beacause last version of jquery.hammer is AMD compatible).
Your issue appears to be that you didn't include the hammerjs library which is required by the hammerjs jquery plugin.
To fix this problem, you'll need to add to your requirejs path something like 'hammer':'lib/hammerjs/dist/hammer.min',
Additionally, here's some related information on how I used hammerjs with requirejs.
In my case, I wanted it to work with backbone and requirejs. I installed the libraries with bower.
bower install --save hammerjs
bower install --save backbone.hammer
Then, I proceeded to add the RequireJS configuration:
I noticed that jquery.hammer.js is AMD and automatically requires jquery. It also silently depends on Hammer. It modifies jquery to support Hammer. No shim is required.
I noticed that hammerjs is AMD and automatically exports Hammer. No shim is required.
I noticed that backbone.hammer is AMD and automatically requires underscore, backbone, and hammer. It modifies Backbone to support Hammer. No shim is required.
Therefore, my configuration uses paths only (since no shim support is required):
require.config({
'baseUrl':'',
'paths':{
'underscore':'js/lib/underscore-amd/underscore-min',
'backbone':'js/lib/backbone-amd/backbone-min',
'jquery':'js/lib/jquery/jquery.min',
'hammer':'js/lib/hammerjs/dist/hammer.min',
'jquery-hammer':'js/lib/hammerjs/dist/jquery.hammer.min',
'backbone-hammer':'js/lib/backbone.hammer/backbone.hammer'
},
shim:{
'underscore': { exports: '_' },
'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' }
}
});
Wrap HammerJS then bind to the global window:
// #path utils/hammer
define([
'hammer'
], function (Hammer) {
window.Hammer = Hammer;
});
Then make whatever plugins or modules which have dependencies on HammerJS depend on utils/hammer.

Intern configuration not processing AMD shim

I am trying to test a Require.js project using Intern. I'm running into errors in my tests where jQuery is not defined when jQuery plugins are being loaded. My loader config looks like this:
loader: {
// Aliased paths
paths: {
'dt': 'dt',
'jq': 'jquery',
'jquery': 'jquery/jquery-1.8.3',
'jquerymx': 'jquery/jquerymx-3.2.custom',
'jquery.ui': 'jquery/jquery-ui-1.9.2.custom.min',
'jquery.ui.widget': 'jquery/jquery.ui.widget',
'jquery.jscrollpane': 'jquery/jquery.jscrollpane.min.edit',
'jquery.colorbox': 'jquery/jquery.colorbox-min',
'jquery.selectbox': 'jquery/jquery.selectbox-0.2.min.edit',
'jquery.base64': 'jquery/jquery.base64',
'jquery.cookie': 'jquery/jquery.cookie',
'jquery.urldecoder': 'jquery/jquery.urldecoder.min',
'jquery.fileupload': 'jquery/jquery.fileupload',
'jquery.history': 'history/scripts/compressed/history.adapter.jquery',
'openajax': 'openajax_2.0.7/OpenAjaxUnmanagedHub',
'zeroclipboard': 'zeroclipboard/ZeroClipboard'
},
// Plugin mappings
map: {
'*': {
'css': 'requirejs/require-css/css',
'text': 'requirejs/text'
}
},
// Shims for non-AMD libraries, mainly jQuery plugins
shim: {
'openajax': {
exports: 'OpenAjax'
},
'zeroclipboard': {
exports: 'ZeroClipboard'
},
'jquerymx': ['jquery'],
'jquery.ui': ['jquery'],
'jquery.ui.widget': ['jquery'],
'jquery.jscrollpane': ['jquery'],
'jquery.colorbox': ['jquery'],
'jquery.selectbox': ['jquery'],
'jquery.base64': ['jquery'],
'jquery.cookie': ['jquery'],
'jquery.urldecoder': ['jquery'],
'jquery.fileupload': ['jquery'],
'jquery.history': [
'jquery',
'history/scripts/compressed/history',
'history/scripts/compressed/history.html4'
]
}
}
I've checked to make sure jQuery and my other dependencies are actually being loaded, and they are, just not in the right order. Does the Dojo AMD loader that Intern use not handle the shim configuration?
The problem is that the AMD loader used by intern doesn't currently implement the shim configuration propertyAMD Specification. I was actually unaware that it was part of the standard until you asked this question.
At the moment, you could run functional tests using a different AMD loader via Intern, but at the moment, it would be difficult to run unit tests on the local machine.
All I had to do was point useLoader config to the require.js, and poof. I had the familiar shim config and path config I use in my app. Bam.

Resources