debug optimized javascript with require.js r.js - requirejs

Without r.js optimizing all workes great with my require js modules.
But with optimized js files ...
r.js -o public/js/app.build.js
... where app.build.js is ...
({
appDir: "../",
baseUrl: "js",
dir: "../../appdirectory-build",
paths: {
jquery: "./jquery-1.9.1",
jade: "lib/requireJade"
},
modules: [
{
name: "main"
}
]
})
... and output without errors and warnings ...
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/css/bootstrap-theme.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/css/bootstrap.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/css/bootstrap.min.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/css/media.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/css/style.css
Optimizing (standard.keepLines) CSS file: /pathToProject/appdirectory-build/min/bundle/3c95026_global.css
Tracing dependencies for: main
Uglifying file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/js/bootstrap.js
Uglifying file: /pathToProject/appdirectory-build/bootstrap-3.2.0-dist/js/bootstrap.min.js
Uglifying file: /pathToProject/appdirectory-build/js/app.build.js
Uglifying file: /pathToProject/appdirectory-build/js/jquery-1.9.1.js
Uglifying file: /pathToProject/appdirectory-build/js/lib/bootstrapRequire.js
Uglifying file: /pathToProject/appdirectory-build/js/lib/requireJade.js
Uglifying file: /pathToProject/appdirectory-build/js/main.js
Uglifying file: /pathToProject/appdirectory-build/js/main_built.js
Uglifying file: /pathToProject/appdirectory-build/js/require.js
Uglifying file: /pathToProject/appdirectory-build/js/submain/load_digits.js
Uglifying file: /pathToProject/appdirectory-build/js/submain/load_map.js
Uglifying file: /pathToProject/appdirectory-build/js/submain/load_more_records.js
Uglifying file: /pathToProject/appdirectory-build/js/submain/load_more_records_event.js
Uglifying file: /pathToProject/appdirectory-build/js/submain/submit_number_chooser_form.js
Uglifying file: /pathToProject/appdirectory-build/js/yamapsapi2.js
Uglifying file: /pathToProject/appdirectory-build/js/yandex-map-show-group.js
Uglifying file: /pathToProject/appdirectory-build/js/yandex-map.js
bootstrap-3.2.0-dist/css/bootstrap-theme.css
----------------
bootstrap-3.2.0-dist/css/bootstrap-theme.css
bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
----------------
bootstrap-3.2.0-dist/css/bootstrap-theme.min.css
bootstrap-3.2.0-dist/css/bootstrap.css
----------------
bootstrap-3.2.0-dist/css/bootstrap.css
bootstrap-3.2.0-dist/css/bootstrap.min.css
----------------
bootstrap-3.2.0-dist/css/bootstrap.min.css
css/media.css
----------------
css/media.css
css/style.css
----------------
css/style.css
min/bundle/3c95026_global.css
----------------
min/bundle/3c95026_global.css
js/main.js
----------------
js/jquery-1.9.1.js
js/yamapsapi2.js
js/yandex-map.js
js/submain/load_map.js
js/lib/requireJade.js
jade!lib/jade/records
js/submain/load_more_records.js
js/submain/load_more_records_event.js
js/submain/submit_number_chooser_form.js
js/main.js
... I got errors in chrome console when page loaded...
Uncaught TypeError: undefined is not a function
(anonymous function) main.js:172
anonymous main.js:172
e.ajax.success main.js:172
l main.js:172
c.fireWith main.js:172
N main.js:172
r
... some functions don't work on my page
So it's ok I got line number where error occurs: 172. But the problem is that optimized main.js row number 172 got length 206490. It's hard to find error such way.
How to debug it and find place where error actually occurs?
Without any optimizing I don't have any error. With optimazing I got error and too poor output to debug this error.
I tried to use excludeShallow with suspected buggy file
r.js -o public/js/app.build.js excludeShallow=load_more_records
But error still occurs and output still the same.

