Require.js and r.js include all dependencies even of submodules - javascript

I'm using require.js for the first time and all is working pretty for the moment. However, I started wanting to make a build. The idea is to create one file with ALL my js and templates. However, every time I use r.js it just includes the dependencies of my main module.
here is my app.build.js:
({
appDir: "public/javascripts",
baseUrl: ".",
dir: "build",
paths: {
"hbs": "lib/hbs",
"jquery": "lib/jquery",
"Handlebars": "lib/Handlebars",
"Backbone": "lib/backbone",
"underscore": "lib/underscore",
"bootstrap": "lib/bootstrap.min.js"
},
modules: [{name: "main"}],
shim: {
"bootstrap": {
deps: ["jquery"],
exports: "$.fn.popover"
},
underscore: {
exports: '_'
},
'Handlebars': {
exports: 'Handlebars'
},
Backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
}})
the beginning of main.js:
require.config({
paths: {
"hbs": "lib/hbs",
"Handlebars": "lib/Handlebars",
"Backbone": "lib/backbone",
"underscore": "lib/underscore",
"jquery": "lib/jquery",
"bootstrap": "lib/bootstrap.min.js"
},
hbs: {
disableI18n: true
},
shim: {
"bootstrap": {
deps: ["jquery"],
exports: "$.fn.popover"
},
underscore: {
exports: '_'
},
'Handlebars': {
exports: 'Handlebars'
},
Backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
}
});
require(['jquery', 'Backbone', 'videos'], function($, Backbone, Videos) { // Whatever });
In this case the final file created in my build 'main.js' only contains: jquery, underscore, backbone and videos. How can I make sure it also includes the dependencies of the module videos namely: the template 'hbs!template/videos/show'. How can I also make sure that bootstrap.min.js is also added even though it's not required anywhere?
Finally should I remove the require.config as it will define paths that are not supposed to be anymore as all the modules are in the final file?

To have the optimizer include all the nested dependencies, include this option in your build file or command line:
{
findNestedDependencies: true
}
This makes it work as you'd expect, and you won't have to include all your dependencies in your main file. It's kind of a secret ... I never saw this in the docs but I read it on a random blog somewhere.

In you app.build.js include link to your main config file and you can remove specified modules, this should include all dependencies used by main module.
({
...
mainConfigFile: 'main.js',
...
})
You may also skip paths and shim, since that is already specified in main. Bellow is sample config that I'm using in one of my projects and works like a charm:
({
name: 'main',
baseUrl: '../',
// optimize: 'none',
optimize: 'uglify2',
exclude: ['jquery'],
paths: {
requireLib: 'require'
},
mainConfigFile: '../main.js',
out: '../main.min.js',
// A function that if defined will be called for every file read in the
// build that is done to trace JS dependencies.
// Remove references to console.log(...)
onBuildRead: function (moduleName, path, contents) {
return contents;
// return contents.replace(/console.log(.*);/g, '');
}
})

Related

Requirejs Optimizer not compiling

I have been using requirejs and am having trouble getting the optimization tool to work. All I want to do is optimize my javascript files into one script file with all my dependencies included.
All my file are in the one js/ folder and I have a sub folder vendors/
I have a config file which looks like this(config.js):
requirejs.config({
baseUrl: ".",
out: "main-built.js",
deps: ["main"],
paths: {
jquery: "vendor/jquery", // v.1.10.2
bootstrap: "vendor/bootstrap",
ajaxform: "vendor/ajaxform",
skrollr: "vendor/skrollr",
jqueryform:"vendor/jqueryform"
},
shim: {
bootstrap: {
deps: ["jquery"],
exports: "bootstrap",
},
ajaxform: {
deps: ["jquery"],
exports: "ajaxform",
},
jqueryform: {
deps: ["jquery"],
exports: "jqueryform",
}
}
});
And I have an main javascript file (main.js) which looks like this:
if (typeof jQuery === 'function') {
define('jquery', function () { return jQuery; });
}
define(["jquery","bootstrap", "ajaxform","skrollr"],
function($, bootstrap, ajaxform, skrollr) {
//have other code here
});
I also created a build file:
({
baseUrl: ".",
paths: {
jquery: "vendor/jquery", // v.1.10.2
bootstrap: "vendor/bootstrap",
ajaxform: "vendor/ajaxform",
skrollr: "vendor/skrollr",
jqueryform:"vendor/jqueryform"
},
shim: {
bootstrap: {
deps: ["jquery"],
exports: "bootstrap",
},
ajaxform: {
deps: ["jquery"],
exports: "ajaxform",
},
jqueryform: {
deps: ["jquery"],
exports: "jqueryform",
}
},
name: "main",
out: "main-built.js"
})
All the build file does is compress the main.js file itself and doesn't include all needed files.
I've been trying to get this working on and off for weeks and can't seem to get it right so any help would be REALLY appreciated.
Thanks
Try adding a modules entry to your build file with your main module, as in:
modules: [
{ name: 'main' }
]
You can see all the options for the build file here: https://github.com/requirejs/r.js/blob/master/build/example.build.js

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'}]
});
//
});
//

