I would like to load and use mustache by requirejs.
Maybe this question has already asked:
AMD Module Loading Error with Mustache using RequireJS
Anyway I am trying to figure out how can I fix my code:
main.js
require.config({
paths: {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-optamd3-min',
mustache: "libs/mustache/mustache"
}
});
require([
'views/app'
], function(AppView){
var app_view = new AppView;
});
app.js
define([
'jquery',
'underscore',
'backbone',
"mustache"
], function($, _, Backbone, Mustache) {
console.log($, _, Backbone, Mustache); // <-- *** Mustache is null ***
// ......
}
);
As you can see in the comment on app.js file, Mustache is null...
Should I use another library of Mustache?
Here what I am using Mustache
Looks like Mustache supports AMD modules as of July '12. So it should now work out of the box with a loader such as require.js.
You should just create in your mustache directory a new file mustache-wrap.js which looks like this:
define(['libs/mustache/mustache'], function(Mustache){
// Tell Require.js that this module returns a reference to Mustache
return Mustache;
});
and then your main will be:
mustache: "libs/mustache/mustache-wrap"
Not sure if RequireJS 2.1.0 was out at the time of posting this question (and the answers) but the preferred way of handling this now is using shim config element (more info on project's docs page).
Your main.js would become:
require.config({
paths: {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-optamd3-min',
mustache: "libs/mustache/mustache"
},
shim: {
'mustache': {
exports: 'Mustache'
}
}
});
(...)
That's effectively the same as wrapper suggested #AntoJs, but without the boilerplate code.
...but then, since Mustache supports AMD there's no need to wrap/shim in the first place!
You could probably also do in-line named define in the code that consumes mustache, or somewhere in "main.js" (saves the trouble of creating *-wrap file)
define('mustache', ['libs/mustache/mustache'], function(){
// Tell Require.js that this module returns a reference to Mustache
return Mustache; // from global
});
require(
['jquery','underscore','backbone','mustache']
, function($, _, BB, Mustache){
// use them
}
)
Related
This code is working fine on Chrome, IE and also android and IOS but an issue occurs sometimes on Firefox. After a few reload of the page the issue is gone!
Error: Module name 'underscore' has not been loaded yet for context: _
http://requirejs.org/docs/errors.html#notloaded require.js (line 7, col 217)
The code :
core.js
require.config({
paths: {
text: 'libs/text',
loader: 'libs/backbone/loader',
jQuery: 'libs/jquery/jquery',
Underscore: 'libs/underscore/underscore',
Backbone: 'libs/backbone/backbone',
'hammer': 'libs/jquery/hammer-min'
},
shim: {
Underscore: { deps: ['jQuery'] },
Backbone: { deps: ['Underscore'] }
}
});
require(['routers/core'], function (App) {
jQuery(document).ready(function () {
App.start();
});
});
routers/core.js
define([
'jQuery',
'Underscore',
'Backbone',
'routers/common'
], function ($, _, Backbone, CommonRouter) {
var start = function () {
var app = {
init: function () {
}
};
_.extend(CommonRouter.prototype, app);
var app_router = new CommonRouter;
Backbone.history.start();
};
return { start: start };
});
libs/backbone/loader.js
define([
'libs/jquery/jquery-base64',
'libs/jquery/jquery-easing',
'libs/jquery/jquery-inputmask',
'libs/jquery/jquery-mousewheel',
'libs/jquery/jquery-tagsinput',
'libs/jquery/jquery-validate',
'libs/jquery/highcharts',
'libs/jquery/raphael',
'libs/jquery/selectreplace',
'libs/jquery/touchswipe',
'libs/jquery/flowplayer-min',
'libs/underscore/underscore-min',
'libs/backbone/backbone-min'
],
function(){
return {
Backbone: Backbone.noConflict(),
_: _.noConflict(),
$: jQuery.noConflict()
};
});
The issue is that Backbone: Backbone.noConflict(), is undefined because the module "underscore" is not loaded yet.
How can I wait and be sure the modules required are loaded when I need them?
To answer your question:
How can I wait and be sure the modules required are loaded when I need them?
We can use the shim option of configuration for that.
To setup jQuery and underscore as dependencies of backbone you should do:
shim: {
backbone: { deps: ['jQuery','underscore'] }
}
You seem to have setup jQuery as a dependency of underscore where there is no actual dependency between them, which is unnecessary.
Apart from that you seems to have few issues -
First of all, you haven't specified any arguments to your libs/backbone/loader.js module. Since there is no global backbone or _ in window, unless you specify these your module won't have a way to access to the exports apart from the arguments object, unless somehow it's available in it's the parent scope.
Most of your imports seems to be jQuery plugins that just modifies jQuery. In such case you should specify them after all other libs that actually exports something which you want to use so that you don't have to specify an argument for each.
another issue could be that you're using the short path names to setup the shim option but you're using the full path (for eg libs/backbone/backbone-min) to load the libraries in libs/backbone/loader.js.
I wonder how it works for you in other browsers without specifying the import names as arguments.
define([
'underscore',
'jquery',
'backbone'
'libs/jquery/jquery-base64',
'libs/jquery/jquery-easing',
'libs/jquery/jquery-inputmask',
'libs/jquery/jquery-mousewheel',
'libs/jquery/jquery-tagsinput',
'libs/jquery/jquery-validate',
'libs/jquery/highcharts',
'libs/jquery/raphael',
'libs/jquery/selectreplace',
'libs/jquery/touchswipe',
'libs/jquery/flowplayer-min'
],
function(_,
$,
Backbone
/*all other imports in order*/
) {
return {
Backbone: Backbone.noConflict(),
_: _.noConflict(),
$: jQuery.noConflict()
};
});
side note: I modified the first letter of path names to small letter because I prefer having a consistent naming convention
Here's my situation, using Backbone and Handlebars with Requirejs.
I'm following CommonJS module definition style, because I find myself to be more comfortable with it:
define(function(require) {
var Backbone = require('Backbone')
var Item = require('model/item')
// ...
})
And this is my requirejs config:
require.config({
baseUrl: "/javascripts/",
paths: {
jquery: 'components/jquery/jquery',
underscore: 'components/underscore/underscore',
backbone: 'components/backbone/backbone',
handlebars: 'components/handlebars/handlebars',
text: 'components/text/text'
},
shim: {
underscore: {
exports: "_"
},
handlebars : {
exports: "Handlebars"
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
Everything is running smooth before optimization, no problem occurs.
But, after optimization with r.js dependencies seem to break.
I'd like to use Almond js in production, so here's my build file:
({
baseUrl: ".",
paths: {
jquery: "components/jquery/jquery",
underscore: "components/underscore/underscore",
handlebars: "components/handlebars/handlebars",
backbone: "components/backbone/backbone",
text: "components/text/text"
},
// we use almond minimal amd module loader
name: "components/almond/almond",
// the application entry point
include: ['app/init'],
// we need to teel almond to require app/init
insertRequire: ['app/init'],
out: "main.js",
cjsTranslate: true,
wrap: true,
optimize: "none"
})
Now, when I run the optimized javascript in browser, all I get are error messages, saying me that jQuery and Handlebars are undefined (neither Backbone.$ is, of course).
A simple workaround was to force jQuery loading, and assigning it to Backbone, like this:
var $ = require('jQuery')
var Backbone = require('Backbone')
Backbone.$ = $
But it sounds very silly and redundant to me.
I feel like I'm doing something wrong but cannot figure out what.
After optimization Handlebars fail to load as dependency too.
If I force its loading (as I did with jQuery), I get an error message during the build process, saying me that the module fs (a npm package) cannot be found.
I googled but found only this topic on Google groups (https://groups.google.com/forum/?fromgroups=#!topic/requirejs/lYwXS-3qjXg) that seems to be related to my problem, even if proposed solutions are not working at all.
I think you should add the Shim's config in your build file too.
I'm working on my first javascript based web application and wanted to leverage a few different frameworks that I've been looking into but I'm having a lot of trouble getting all my different libraries loaded properly. I am trying to use Backbone and Underscore as well as the javascript included with Twitter Bootstrap (which I'm using for my CSS/HTML scaffolding). This is my butchered attempt at loading all of the scripts but I'm still getting firebug errors coming out of of require.js
As per the suggested answers I have edited my setup. In my index.html:
<script data-main="../scripts/main.js" src="../scripts/require.js"></script>
And in main.js:
require.config({
// Require is defined in /scripts, so just the remaining path (and no ext needed)
'paths': {
"bootstrap": "scripts/bootstrap",
"jquery": "scripts/jquery",
"underscore": "scripts/underscore",
"backbone": "scripts/backbone"
},
'shim':
{
backbone: {
'deps': ['jquery', 'underscore'],
'exports': 'Backbone'
},
underscore: {
'exports': '_'
}
}
});
require([
'jquery',
'bootstrap',
'underscore',
'backbone'
],
function(bootstrap, $, _, Backbone){
Person = Backbone.Model.extend({
initialize: function () {
alert("Welcome to this world");
}
});
var person = new Person;
});
But I am still getting script errors from require.js that points to this link
http://requirejs.org/docs/errors.html#scripterror
From a glance it looks like it's the setup of RequireJS, take a look at this: https://github.com/jcreamer898/RequireJS-Backbone-Starter
You don't need to define your scripts in the body, those should be loaded through Require, so something like:
Your main index.html:
<script src="path/to/require.js" data-main="scripts/app">
Then the data-main reference would point to something like /scripts/app.js with the following:
require.config({
// Require is defined in /scripts, so just the remaining path (and no ext needed)
'paths': {
"bootstrap": "libraries/bootstrap"
"jquery": "libraries/jquery",
"underscore": "libraries/underscore-min",
"backbone": "libraries/backbone-min"
},
'shim':
{
backbone: {
'deps': ['jquery', 'underscore'],
'exports': 'Backbone'
},
underscore: {
'exports': '_'
}
}
});
require([
'bootstrap',
'jquery',
'underscore',
'backbone'
],
function(bootstrap, $, _, Backbone){
// Start your application here...
});
With RequireJS the only library you should include in the <script /> tags is require.js. In addition you need to specify a "main" javascript file, which should be loaded by RequireJS:
<script data-main="scripts/main.js" src="scripts/require.js"></script>
The main file should then load other libraries:
requirejs(['jquery','backbone'], function ($,Backbone) {
//...
});
I suggest you read through the RequireJS API documentation and follow the examples.
Nobody has made the point that maybe you are starting with so many components (each with its concepts to learn) to be your first time Javascript project. I would try to explore each of the libraries separately before in really simple projects, have some experience with them and when you have a clear picture of what they do (docs don't always give it) you can start combining them all.
Possibly not the answer you were looking for, but it's my experience who's talking here. Good luck!
I am trying to modularize my Backbone app through Requirejs, but I cannot seem to get Requirejs to include Backbone. Here is my main.js that gets included from the index page:
require.config({
baseUrl: '/static/js/',
paths: {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
text: 'libs/require/text',
},
});
require(['/static/js/views/app.js'], function(AppView) {
var appView = new AppView;
});
Here is my app.js that gets included from the above file:
define([
'jquery',
'underscore',
'backbone',
], function($, _, Backbone) {
console.log($);
console.log(_);
console.log("inside of the app js file");
var AppView = Backbone.View.extend({
initialize: function() {
console.log("inside of appview initialize");
},
});
});
The following information gets printed out in my Google Chrome console:
function (a,b){return new e.fn.init(a,b,h)}
app.js:7undefined
app.js:8inside of the app js file
app.js:9Uncaught TypeError: Cannot read property 'View' of undefined
The definition for $ works, but the definitions for _ and Backbone do not work. They come up as undefined. Any idea why this is happening?
I recommend you use the version of requireJS that has jQuery bundled. It will save you much setup pain. You can read the details here: http://requirejs.org/docs/jquery.html and download the files here: https://github.com/jrburke/require-jquery
In their own words:
With RequireJS, scripts can load in a different order than the order they are specified. This can cause problems for jQuery plugins that assume jQuery is already loaded. Using the combined RequireJS + jQUery file makes sure jQuery is in the page before any jQuery plugins load.
This should take care of loading jQuery properly with requireJS:
<script data-main="js/main" src="js/require-jquery.js"></script>
Main.js
A couple of notes here:
No need to re-define the path to jquery since that's already taken care of
You still have to indicate jquery as a required module
(I had to update the paths to have them work in my system)
Code:
require.config({
baseUrl: 'js/',
paths: {
underscore: 'libs/underscore-min',
backbone: 'libs/backbone-min',
},
});
require(['jquery', 'app'], function($, AppView) {
console.log("done w/ requires");
console.log($)
console.log(AppView)
var appView = new AppView;
});
app.js
A couple notes:
You can only retrieve the JS files after loading them in the callback if they have been defined as modules. So function($, _, Backbone) will fail for you.
You must return your object so that it can be used in the main.js callback (return AppView)
Code:
define(
[
'jquery',
'underscore',
'backbone',
],
function() {
console.log($);
console.log(_);
console.log(Backbone);
console.log("inside of the app js file");
return AppView = Backbone.View.extend({
initialize: function() {
console.log("inside of appview initialize");
},
});
});
Console
With that code in place, this is the console output:
function ( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
} [app.js:8]
function (a){return new m(a)} [app.js:9]
Object [app.js:10]
inside of the app js file [app.js:11]
done w/ requires main.js:21
function ( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
} [main.js:22]
function (){a.apply(this,arguments)} [main.js:23]
inside of appview initialize [app.js:15]
I would shy away from using forked versions of backbone and underscore. A "shim" configuration option has been added to requirejs to handle 3rd party libraries that don't natively support AMD. This makes updating to the latest versions of the libraries much easier.
http://requirejs.org/docs/api.html#config-shim
Here is an example:
require.config({
paths: {
jquery: "libs/jquery",
underscore: "libs/underscore",
backbone: "libs/backbone"
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
}
});
You may not have the correct reference backbone and _,may be this can help you:
Loading Backbone and Underscore using RequireJS
more:
http://requirejs.org/docs/api.html#config-shim
I'm trying to load Backbone and Underscore (as well as jQuery) with RequireJS. With the latest versions of Backbone and Underscore, it seems kind of tricky. For one, Underscore automatically registers itself as a module, but Backbone assumes Underscore is available globally. I should also note that Backbone doesn't seem to register itself as a module which makes it kind of inconsistent with the other libs. This is the best main.js I could come up with that works:
require(
{
paths: {
'backbone': 'libs/backbone/backbone-require',
'templates': '../templates'
}
},
[
// jQuery registers itself as a module.
'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js',
// Underscore registers itself as a module.
'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js'
], function() {
// These nested require() calls are just due to how Backbone is built. Underscore basically says if require()
// is available then it will automatically register an "underscore" module, but it won't register underscore
// as a global "_". However, Backbone expects Underscore to be a global variable. To make this work, we require
// the Underscore module after it's been defined from within Underscore and set it as a global variable for
// Backbone's sake. Hopefully Backbone will soon be able to use the Underscore module directly instead of
// assuming it's global.
require(['underscore'], function(_) {
window._ = _;
});
require([
'order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js',
'order!app'
], function(a, app) {
app.initialize();
})
});
I should mention that, while it works, the optimizer chokes on it. I receive the following:
Tracing dependencies for: main
js: "/home/httpd/aahardy/requirejs/r.js", line 7619: exception from uncaught JavaScript throw: Error: Error: Error evaluating module "undefined" at location "/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js":
JavaException: java.io.FileNotFoundException: /home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js (No such file or directory)
fileName:/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js
lineNumber: undefined
http://requirejs.org/docs/errors.html#defineerror
In module tree:
main
Is there a better way of handling this? Thanks!
RequireJS 2.X now organically addresses non-AMD modules such as Backbone & Underscore much better, using the new shim configuration.
The shim configuration is simple to use: (1) one states the dependencies (deps), if any, (which may be from the paths configuration, or may be valid paths themselves). (2) (optionally) specify the global variable name from the file you're shimming, which should be exported to your module functions that require it. (If you don't specify the exports, then you'll need to just use the global, as nothing will get passed into your require/define functions.)
Here is a simple example usage of shim to load Backbone. It also adds an export for underscore, even though it doesn't have any dependencies.
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
}
});
//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) { // or, you could use these deps in a separate module using define
});
Note: this simplified code assumes that jquery, backbone and underscore are in files named "jquery.js", "backbone.js" and "underscore.js" in the same directory as this "main" code (which becomes the baseURL for require). If this isn't the case, you'll need to use a paths config.
I personally think with the built-in shim functionality, the advantages of not using a forked version of Backbone & Underscore outweigh the benefits of using the AMD fork recommended in the other popular answer, but either way works.
Update: As of version 1.3.0 Underscore removed AMD (RequireJS) support.
You can use the amdjs/Backbone 0.9.1 and the amdjs/Underscore 1.3.1 fork with AMD support from James Burke (the maintainer of RequireJS).
More info about AMD support for Underscore and Backbone.
// main.js using RequireJS 1.0.7
require.config({
paths: {
'jquery': 'libs/jquery/1.7.1/jquery',
'underscore': 'libs/underscore/1.3.1-amdjs/underscore', // AMD support
'backbone': 'libs/backbone/0.9.1-amdjs/backbone', // AMD support
'templates': '../templates'
}
});
require([
'domReady', // optional, using RequireJS domReady plugin
'app'
], function(domReady, app){
domReady(function () {
app.initialize();
});
});
The modules are properly registered and there is no need for the order plugin:
// app.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
return {
initialize: function(){
// you can use $, _ or Backbone here
}
};
});
Underscore is actually optional, because Backbone now gets its dependencies on its own:
// app.js
define(['jquery', 'backbone'], function($, Backbone){
return {
initialize: function(){
// you can use $ and Backbone here with
// dependencies loaded i.e. Underscore
}
};
});
With some AMD sugar you could also write it like this:
define(function(require) {
var Backbone = require('backbone'),
$ = require('jquery');
return {
initialize: function(){
// you can use $ and Backbone here with
// dependencies loaded i.e. Underscore
}
};
});
Regarding the optimizer error: doublecheck your build configuration. I assume your path configuration is off. If you have a directory setup similar to the RequireJS Docs you can use:
// app.build.js
({
appDir: "../",
baseUrl: "js",
dir: "../../ui-build",
paths: {
'jquery': 'libs/jquery/1.7.1/jquery',
'underscore': 'libs/underscore/1.3.1-amdjs/underscore',
'backbone': 'libs/backbone/0.9.1-amdjs/backbone',
'templates': '../templates'
},
modules: [
{
name: "main"
}
]
})
For reference, as of version 1.1.1 (~Feb '13), Backbone also registers itself as an AMD module. It will work with requirejs without the need to use its shim config. (James Burke's amdjs fork also hasn't been updated since 1.1.0)
Good news, Underscore 1.6.0 now supports requirejs define !!!
versions below this require shims, or requiring underscore.js then blindly hoping that the "_" global variable hasn;t been smashed (which to be fair is a fair bet)
simply load it in by
requirejs.config({
paths: {
"underscore": "PATH/underscore-1.6.0.min",
}
});
I will write down directly, you can read the explaination on requirejs.org, you could use below code as a snippet for your everyday use; (p.s. i use yeoman) (since many things updated, im posting this as of Feb 2014.)
Make sure you included script in your index.html
<!-- build:js({app,.tmp}) scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->
Then, in main.js
require.config({
shim: {
'backbone': {
deps: ['../bower_components/underscore/underscore.js', 'jquery'],
exports: 'Backbone'
}
},
paths: {
jquery: '../bower_components/jquery/jquery',
backbone: '../bower_components/backbone/backbone'
}
});
require(['views/app'], function(AppView){
new AppView();
});
app.js
/**
* App View
*/
define(['backbone', 'router'], function(Backbone, MainRouter) {
var AppView = Backbone.View.extend({
el: 'body',
initialize: function() {
App.Router = new MainRouter();
Backbone.history.start();
}
});
return AppView;
});
I hope I was useful.!
require.config({
waitSeconds: 500,
paths: {
jquery: "libs/jquery/jquery",
jqueryCookie: "libs/jquery/jquery.cookie",
.....
},
shim: {
jqxcore: {
export: "$",
deps: ["jquery"]
},
jqxbuttons: {
export: "$",
deps: ["jquery", "jqxcore"]
}
............
}
});
require([
<i> // Load our app module and pass it to our definition function</i>
"app"
], function(App) {
// The "app" dependency is passed in as "App"
// Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
App.initialize();
});