Require.js + Backbone optimization - javascript

Good afternoon,
I'm trying to optimize a source code based on Require.js and Backbone using r.js but I'm getting the following error during the compilation :
Tracing dependencies for: main
Cannot optimize network URL, skipping: empty:.js
TypeError: Cannot read property 'normalize' of undefined
In module tree:
main
app
router
views/main_panel/event_details
helpers/template_manager
My template_manager module does not try to access any 'normalize' property so I don't really understand what is that supposed to mean.
Here's the entry point to my application as well as the require.js configuration.
require.config({
paths: {
order: 'libs/requirejs-plugins/order',
text: 'libs/requirejs-plugins/text',
jQuery: 'libs/jquery/jquery',
Underscore: 'libs/underscore/underscore',
Backbone: 'libs/backbone/backbone',
templates: '../templates',
Sync: 'helpers/sync'
}
});
require([
'app',
'event_manager',
'order!https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js',
'order!libs/underscore/underscore-min',
'order!libs/backbone/backbone-min',
'helpers/objects_extension',
'helpers/date_extension',
'helpers/assets'
], function(App){
App.initialize();
});
The application itself more or less follows what's in this tutorial.
My app.build.js file is as follow
({
appDir: "../",
baseUrl: "js",
dir: "../app-build",
modules: [
{
name: "main"
}
],
paths: {
order: 'empty:',
text: 'empty:',
jQuery: 'empty:',
Underscore: 'empty:',
Backbone: 'empty:',
templates: '../templates',
Sync: 'helpers/sync'
}
})
Thank you for your help.

James Burke says:
The text plugin needs be loaded by the loader for it to process text! depenencies. Loader plugins are executed as part of a build to resolve their resources.
So it should be enough to remove the text: "empty:" from the paths config, and just leave the excludes: in so it is not included in the final build result. This assumes you have text.js available locally to be read by the optimizer.
https://github.com/jrburke/r.js/issues/221

Related

RequireJS bundles fail in optimizer - "modules share the same URL"

tl;dr
RequireJS optimizer doesn't like me defining bundle definitions on a module, but also does not find the modules if I don't define the bundles.
long version
I am getting the following error when trying to use the requirejs optimizer:
Error: Module loading did not complete for: scripts/simulation.bundle, app_mini, testservice
The following modules share the same URL. This could be a misconfiguration if that URL only has one anonymous module in it:
.../web/dist/scripts/app.bundle.js: app_mini, testservice
I am actually using grunt-contrib-requirejs to optimize my js scripts for production. It was all working fine before adding the simulator.bundle
I have 3 bundles:
app.bundle (main bundle)
simulation.bundle
vendor.bundle
This is the modules option of the requirejs grunt tasks
[{
name: 'scripts/vendor.bundle',
exclude: [],
override: {
paths: {
angular: 'bower/angular/angular',
jquery: 'bower/jquery/dist/jquery',
ngRoute: "bower/angular-route/angular-route"
},
shim: {
angular: {
exports: 'angular',
deps: ['jquery'] // make jquery dependency - angular will replace jquery lite with full jquery
},
bundles: {
'scripts/app.bundle': ['app_mini', 'testservice'],
},
}
}
},
{
name: 'scripts/simulation.bundle',
exclude: [],
override: {
paths: {},
shim: {},
bundles: {
'scripts/vendor.bundle': ['angular', 'jquery'],
'scripts/app.bundle': ['app_mini', 'testservice']
}
}
},
{
name: 'scripts/app.bundle',
exclude: ['scripts/vendor.bundle'],
override: {
paths: {
app_mini: 'scripts/app.mini',
testservice: 'scripts/features/test.service'
},
shim: {},
bundles: {
'scripts/vendor.bundle': ['angular', 'jquery']
}
}
}
]
The bundles in simulation.bundle seem to be the problem. However, if I remove them, the files cannot be found:
>> Error: ENOENT: no such file or directory, open
>> '...\web\dist\app_mini.js'
>> In module tree:
>> scripts/simulation.bundle
The simulation.bundle is just a dummy module, loading angular and app_mini:
define(['app_mini', 'angular'], function(app_mini, angular) {
// nothing here
}
So either way, the optimizer cannot process the dependencies. How do I have to configure it to make it work?
Alright, once again I am posting the answer to my own question, and I hope some other people will benefit from my mistakes ;)
So what I found out is:
Bundle config is only for requireJS and not for the optimizer!
The bundles I defined in the config are leading to the error of modules sharing the same url.
The right way to do it, is to define ALL the paths for ALL the modules, and to specifically exclude the modules by name that should not be included in a module.
For example, app_mini should go into the app.bundle, but because it is required in the simulation.bundle it would get included there, because excluding app.bundle is not yet possible (it has not been optimized at this point), we need to exclude app_mini directly.
So a working config would look like this: (not tested)
paths: {
angular: 'bower/angular/angular',
jquery: 'bower/jquery/dist/jquery',
ngRoute: "bower/angular-route/angular-route"
app_mini: 'scripts/app.mini',
testservice: 'scripts/features/test.service'
},
shim: {
angular: {
exports: 'angular',
deps: ['jquery'] // make jquery dependency - angular will replace jquery lite with full jquery
}
},
modules: [
{
name: 'scripts/vendor.bundle',
exclude: [],
},
{
name: 'scripts/simulation.bundle',
exclude: [`app_mini`],
},
{
name: 'scripts/app.bundle',
exclude: ['scripts/vendor.bundle'],
}
}]

