Getting blank page using RequireJS and Grunt - javascript

I'm going a bit crazy here. I'm trying to use Grunt to go through a large RequireJS-based project and combine and minify the results during the deployment process. Here is my grunt process (using grunt-contrib-requirejs):
requirejs: {
compile: {
options: {
baseUrl: "public/js",
mainConfigFile: "public/js/config.js",
name: 'config',
out: "public/js/optimized/script.min.js",
preserveLicenseComments: false
}
}
}
Initially, I was taking the outputted script and placing it in the HTML -- but this lead to the 'define is undefined' error that means that RequireJS wasn't evoked. So instead, I'm putting in the HTML like this:
<script data-main="js/optimized/script.min" src="js/vendor/require.js"></script>
However, now I'm only getting a blank page.
The closest thing I can find out there that sounds like this is here, but's not being super helpful right now. For reference, I was using this as a starting point of my project -- however, when I run it, everything seems to be working for them but I can't find the differences.
Here is my config.js file:
require.config({
//Define the base url where our javascript files live
baseUrl: "js",
//Increase the timeout time so if the server is insanely slow the client won't burst
waitSeconds: 200,
//Set up paths to our libraries and plugins
paths: {
'jquery': 'vendor/jquery-2.0.3.min',
'underscore': 'vendor/underscore.min',
'backbone': 'vendor/backbone.min',
'marionette': 'vendor/backbone.marionette',
'mustache': 'vendor/mustache.min',
'bootstrap': 'vendor/bootstrap.min',
'bootbox': 'vendor/bootbox.min',
'jquery-ui': 'vendor/jquery-ui-1.10.2',
'app-ajax': '../conf/app-ajax',
'common': 'common',
'moment': 'vendor/moment.min'
},
//Set up shims for non-AMD style libaries
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'marionette': {
deps: ['backbone', 'underscore', 'jquery'],
exports: 'Marionette'
},
'mustache': {
exports: 'mustache'
},
'bootstrap': {
deps: ['jquery']
},
'bootbox': {
deps: ['jquery', 'bootstrap'],
exports: 'bootbox'
},
'jquery-ui': {
deps: ['jquery']
},
'jquery-layout': {
deps: ['jquery', 'jquery-ui']
}
}
});
//Initalize the App right after setting up the configuration
define([
'jquery',
'backbone',
'marionette',
'common',
'mustache',
'bootbox',
'controllers/GlobalController',
'routers/GlobalRouter'
],
function ($, Backbone, Marionette, Common, Mustache, bootbox) {
//Declare ECMAScript5 Strict Mode first and foremost
'use strict';
//Define the App Namespace before anything else
var App = Common.app_namespace || {};
//Create the Marionette Application
App.Application = new Marionette.Application();
//Add wrapper region, so we can easily swap all of our views in the controller in and out of this constant
App.Application.addRegions({
wrapper: '#wrapper'
});
// Set up Initalizer (this will run as soon as the app is started)
App.Application.addInitializer(function () {
//Reach into Marionette and switch out templating system to Mustache
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function (rawTemplate) {
return Mustache.compile(rawTemplate);
};
var globalController = new App.Controllers.GlobalController();
var globalRouter = new App.Routers.GlobalRouter({
controller: globalController
});
//Start Backbone History
Backbone.history.start();
});
//Start Application
App.Application.start();
}
);

Okay, so this is the crazy simple fix:
In the module that's declared after the require.config, use 'require' instead of 'define' when declaring the module.
If you use 'define', it added 'config' as a dependency of that module, which broke the whole thing. Craziness!

Related

requirejs include multiple extensions for jquery control