RequireJS multipage r.js

I have a quite large app built with RequireJS and I'm trying optimise the modules with r.js.
But no matter what I do, I always get the same annoying error.
me: ~/WORK/LAB/require_r_js/js
→ r.js -o build.js
Optimizing (standard.keepLines.keepWhitespace) CSS file: /<path_to_my_js_folder>/js/dist/vendor/tinyscrollbar/tinyscrollbar.css
Tracing dependencies for: utils/Vendor
Error: ENOENT, no such file or directory
'/<path_to_my_js_folder>/js/dist/TweenLite.js'
In module tree:
utils/Vendor
cssplugin
It looks like my path cssplugin is been ignored, here is my build.js file:
{
mainConfigFile : "core/commom.js",
appDir: '.',
baseUrl: ".",
removeCombined: true,
findNestedDependencies: true,
dir: "./dist",
paths: {
tweenlite: "vendor/greensock/TweenLite.min",
cssplugin: "vendor/greensock/plugins/CSSPlugin.min",
easepack: "vendor/greensock/easing/EasePack.min",
jquery: "vendor/jquery/jquery-1.11.2.min",
signals: "vendor/signals/signals",
underscore: "vendor/underscore/underscore-min",
retina: "vendor/retinajs/retina-1.1.0",
tinyscrollbar: "vendor/tinyscrollbar/jquery.tinyscrollbar.min",
async: 'vendor/millermedeiros/requirejs-plugins/async',
simpleWeather: 'vendor/simpleWeather/jquery.simpleWeather.min'
},
shim: {
underscore: {
exports: "_"
},
jquery: {
exports: "jQuery"
},
simpleWeather: {
exports: "simpleWeather",
deps: ["jquery"]
}
},
modules: [
{ name: "utils/Vendor" },
{
name: "core/Main",
exclude: ['utils/Vendor']
},
{
name: "controllers/MapsHome"
},
{
name: "controllers/SuperHome"
},
{
name: "controllers/Register"
},
{
name: "controllers/hotel/HotelHome"
}
]
}
Well.. I know it looks a lot of information, but this is my commom.js file (the RequireJS config):
(function() {
requirejs.config({
baseUrl: "../",
waitSeconds: 120,
paths: {
tweenlite: "vendor/greensock/TweenLite.min",
cssplugin: "vendor/greensock/plugins/CSSPlugin.min",
easepack: "vendor/greensock/easing/EasePack.min",
jquery: "vendor/jquery/jquery-1.11.2.min",
jmask: "vendor/igorescobar/jquery-mask-plugin.min",
signals: "vendor/signals/signals",
underscore: "vendor/underscore/underscore-min",
retina: "vendor/retinajs/retina-1.1.0",
tinyscrollbar: "vendor/tinyscrollbar/jquery.tinyscrollbar.min",
async: 'vendor/millermedeiros/requirejs-plugins/async',
simpleWeather: 'vendor/simpleWeather/jquery.simpleWeather.min'
},
shim: {
underscore: {
exports: "_"
},
jquery: {
exports: "jQuery"
},
simpleWeather: {
exports: "simpleWeather",
deps: ["jquery"]
},
facebook: {
exports: 'FB'
}
}
});
}).call(this);
The files are organized in this structure:
Well, in my website the scripts are loaded as this:
<script type="text/javascript">
require([globalServerConf.requireJSConfURL], function() {
require(['core/Main'], function(Main) {
var m = new Main();
// The name of the Page Controller is set by a PHP Variable:
m.init("{{$jsController}}");
});
});
</script>
So, a global JS object (built by a PHP script) has the URL to the requirejs.config object. When commom.js is loaded, RequireJS asks for core/Main.js file. When core/Main is loaded, it will ask first for the utils/Vendor module. This module loads all third part scripts (like jQuery, TweenLite, CSSPlugin, etc etc). Only when these files are loaded, Main.js asks for the page controller file (which makes use of many other files as well).
So, I am trying to build with r.js all these modules:
All third part scripts: utils/Vendor
Main script: core/Main
All other main pages controllers:
controllers/MapsHome, controllers/SuperHome, controllers/Register, controllers/hotel/HotelHome
Every time I run r.js, tweelite or cssplugin makes that error and the optimization is killed.

Why I have to use 'include' again in grunt-requirejs to optimize into a single js file?