To make main.js more debuggable I added optimize: "none" in config.
({
appDir: "../",
baseUrl: "js",
dir: "../../appdirectory-build",
paths: {
jquery: "./jquery-1.9.1",
jade: "lib/requireJade"
},
modules: [
{
name: "main"
}
],
optimize: "none"
})
This option restricts to write all js in one line. Then I saw the actual line where error occurs. And to fix error add ...
pragmasOnSave: {
excludeJade : true
}
... to app.build.js as written here.
And error was fixed. Final app.build.js:
({
appDir: "../",
baseUrl: "js",
dir: "../../appdirectory-build",
paths: {
jquery: "./jquery-1.9.1",
jade: "lib/requireJade"
},
modules: [
{
name: "main"
}
],
// optimize: "none",
pragmasOnSave: {
excludeJade : true
}
})

Related

Should requirejs be included in the main built file when using the requirejs bundles option

I'm running into an issue when using the require bundles option. If the main built file has requirejs inside of it everything works fine until I try to load a file from a different bundle. The bundled file is retrieved but then throws an "define is undefined" error. The only way I have been able to get the bundle to load is to make sure requirejs is not in the main-built file or the pm.js and then to load requirejs with a script tag and use the data-main attribute, but this doesn't seem right.
So something like this initially works when requirejs is included in main-built.js (site loads fine), but I get the "define is undefined" error when pm.js bundle loads
<script type="text/javascript" src="~/dist/main-built.js"></script>
requirejs.config({
bundles: {
'pm': ['pm/dashboard', 'text!pm/dashboard.html']
}
});
This is how I ended up getting it to work, but doesn't seem right.
<script type="text/javascript" src="~/scripts/require.js" data-main="dist/main-debug")"></script>
This durandal task creates the main-built file
durandal: {
main: {
src: ["app/**/*.*", "scripts/durandal/**/*.*", "!app/mockup/**/*.*", "!app/performancemanagement/**/*.*"],
options: {
//name: "scripts/require",
name: "",
baseUrl: requireConfig.baseUrl,
paths: mixIn({}, requireConfig.paths, { "require": "scripts/require.js" }),
exclude: ["jquery", "knockout", "toastr", "moment", "underscore", "amplify"],
optimize: "none",
out: "dist/main-debug.js"
}
},
},
This task builds the pm.js bundle
requirejs: {
compile: {
options: {
include: generateFileList("app/pm", "**/*.*", false, false),
//exclude: ["jquery", "knockout", "toastr", "moment", "underscore", "amplify", "preferenceconstants", "constants", "config", "utility/koutilities", "scripts/logger", "base/viewmodel"]
// .concat(generateFileList("scripts/durandal", "**/*.js", false))
// .concat(generateFileList("app/dataservice", "**/*.js", false))
// .concat(generateFileList("app/model", "**/*.js", false))
// .concat(generateFileList("app/reports", "**/*.js", false)),
baseUrl: "app/",
name: "",
paths: mixIn({}, requireConfig.paths, { "almond": "scripts/almond-custom.js" }),
optimize: 'none',
inlineText: true,
pragmas: {
build: true
},
stubModules: ['text'],
out: "dist/pm.js"
}
}
}
The pm.js bundle gets downloaded and executed when anything in main-built requires it, right now its being done by the router in Durandal, but I'm pretty sure Durandal has nothing to do with the issue.
This appears suspicious in your main file build:
paths: mixIn({}, requireConfig.paths, { "require": "scripts/require.js" }),
I'm not sure what the mixIn bit does as this is not stock RequireJS code, but you seem to want to include RequireJS in the build under the name require, which is definitely wrong. The documentation says:
If you want to include require.js with the main.js source, you can use this kind of command:
node ../../r.js -o baseUrl=. paths.requireLib=../../require name=main include=requireLib out=main-built.js
Since "require" is a reserved dependency name, you create a "requireLib" dependency and map it to the require.js file.

RequireJS baseUrl and multiple optimized files