How do you load other extensions for a jquery control called 'fancytree' I'm trying to get fancytee to load or include the fancytree.table.js and other extensions that are needed - below is my config
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
'jquery-ui': {
exports: "$",
deps: ['jquery']
},
'fancytree': {
deps: ['jquery-ui']
},
'alertify': {
deps: ['jquery']
},
'fancytreetable': {
deps: ['jquery', 'fancytree']
}
},
paths: {
'jquery': '../lib/jquery/jquery',
'underscore': '../lib/underscore/underscore',
'backbone': '../lib/backbone/backbone',
'text': '../lib/text/text',
'jquery-ui': '../vendor/jquery-ui/jquery-ui',
'fancytree': [
'../vendor/fancytree/fancytree',
'../vendor/fancytree/fancytree.table'/* this extension here needs to be added but it's not included */
],
'alertify': '../vendor/alertify/alertify'
},
baseUrl: '/js/app',
});
Nikhil Mehta's comment points you in the right direction. Your paths value for fancytree is wrong. You use an array there when you want to provide fallback values for modules. If you give [A, B, C], for instance, if A fails to load, RequireJS tries B and if this fails, tries C. And if all fail, then that's a load failure.
Based on the configuration you show, you'd need:
fancytree: '../vendor/fancytree/fancytree',
fancytreetable: '../vendor/fancytree/fancytree.table'
You already have a shim that establishes that fancytreetable needs fancytree.
Note that unless you are using fairly old versions of Underscore and Backbone, you do not need to specify shim values for them. RequireJS is probably going to just ignore them but it may confuse people reading your code.
Here is how made it work, requirejs with jquery.fancytree-all and latest jquery-ui with AMD support, since working with individual extensions will require a lot of shimming.
onBuildWrite is optional but i prefer it this way
requirejs.config({
paths: {
'jquery': './js/vendor/jquery',
'jquery-ui': './js/vendor/jquery-ui',
'jquery.fancytree': './js/vendor/fancytree/jquery.fancytree-all'
},
shim: {
'jquery.fancytree': {
deps: ['jquery', 'jquery-ui/core', 'jquery-ui/effect', 'jquery-ui/effects/effect-blind', 'jquery-ui/widgets/draggable', 'jquery-ui/widgets/droppable'],
exports: 'jQuery.fn.fancytree'
}
},
onBuildWrite: function (moduleName, path, contents) {
'use strict';
if (moduleName === 'jquery.fancytree') {
contents = 'define( "jquery.fancytree", ["jquery", "jquery-ui/core", "jquery-ui/effect", "jquery-ui/effects/effect-blind", "jquery-ui/widgets/draggable", "jquery-ui/widgets/droppable"], function(jQuery) { ' + contents + '});';
}
return contents;
}
});
// usage
define([
'jquery',
'jquery.fancytree',
'css!./css/fancytree/skin-custom/ui.fancytree.css',
],
function($) {
'use strict';
//
$('#tree').fancytree({
checkbox: true,
source: [{title: 'Node 1'}, {title: 'Node 2',key: 'id2'}]
});
//
});
//

Separate scripts with RequireJS