RequireJS Optimizer - what does it actually do?

I was under the impression that the RequireJS Optimizer would look through the defined dependencies and gather up all of the referenced js files in an application and bundle them up into a single, large js file.
You'd then be able to reference that single file in your html script include.
But this doesn't seem to be the case. When I run this, I get a large file, but it includes the original main.js file that includes paths to files in a directory structure.
What is the point of that? Why does the new large file contain paths outside of itself if everything needed is contained within? It seems like the optimizer would rewrite the paths to point to "./" or something.
When I bundle up the entire app and reference that in the page, I'm getting errors about missing files that ARE included in the large js file:
Uncaught object require.js:70
GET http://localhost/ui/js/modules/mod_limeLight.js 404 (Not Found) require.js:729
Uncaught Error: Script error for: mod_limelight
http://requirejs.org/docs/errors.html#scripterror
build.js:
({
baseUrl: "./src/ui/scripts",
name: "main",
mainConfigFile : "src/ui/scripts/main.js",
out: "dist/ui/scripts/main-built.js"
})
main.js
'use strict';
require.config({
"paths": {
"jquery": "libs/jquery-1.11.0.min",
"twitter_bootstrap": "../bower_components/bootstrap/dist/js/bootstrap.min",
"respondjs": "../bower_components/respond/dest/respond.min",
"debouncejs": "libs/dw-debounce",
"carousel": "libs/jquery.carouFredSel-6.2.1-packed",
"swipe": "libs/jquery.touchSwipe.min",
"app": "app",
"OOo_config": 'libs/oo_conf_entry-ck', // Opinion Lab pop-up
//modules
"addthis": "//s7.addthis.com/js/300/addthis_widget",
"mod_addThis": "modules/mod_AddThis",
"limelight": "//assets.delvenetworks.com/player/embed",
"mod_limelight": "modules/mod_limeLight"
},
"shim": {
"twitter_bootstrap": ["jquery"],
"carousel": ["jquery"],
"swipe": ["jquery"],
"packeryjs": ["jquery"]
}
});
require([
"jquery",
"app",
"OOo_config",
"respondjs",
"mod_addThis",
"mod_limelight"
], function ($, app) {
app.init();
});
example module starts off like:
define([
"jquery", "debouncejs", "limelight"
],
function ($) {
'use strict';
var playerElement = ...
});
Then running:
node r.js -o build.js
What am I missing? Why is it trying to fetch files that are contained in that large js file?
Thanks,
Scott
It identifies the included modules using their usual paths, because that’s simple and unambiguous, and it works. The files aren’t fetched, of course.