I've separated out my 3rd party libraries from my app code and grouped them all together into a vendor.js file for requirejs to pull in. In my build.js file, I'm using the modules syntax to optimize my main application, excluding the vendor scripts, and to optimize the vendor.js file. The only issue I'm having is when my compiled main module requests vendor, it's getting the baseUrl from the config file and so doesn't load the optimized vendor.js file. My build.js file looks like this:
({
baseUrl: "js",
dir: "build",
mainConfigFile: "js/main.js",
removeCombined: true,
findNestedDependencies: true,
skipDirOptimize: true,
inlineText: true,
useStrict: true,
wrap: true,
keepBuildDir: false,
optimize: "uglify2",
modules: [
{
name: "vendor"
},
{
name: "main",
exclude: ["vendor"]
}
]
})
And my main.js file looks like this:
requirejs.config({
baseUrl: "js",
paths: {
jquery: 'vendor/jquery/jquery-2.1.3.min',
bootstrap: 'vendor/bootstrap/bootstrap.min',
handlebars: 'vendor/handlebars/handlebars-v2.0.0',
backbone: 'vendor/backbone/backbone-min',
underscore: 'vendor/lodash/lodash.underscore',
marionette: 'vendor/marionette/backbone.marionette.min',
models: 'common/models',
collections: 'common/collections'
}
});
define(['module', 'vendor'], function(module) {
var configPath = "config/config." + module.config().env;
require([configPath, 'app', 'jquery'], function(config, Application, $) {
$(function() {
// Kick off the app
Application.start(config);
});
});
});
All development is done in the js folder, and my build.js file is outside that folder. The optimized files end up in build, a sibling to js, but when I include my main file like this:
<script data-main="build/main" src="js/vendor/require/require.max.js"></script>
It ends up loading js/vendor.js for that define() call. What am I missing here? How can I tell the optimized main file to load build/vendor.js instead, yet allow the unoptimized version to still load js/vendor.js?
Ok, I figured this out. It was simple, really, just a case of too much configuration. When you load your script using data-main, the baseUrl is set relative to that file. So, if I specified js/main, the baseUrl would be js. But, since I explicitly specified baseUrl in the config block of main.js, that gets overridden, both in development and production. By removing baseUrl: "js" from main.js, everything works as expected. The development build loads everything relative to js and the production build loads everything (vendor.js) relative to build when I change data-main to build/main. Hope this helps somebody else someday.
requirejs.config({
paths: {
jquery: 'vendor/jquery/jquery-2.1.3.min',
...
}
});
// 'vendor' is loaded relative to whatever directory main.js is in
define(['module', 'vendor'], function(module) {
...
});

Requirejs optimized file is not executed