I recently worked on a web app, and i wanted to separate it into modules.
I searched and found out that RequireJs is the best for this. I read the doc, and some tutorials about it and came up with this
requirejs.config({
baseUrl: "js/lib",
shim: {
'jquery-1.12.1.min': ['jquery-1.12.1.min'],
'materialize.min': ['materialize.min'],
'knockout-3.4.0': ['knockout-3.4.0'],
'pouchdb-5.3.0.min': ['pouchdb-5.3.0.min']
},
waitSeconds: 0,
paths: {
'jquery-1.12.1.min': 'jquery-1.12.1.min',
'materialize.min': 'materialize.min',
'knockout-3.4.0': 'knockout-3.4.0',
'pouchdb-5.3.0.min': 'pouchdb-5.3.0.min',
}
});
require(["jquery-1.12.1.min", "knockout-3.4.0", "materialize.min", "pouchdb-5.3.0.min"], function($, ko) { //My main functions and other stuff ... }
My index has the following:
<script data-main="js/main" src="js/lib/require.js"></script>
<script type="text/javascript" src="js/converter.js"></script>
But it seems that my Jquery, KO, materialize.css and pouchdb aren't loading as i see on my chrome dev tools in Network:
I also read about the shim config how to set up the dependences and i want them in that order. I don't really know what am i missing, any help would really be appreciated.
Folder structure is:
js:
lib:
->jquery-1.12.1.min.js
->knockout-3.4.0.js
->pouchdb-5.3.0.min.js
->materialize.min.js
->require.js
main.js
converter.js
Ok it seems require and materialze.css have a problem with hammer.js, what i recommend is you go and download Hammer.min.js and include it in your lib folder.
Then in your main.js add the following:
requirejs.config({
baseUrl: 'js/lib',
waitSeconds: 0,
paths: {
app: '../app',
jquery: 'jquery-1.12.1.min',
materialize: 'materialize.min',
knockout: 'knockout-3.4.0',
pouchdb: 'pouchdb-5.3.0.min',
hammer: 'hammer.min'
},
shim: {
hammer: {
deps: ['jquery']
},
pouchdb: {
deps: ['jquery']
},
knockout: {
deps: ['jquery'],
exports: 'ko'
},
materialize: {
deps: ['jquery', 'hammer'],
},
jquery: {
exports: '$'
}
}
});
You include you hammer and also the dependency for jquery on it. And i see that you didn't put the PouchDb object in the function:
define(["jquery", "knockout", "pouchdb", "materialize" ], function($, ko, PouchDB) {...
Hope this helps
Using path, requirejs replace module id prefixes (name in config) with the corresponding value.
Using shim you can export a global variable and configure the dependencies ( materialize depends jquery so you have to import jQuery before importing materialize.js )
requirejs.config({
baseUrl: "js/lib",
waitSeconds: 0,
paths: {
'jquery': 'jquery-1.12.1.min',
'materialize': 'materialize.min',
'knockout': 'knockout-3.4.0',
'pouchdb': 'pouchdb-5.3.0.min',
'hammer': 'hammer.min',
},
shim: {
pouchdb: {
deps: ['jquery']
},
knockout: {
exports: 'ko'
},
materialize: {
deps: ['jquery', 'hammer']
},
jquery: {
exports: '$'
}
}
});
require(["jquery", "knockout", "materialize", "pouchdb"], function ($, ko) {
console.log($);
console.log(ko);
});

How to include SignalR with gulp build process?

When I run my Durandal app with main.js (not minified), it loads signalr.core and signalr.hubs correctly, however, after building with gulp, it fails to load signalr.hubs.
Here is my RequireJS config:
requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'knockout': '../Scripts/knockout-3.2.0',
'knockout.validation': '../Scripts/knockout.validation',
'bootstrap': '../Scripts/bootstrap',
'jquery': '../Scripts/jquery-2.1.3',
'jquery.utilities': '../Scripts/jquery.utilities',
'toastr': '../Scripts/toastr',
'offline': '../Scripts/offline',
'signalr.core': '../Scripts/jquery.signalR-2.2.0.min',
"signalr.hubs": '../signalr/hubs?'
},
shim: {
'jquery.utilities': {
deps: ['jquery']
},
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
},
'knockout.validation': {
deps: ['knockout']
},
'signalr.core': {
deps: ['jquery'],
exports: '$.connection'
},
'signalr.hubs': {
deps: ['signalr.core'],
}
}
});
define('jquery', function () { return jQuery; });
define('knockout', ko);
define('moment', moment);
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'durandal/composition', 'global/session', 'knockout', 'knockout.validation', 'signalr.core', 'signalr.hubs'], function (system, app, viewLocator, composition, session) {
});
Here is my gulpfile:
var gulp = require('gulp');
var durandal = require('gulp-durandal');
gulp.task('durandal', function () {
durandal({
baseDir: 'app', //same as default, so not really required.
main: 'main.js', //same as default, so not really required.
output: 'main-built.js', //same as default, so not really required.
almond: true,
minify: true
})
.pipe(gulp.dest('app'));
});
I don't fully understand the minification process, but I do know that SignalR is not AMD compliant so that might be the issue. Also, the hub endpoint produces dynamic JavaScript so it would make sense that it can't be included in the build.
What am I missing to get signalr.hubs to play nicely with main-built.js? Should I load SignalR separately from RequireJS?
I guess there are ways to make the dynamic endpoint work, but as you already thought that's a bit of a different beast to treat. I would suggest you either use the proxyless approach (which removes the need of the dynamic endpoint, but you'll have to tweak your calls and event handlers a bit), or you add a step to your build process to serialize the dynamic endpoint through the signar.exe utility, as explained here.