I'm trying to use grunt-requirejs to optimize my requirejs project into a single production js file. However, I'm not sure if my Gruntfile.js is correct because I have to specify which model to include during the optimization again, which seems wrong to me as I specify mainConfigFile already. I thought it's going to read everything from my requirejs file. I asked this because I have a lot of modules and I don't want to DRY.
Here's my Gruntfile.js
requirejs : {
compile : {
options: {
almond: true,
baseUrl : 'src/Web/Scripts',
mainConfigFile : 'src/Web/Scripts/main-new.js',
out: 'src/Web/Scripts/out.js',
optimize: 'uglify2',
include: ['main-new',
'app/app.js',
'app/viewmodels/home/home.mobile.js',
'zepto',
'hammer',
'zepto-hammer',
'zepto-dragswipe',
'knockout',
'knockout-validation',
'knockout-postbox',
'knockout-mapping',
'knockout-notification',
'q',
'underscore'
]
}
}
},
And this is my main-new.js file
requirejs.config({
baseUrl: '/m/Scripts',
paths: {
'jquery': 'vendors/jquery/jquery-1.10.2',
'jquery-cookie': 'vendors/jquery/jquery.cookie-1.4.1',
'zepto': 'vendors/zepto/zepto',
'hammer': 'vendors/hammer/hammer',
'zepto-hammer': 'vendors/zepto/zepto.hammer',
'zepto-dragswipe': 'vendors/zepto/zepto.dragswipe',
'knockout': 'vendors/knockout/knockout-3.1.0',
'knockout-validation': 'vendors/knockout/knockout.validation',
'knockout-postbox': 'vendors/knockout/knockout-postbox',
'knockout-mapping': 'vendors/knockout/knockout.mapping',
'knockout-notification': 'vendors/knockout/knockout-notification-1.1.0',
'viewmodels': 'app/viewmodels',
'service': 'app/services',
'config': 'app/config',
'helpers': 'app/helpers',
'q': 'vendors/q/q-0.9.6',
'underscore': 'vendors/underscore/underscore-min'
},
shim: {
'knockout-validation': ['knockout'],
'knockout-mapping': ['knockout'],
'knockout-postbox': ['knockout'],
'knockout-notification': ['knockout'],
'jquery-cookie': ['jquery'],
'hammer': ['zepto'],
'zepto-hammer': ['zepto', 'hammer'],
'zepto-dragswipe': ['zepto', 'hammer'],
'zepto': {
exports: 'Zepto'
},
'underscore': {
exports: '_'
}
}
});
In include section you should put modules that is required dynamically like:
require(['path/' + moduleName], function() { ... })
Because r.js can't predict at build time what you will be requiring in runtime.
Everything else should be resolved by dependency arrays in your modules.

r.js not compiling shimmed scripts properly

I'm able to successfully compile my JS modules via Grunt's requirejs task, but I'm getting undefined with any shim scripts. Here is my config
requirejs.config({
"baseUrl": "../../../components/",
"paths": {
"less": "less.js/dist/less-1.3.3",
"datepicker": "jquery-ui/ui/jquery.ui.datepicker",
"jquery": "jquery/jquery",
"jqueryui": "jquery-ui/ui/jquery-ui",
"spectrum": "spectrum/spectrum",
"class": "class/class",
"underscore": "underscore-amd/underscore",
"d3": "d3/d3",
"nv": "nvd3/nv.d3",
"dataTables": "datatables/dataTables"
},
shim: {
less: {
exports: "less"
},
jqueryui: {
exports: "jqueryui"
},
spectrum: {
exports: "spectrum"
},
class:{
deps: [ 'jquery'],
exports: "class"
}
}
})
Here is my requirejs config from my Gruntfile:
requirejs: {
dist: {
options: {
mainConfigFile: 'src/scripts/main.js',
out: '<%= yeoman.dist %>/scripts/main.js',
paths:{
"main" : "../final/src/scripts/main"
},
include:['main'],
preserveLicenseComments: false,
useStrict: true,
wrap: true
}
}
}
Now when I run grunt requirejs:dist It compiles just fine, and does include my shimmed files. But whenever I try to run the compiled JS, access to any of my shimmed scripts are undefined.
Not sure what you mean by "access to any of my shimmed scripts are undefined". You need to ensure that shimmed scripts are included in correct order. Also you may try defining fake module for that script. In you build JS configuration add:
onBuildRead: function (moduleName, path, contents) {
if (moduleNam === 'spectrum'){
contents += '; define(' + moduleName + ', function(){ return window.spectrum; });';
}
return contents;
}
You need to understand, what exports does. After script is loaded it will look for that variable in a global namespace. I don't think there is 'jqueryui' namespace. So it will always be undefined, because it has to load after jQuery and it just extends jQuery, so module can not return anything useful.
I hope that helps.

Categories