I am seriously missing some vital element on how to use the r.js optimiser. This is probably a trivial answer for many, but I can for the life of me not figure out the problem.
I've set up my environment using a grunt task to build an optimised file. The optimised file is built and dependencies seems to resolve correctly, but the code in my mainfile is never executed.
I've created a minimal environment to help you help me where there is pretty much only the Gruntfile, the mainfile and some dependencies (jquery, almond).
My project structure is:
require_this/
│
├──Gruntfile.coffee
│
└──src/
│
├──index.html
│
├──bower_components/(jquery,almond,requirejs)
│
└──app/
│
└──main.js
Gruntfile:
module.exports = (grunt) ->
'use strict'
grunt.initConfig
pkg: grunt.file.readJSON 'package.json'
settings:
distDirectory: 'dist'
srcDirectory: 'src'
tempDirectory: '.temp'
allFile: 'main.js'
clean:
working: ['<%= settings.tempDirectory %>', '<%= settings.distDirectory %>']
finished: ['<%= settings.tempDirectory %>']
copy:
app:
files: [
cwd: '<%= settings.srcDirectory %>'
src: '**'
dest: '<%= settings.tempDirectory %>'
expand: true
]
requirejs:
scripts:
options:
baseUrl: '<%= settings.tempDirectory %>'
mainConfigFile: '<%= settings.tempDirectory %>/app/main.js'
optimize: 'none'
logLevel: 0
findNestedDependencies: true
name: 'main'
include: ['requireLib']
paths:
'main': 'app/main'
'requireLib': 'bower_components/almond/almond'
out: '<%= settings.distDirectory %>/<%= settings.allFile %>'
processhtml:
your_target:
files:
'dist/index.html': '.temp/index.html'
grunt.loadNpmTasks 'grunt-processhtml'
grunt.loadNpmTasks 'grunt-contrib-clean'
grunt.loadNpmTasks 'grunt-contrib-copy'
grunt.loadNpmTasks 'grunt-contrib-requirejs'
grunt.registerTask 'build', [
'clean:working'
'copy:app'
'requirejs'
'processhtml'
]
index.html:
<!DOCTYPE html>
<head>
<!-- build:js main.js -->
<!-- The line below will be changed to <script src="main.js"></script> after processhtml -->
<script src="bower_components/requirejs/require.js" data-main="app/main.js"></script>
<!-- /build -->
</head>
<body>
</body>
main.js
require.config({
baseUrl: './',
paths: {
'jquery': 'bower_components/jquery/dist/jquery.min'
}
});
define([
'jquery',
], function ($) {
console.log('changing html');
$('body').append('<div>Hello World</div>');
});
After completing the build task, my dist directory will contain index.html and main.js file.
The dist/main.js file will look like:
/*almond stuff*/
/*jquery stuff*/
require.config({
baseUrl: './',
paths: {
'jquery': 'bower_components/jquery/dist/jquery.min'
}
});
define('main',[
'jquery',
], function ($) {
console.log('changing html');
$('body').append('<div>Hello World</div>');
});
Using a static fileserver against the uncompressed files works as expected. When using the build files, nothing is logged and nothing is added to the html even though the optimised file is loaded.
I suspect the answer is similar to Why is my RequireJS ignoring the code in my optimized main.js?, (some module name mismatch?) but I did not understand this well enough to fix my own problem.
Help is greatly appreciated!
The optimized version simply defines module main but it is never executed because it is never required. I'm not sure why is main executed in the non-optimized version.
The main.js could have rather looked like:
require.config({
baseUrl: './',
paths: {
'jquery': 'bower_components/jquery/dist/jquery.min'
}
});
// use require instead of define here
require([
'jquery',
], function ($) {
console.log('changing html');
$('body').append('<div>Hello World</div>');
});
the difference is that instead of defining a module this code requires jquery and passes it to the anonymous function, which is executed right away. It doesn't look like your app actually relied on that code being available as a module (the function doesn't return anything), so this change should be sufficient.

RequireJS Optimizer throws ReferenceError: text is not defined