The jquery.fileupload plugin causes require.js to randomly fail imports

I'm using require.js and have a page with an from that used jquery.fileupload. After introducing the plugin I now see some files fail to be imported before the define call back is executed. This causes random errors where the libraries can't find their dependencies. It's as though require.js is moving on before all the dependencies can be resolved.
I've followed these instructions:
https://github.com/blueimp/jQuery-File-Upload/wiki/How-to-use-jQuery-File-Upload-with-RequireJS
But beyond that it's a very vanilla install. I'm using the minified versions of libraries where possible. Any insight is welcome.
here's the main.js:
(function () {
'use strict';
require.config({
baseUrl: '/js',
waitSeconds: 800,
paths: {
jquery: ['//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min',
'lib/jquery/jquery-2.0.3.min'],
'jquery.fileupload': 'lib/jquery.fileupload/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jquery.fileupload/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jquery.fileupload/jquery.fileupload-image',
'jquery.fileupload-validate': 'lib/jquery.fileupload/jquery.fileupload-validate',
'jquery.fileupload-video': 'lib/jquery.fileupload/jquery.fileupload-video',
'jquery.fileupload-audio': 'lib/jquery.fileupload/jquery.fileupload-audio',
'jquery.fileupload-process': 'lib/jquery.fileupload/jquery.fileupload-process',
'jquery.ui.widget': 'lib/jquery.ui/jquery.ui.widget',
'jquery.iframe-transport': 'lib/jquery.iframe-transport/jquery.iframe-transport',
'load-image': 'lib/load-image/load-image.min',
'load-image-meta': 'lib/load-image/load-image-meta',
'load-image-exif': 'lib/load-image/load-image-exif',
'load-image-ios': 'lib/load-image/load-image-ios',
'canvas-to-blob': 'lib/canvas-to-blob/canvas-to-blob.min',
tmpl: 'lib/tmpl/tmpl.min',
bootstrap: 'lib/bootstrap/bootstrap',
bootstrapTab: 'lib/bootstrap/bootstrap-tab',
EventEmitter: 'lib/event_emitter/EventEmitter',
linkedin: ['//platform.linkedin.com/in.js?async=true',
'http://platform.linkedin.com/in.js?async=true'],
skinny: 'lib/skinny/skinny',
selectize: 'lib/selectize/selectize.min',
sifter: 'lib/sifter/sifter',
microplugin: 'lib/microplugin/microplugin.min'
},
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
}
}
});
require(['app'], function (App) {
App.initialize();
});
}());
And the from code:
define([], function () {
'use strict';
return function () {
require(['jquery', 'tmpl', 'load-image', 'canvas-to-blob',
'jquery.iframe-transport', 'jquery.fileupload-ui'], function ($) {
$('#product').fileupload({
url: '/products/create'
});
});
};
});
The module gets called after the page has been loaded.
It's also worth noting that all files are downloaded successfully. No 404's, etc.
It turns out there is a flaw in the minified version of load-image.js that breaks how the dependencies load. I don't have exact proof as to why, it could be the smaller size causes a race condition, or it could be something weird in that particular file. What I do know is the minified version causes the random errors and the normal version does not (this is off master so I suppose I was taking a risk).
I raised a flag here
EDIT: it turns out the minified version of the plugin includes all the extensions which explains the odd dependency behavior.
The Answer from matt is the best solution in this case. Thanks a million, it save us a lot of time.
In requirejs.config, you have to add the load-image dependecies separatly - file by file.
For example:
require.config({
'jquery.ui.widget' : 'lib/jQuery-File-Upload-9.9.2/js/vendor/jquery.ui.widget',
'jquery.fileupload':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-image',
'jquery.fileupload-validate':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-validate',
'jquery.fileupload-audio':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-audio',
'jquery.fileupload-video':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-video',
'jquery.fileupload-process': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-process',
'jquery.fileupload-jquery-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-jquery-ui',
'jquery.iframe-transport': 'lib/jQuery-File-Upload-9.9.2/js/jquery.iframe-transport',
'load-image':'lib/load-image-1.10.0',
'load-image-meta':'lib/load-image-meta-1.10.0',
'load-image-ios':'lib/load-image-ios-1.10.0',
'load-image-exif':'lib/load-image-exif-1.10.0',
'canvas-to-blob':'lib/canvas-to-blob-2.0.5',
'tmpl':'lib/tmpl.2.4.1'
}
});
call in html site:
requirejs(['jquery',
'jquery.ui.widget',
'tmpl',
'load-image',
'jquery.iframe-transport',
'jquery.fileupload-ui'], function () {
$('#fileupload').fileupload({
url: 'photo-upload.html'
});
}
);
One possibility modify the shim:
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
},
'jquery.fileupload-ui':{
deps: ['jquery']
}
Another option downgrade jquery to 1.X (this is because the sample page is using jquery 1.X)