Built RequireJS app won't load

So, I built my RequireJS app using grunt-require, which I believe uses r.js behind the scenes. However, upon running the app, I get this every time:
Uncaught Error: Module name "underscore" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded require-2.1.9.min.js:8
GET http://localhost:8080/resources/js/app/App.js 404 (Not Found) require-2.1.9.min.js:34
Uncaught Error: Script error for: app/App
http://requirejs.org/docs/errors.html#scripterror
My "main" script is in app/Main.js and looks like this:
require(['common'], function() {
'use strict';
require(['app/App'], function(app) {
app.start();
});
});
And then the build options for grunt-require:
requirejs: {
options: {
baseUrl: 'resources/js',
dir: 'resources/js/build',
main: 'app/Main',
out: null,
optimize: 'uglify2',
skipDirOptimize: true,
priority: ['common'],
preserveLicenseComments: false,
modules: [
{
name: 'common'
},{
name: 'app/Main',
exclude: ['common'],
include: ['app/App']
}
],
paths: { ... },
shim: { ... }
}
}
As you can see, I've included app/App in the build of app/Main.js.
It loads Main.js and common.js separately, as expected, but then it tries to load app/App.js separately. When I look in the built version of Main.js, I see that app/App.js has in fact been built in.
Any ideas why it's trying to load app/App.js separately?
It seems, you forgot findNestedDependencies : true option in your build config and your nested require did not load. See its description.

Getting dependencies to load correctly in requirejs (autobahn and whenjs)

I have been stuck on this problem for the past few hours. I'm trying to get autobahnjs and whenjs to be loaded correctly by requirejs.
require.config({
paths: {
angular: '../bower_components/angular/angular',
angularBootstrap: '../bower_components/angular-bootstrap/ui-bootstrap',
bootstrap: '../bower_components/bootstrap/dist/js/bootstrap',
jquery: '../bower_components/jquery/jquery',
chosen: '../bower_components/chosen/chosen.jquery.min',
text: '../bower_components/requirejs-text/text',
autobahn: '../bower_components/autobahnjs/autobahn/autobahn'
},
packages: [
{ name: 'when', location: '../bower_components/when/', main: 'when' }
],
baseUrl: '/bundles/example/app/scripts/',
shim: {
angular : {
exports : 'angular'
},
angularBootstrap: {
deps: ['angular']
},
autobahn: {
deps: ['when']
}
},
priority: [
'angular'
]
});
require
( [
'angular',
'app',
'autobahn',
'angularBootstrap',
'jquery',
'bootstrap',
'chosen',
'controllers/event',
'services/notify'
], function(angular, app) {
// more code here
});
Autobahnjs has a dependency on whenjs. All the files are loaded (and in the correct order). but when is always undefined. I have absolutely no idea what I'm doing wrong. I've tried all sorts of ways to solve it. I also have a bower.json file if this helps anyone replicate the problem. Thanks in advance.
EDIT: Autobahnjs does not currently support AMD. Whenjs, however, does support it.
As you have noticed already, there is an issue for adding requirejs support to AutobahnJS. There is also more embedded stuff inside AutobahnJS bundled for "convenience", mainly parts from cryptojs.
The challenge simply is: how to best serve all users, not matter if and what module loader they use, and if they want convenience (bundled stuff) or prefer to have stuff separate (and manage/load that themselves).
I can't promise, but I try to address it with priority. However, for further discussion, I think the best place would be the GitHub issue.
This has now been implemented in v0.8.0

Requirejs, almond, backbone, handlebars

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.

Categories

Resources