I have been using r.js to attempt to minify a fairly large project and I'm having trouble with the text plugin. I am using node.js and a build file that goes as follows:
Build File
({
name: '../main',
baseUrl: '../../js/app',
appDir: "./app",
dir: 'build',
paths: {
jquery: '../lib/jquery/jquery-1.10.2.min',
underscore: '../lib/underscore/underscore-min',
backbone: '../lib/backbone/backbone-min',
text: '../lib/require/text',
picker: '../lib/pickadate/picker',
pickerDate: '../lib/pickadate/picker.date',
pickerLegacy: '../lib/pickadate/legacy'
},
mainConfigFile : '../js/main.js'
})
Main Config File
requirejs.config({
baseUrl: 'js/app',
paths: {
jquery: '../lib/jquery/jquery-1.10.2.min',
underscore: '../lib/underscore/underscore-min',
backbone: '../lib/backbone/backbone-min',
text: '../lib/require/text',
picker: '../lib/pickadate/picker',
pickerDate: '../lib/pickadate/picker.date',
pickerLegacy: '../lib/pickadate/legacy'
},
shim: {
picker: ['jquery', 'pickerLegacy'],
pickerDate: {
deps: ['jquery', 'picker'],
exports: 'DatePicker'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
text : {
exports : 'text'
}
}
});
The references above are all verified correct. Whenever I try to compile this, I get the following output in the console:
node r.js -o app.build.js
Tracing dependencies for: ../main
ReferenceError: text is not defined
In module tree:
../main
app
router
views/pages/home
views/panel/allStoresPanel
text
Error: ReferenceError: text is not defined
In module tree:
../main
app
router
views/pages/home
views/panel/allStoresPanel
text
at eval (eval at <anonymous> (C:\code\Web\DixonsDashboard\deploy\_compiler\r.js:23699:64), <anonymous>:1:1)
I have no idea why it finds text to be undefined. The path to it is definitely correct - the site works like a charm in it's current expanded format. I have tried all of the options available to r.js and none of them seem to make any difference.
If I delete the file, I get a "No such file or directory" error, so it looks like it's finding the file OK.
Can anybody point out what I'm missing here?
You only configure shim for plugins that are not AMD compatible. The "text" plugin is already AMD compatible so running it through the shim mechanism actually breaks it.
I've just tested with a simplified version of your code: including text in the shim section does show "ReferenceError: text is not defined", removing it makes the build work fine.

RequireJS + Optimizer Include modules defined on the main file

I'm using Optimizer for the first time and I am running in some issues or questions.
I'm trying to optimize a main file and it puts, like I've expected, the jQuery, Backbone and Require modules ( and uses then across the whole navigation). But let's say I have a jQuery Plugin that I use on several views. I've tried to add it in the main file using the "include" option on the build.js file. It adds it ( e.g jQuery Slides ) but as I have a view with define("jquery-slides") ( again, an example ) the browser loads the file of the plugin again. Even if it is on the main built file.
Is this suppose to happen? Can I fix this?
Thanks.
Here is some code. Hope it helps =)
build.js
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
name: "main-site",
include: ['libs/requirejs/require', jquery-slides'],
insertRequire: ['main-site'],
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
}
}
main-site.js
require.config({
baseUrl: "/javascripts/",
paths: {
'jquery': 'libs/jquery/jquery',
'underscore': 'libs/underscore/underscore',
'bootstrap': 'libs/bootstrap/bootstrap.min',
'datepicker': 'libs/bootstrap/plugins/bootstrap-datepicker',
'backbone': 'libs/backbone/backbone.max',
'backbone-paginator': 'libs/backbone/plugins/backbone.paginator',
'backbone-validation': 'libs/backbone/plugins/backbone.validation',
'text': 'libs/requirejs/text',
'templates': '/templates/site',
'views': 'views/site',
'jquery-cookie': 'libs/jquery/plugins/jquery.cookie',
'jquery-raty': 'libs/jquery/plugins/jquery.raty.min',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
shim: {
'backbone-paginator': ['backbone'],
'bootstrap': ['jquery'],
'datepicker': ['bootstrap'],
'jquery-cookies': ['jquery'],
'jquery-raty': ['jquery'],
'jquery-slides': ['jquery'],
'backbone-validation': ['backbone']
}
});
require([
'app-site'
], function(App) {
$(function(){
App.initialize();
});
});
Instead of using include I recommend you to declare the modules you want to build. In this way requirejs will package the module and all its dependencies in the optimized bundle.
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
modules : [
{
name : 'main-site',
}
]
}
Further considerations:
If you have jquery-slides included as a dependency in any of your modules define(['jquery-slides'], function() {... } you don't need to use the include directive since all the dependencies of that module will be included in the optimized file
See the documentation of the modules property in this link
https://github.com/jrburke/r.js/blob/master/build/example.build.js#L330
Use the property mainConfigFile to avoid duplications https://github.com/jrburke/r.js/blob/master/build/example.build.js#L35
Good luck and I hope this helps you

Resources