Unable to resolve _ in a Backbone & RequireJS app

I'm relatively new to Backbone and RequireJS, so please bear with me. I'm getting an error when I do the following in my collection: _.range(0,10). It's giving me this error:
Uncaught TypeError: Cannot call method 'range' of undefined
Somehow the "_" is not getting resolved when my Collection is loaded. Here's my collection below:
define([
'jquery',
'underscore',
'backbone',
'collections/feed',
'text!/static/templates/shared/display_item.html'
], function($, _, Backbone, FeedCollection, DisplayItem){
debugger; // Added this to test the value of _
var FeedView = Backbone.View.extend({
el: '#below-nav',
initialize: function () {
this.feedCollection = new FeedCollection();
},
feed_row: '<div class="feed-row row">',
feed_span8: '<div class="feed-column-wide span8">',
feed_span4: '<div class="feed-column span4">',
render: function () {
this.loadResults();
},
loadResults: function () {
var that = this;
// we are starting a new load of results so set isLoading to true
this.isLoading = true;
this.feedCollection.fetch({
success: function (articles) {
var display_items = [];
// This line below is the problem...._ is undefined
var index_list = _.range(0, articles.length, 3);
_.each(articles, function(article, index, list) {
if(_.contain(index_list, index)) {
var $feed_row = $(that.feed_row),
$feed_span8 = $(that.feed_span8),
$feed_span4 = $(that.feed_span4);
$feed_span8.append(_.template(DisplayItem, {article: articles[index]}));
$feed_span4.append(_.template(DisplayItem, {article: articles[index+1]}));
$feed_span4.append(_.template(DisplayItem, {article: articles[index+2]}));
$feed_row.append($feed_span8, $feed_span4);
$(that.el).append($feed_row);
}
});
}
});
}
});
return FeedView;
});
I added the debugger line so that I could test the values of all the arguments. Everything loaded fine, except for _. Could this be something wrong with my config.js file?
require.config({
// Set base url for paths to reference
baseUrl: 'static/js',
// Initialize the application with the main application file.
deps: ['main'],
paths: {
jquery: 'libs/jquery/jquery.min',
require: 'libs/require/require.min',
bootstrap: 'libs/bootstrap/bootstrap.min',
text: 'libs/plugins/text',
underscore: 'libs/underscore/underscore',
backbone: 'libs/backbone/backbone',
json: 'libs/json/json2',
base: 'libs/base/base'
},
shim: {
'backbone': {
// These script dependencies should be loaded first before loading
// backbone
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'bootstrap': {
deps: ['jquery'],
exports: 'Bootstrap'
}
}
})
Your help is greatly appreciated. My head is spinning as a result of this error.
Based off the project that I'm working on, you need a shim for underscore as well. Underscore isn't 'exported' per say, so use this instead:
shim: {
'backbone': {
// These script dependencies should be loaded first before loading
// backbone
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'bootstrap': {
deps: ['jquery'],
exports: 'Bootstrap'
},
'underscore': {
exports: '_'
}
}
Seems this might also be 'duplicate' question of Loading Backbone and Underscore using RequireJS - one or two of the answers down the list there is a mention of this setup.

Categories