I'm trying to optimize RequireJS using GruntJS, using the grunt-contrib-requirejs plugin.
The problem is my code works fine before optimizing it, and then after optimizing it, on the console it says Uncaught ReferenceError: define is not defined.
Here's the Gruntfile.js
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.initConfig({
requirejs: {
compile : {
options : {
name : 'main',
baseUrl : ".",
mainConfigFile : "./main.js",
out : "./optimized.js",
preserveLicenseComments: false
}
}
}
})
grunt.registerTask('default', 'requirejs');
}
Adding the require.js file as an "include" option should work.
requirejs: {
compile : {
options : {
name : 'main',
baseUrl : ".",
mainConfigFile : "./main.js",
out : "./optimized.js",
preserveLicenseComments: false,
include: ['path/to/require.js']
}
}
}
As define is a requireJs function it seems you miss to load requireJs or any other AMD loader. If you dont need to load any other AMD module then your complied once, you can use a light weight loader shim like almond.
As pointed out before the requirejs-script is missing.
This is the way the official requirejs-page suggests you do it (ripped from my gruntfile):
requirejs: {
compile: {
options: {
baseUrl: "src/js",
mainConfigFile: 'src/js/require.config.js',
paths: {
requireLib: "vendor/require/require"
},
include: "requireLib",
name: "require.config",
out: "dist/js/bundle.js"
}
}
},
Observe the options paths and include, those are vital for the require to be defined.
Just point the requireLib-option to your require.js-file.
See the official answer here: http://requirejs.org/docs/optimization.html#onejs
It seems that the grunt-contrib-requirejs doesn't compile requirejs in by default. You could use concat to re-add requirejs back in.
concat : {
dist : {
src : ['./optimized.js', 'path/to/requirejs.js'],
dest : './optimized.js'
},
}
grunt.loadNpmTasks('grunt-contrib-concat');
Related
After trying out many things interact.js isn't working with require.js
Here is interact.js file I am using http://code.interactjs.io/interact-1.2.4.js
Since third party library which doesn't 'Define' a module needs to be specified in shim configuration, I tried that:
requirejs.config({
baseUrl: 'scripts',
paths: {
'interact': 'include/interact.min'
},
shim: {
'interact': ['include/jquery.min']
}
});
I also tried in this way:
requirejs.config({
baseUrl: 'scripts',
paths: {
'interact': 'include/interact.min'
},
shim: {
'interact': {
exports: 'interact'
}
}
});
Then trying to use interact function in separate js file like this:
define( ['interact'] , function (int) {
return {
interact('#renderCanvas').dropzone({});
}
You did not look correctly, because it does check whether an AMD loader is present, and calls define:
// AMD
else if (typeof define === 'function' && define.amd) {
define('interact', function() {
return interact;
});
}
I found that by following the link you gave and searching for define.amd.
So no shim.
Ok, there is a bunch of questions with similar titles, but none of them helped me solve my problem so here it is.
I am trying to use Angular with RequireJS; I am getting the error message Uncaught TypeError: Cannot read property 'module' of undefined which is referring to the angular object within the angular-routes.js file. This suggests to me that requireJS is trying to load angular-routes before angular has loaded. I was under the impression that this wouldn't happen because I have set 'angular-route' as dependant on 'angular' within the shim. Can anyone spot what I am doing wrong here?
// Setup requireJS
require.config({
baseUrl : "scripts",
packages : [
{ "name":"angular", "location":"../bower_components/angular", "main":"angular"},
{ "name":"angular-route", "location":"../bower_components/angular-route", "main":"angular-route"},
{ "name":"angular-animate", "location":"../bower_components/angular-animate", "main":"angular-animate"},
{ "name":"angular-storage", "location":"../bower_components/angular-storage/dist", "main":"angular-storage"},
{ "name":"jquery", "location":"../bower_components/jquery/dist", "main":"jquery"}
],
shim:{
'angular' : { exports : 'angular', deps : ['jquery'] },
'angular-route' : { deps : ['angular'] },
'angular-animate' : { deps : ['angular'] },
'angular-storage' : { deps : ['angular'] },
}
});
// Load app files
function loadApp($, app)
{
angular.element(document).ready(function(){
angular.bootstrap(document, ['mealPlannerApp']);
});
}
requirejs(['app'], loadApp);
My app.js file is as follows
(function() {
// Declare AMD module with dependencies
define(['angular', 'angular-route', 'routes'],
function(config)
{
var app = angular.module('mealPlannerApp', ['ngRoute', 'ngAnimate', 'ngAnimate']);
app.config(config);
});
}());
Packages are great for your internal packages, I haven’t tried to load main AngularJS files as them.
Please read http://jonathancreamer.com/require-js-packages-for-building-large-scale-angular-applications/ for some better clarification and examples than change config section to something like this. Major change is replacement of packages with paths
Please also consider to change variables to camelCase style
require.config({
paths: {
angular: '../bower_components/angular/angular',
'angular-route': '../bower_components/angular-route/angular-route',
'angular-animate': '../bower_components/angular-route/angular-animate',
'angular-storage': '../bower_components/angular-route/angular-storage'
},
shim: {
'angular' : { exports : 'angular', deps : ['jquery'] },
'angular-route' : { deps : ['angular'] },
'angular-animate' : { deps : ['angular'] },
'angular-storage' : { deps : ['angular'] },
},
priority: [
"angular"
]
});
I am trying to use waypoints with zepto and RequireJS.
My requireJS configuration looks like this:
requirejs : {
options : {
baseUrl : '<%= config.app.js %>',
paths : {
almond : '../node_modules/almond/almond',
zepto : '../node_modules/zepto/zepto.min',
'progressbar' : '../node_modules/progressbar.js/dist/progressbar',
waypoints : '../node_modules/waypoints/lib/zepto.waypoints'
},
shim : {
zepto : {
exports : '$'
}
},
mainConfigFile: '<%= config.app.js %>/common.js',
include : ['common'],
name : 'almond',
out : 'dist/js/<%= pkg.name %>.js',
insertRequire: ['common'],
wrap: true
},
dist : {
options : {
optimize: 'uglify2'
}
},
dev : {
options : {
optimize: 'none'
}
}
},
Furthermore, my common.js file is as follows:
define(['zepto', 'waypoints'], function($) {
var waypoint = $('#experience').waypoint({
handler: function(direction) {}
});
});
But when the page is loaded, I get the following error:
Uncaught TypeError: Cannot read property 'apply' of undefined
The error, comes from this line on the waypoints plugin library:
return this.$element[method].apply(this.$element, args)
When I debug the code, I can see that function ZeptoAdapter(element) is called twice, once with $('#experience') as element, and once with window. The second time is when it fails, since this.$element is undefined. Am I doing something wrong? What's the proper way of including a zepto plugin?
Thanks,
Waypoints doesn't do anything to export for CommonJS or AMD. I believe you need to shim it as well:
shim : {
zepto : {
exports : '$'
},
waypoints: {
deps: ['zepto'],
exports: 'Waypoint'
}
}
This solve my problem
shim : {
jqueryWaypoints:{
deps: ['jquery'],
exports: 'jqueryWaypoints'
}
}
I'm using RequireJS (version 2.1.14) and would like to concatenate my JavaScript files into one single app-built.js.
I've created a little node module which reads my app.js, extracts the project paths and gets executed once I run node build in the js directory of my application.
The node module (build.js):
var fs = require('fs'),
path = require('path'),
directory = __dirname + path.sep,
requirejs = require(directory + 'vendor/r.js');
fs.readFile(directory + 'app.js', 'utf8', function(err, data) {
if (err) {
console.log('Error: ' + err);
return
} else {
data = data.replace(/'/g, '"').replace(/\s+/g, '');
var paths = data.substr(data.indexOf('{'), data.indexOf('}')),
paths = paths.substr(0, paths.indexOf('}') + 1),
paths = JSON.parse(paths);
createAppBuilt(paths);
}
});
function createAppBuilt(paths) {
var config = {
baseUrl: __dirname,
paths: paths,
name: 'app',
out: 'app-built.js',
preserveLicenseComments: false,
findNestedDependencies: true,
removeCombined: true
};
requirejs.optimize(config, function(buildResponse) {
var contents = fs.readFileSync(config.out, 'utf8');
console.log('Created app-built.js');
}, function(err) {
console.log('Error: ' + err);
return;
});
}
app.js:
var paths = {
'jquery': 'vendor/jquery-1.11.0.min',
// other paths
};
// Set language, necessary for validtaion plugin -> validation.js
if (Modernizr.localstorage) {
localStorage.getItem('language') || localStorage.setItem('language', navigator.language || navigator.userLanguage);
}
requirejs.config({
paths: paths,
shim: {
touchswipe: {
deps: ['jquery']
},
icheck: {
deps: ['jquery']
},
validate: {
deps: ['jquery']
},
mask: {
deps: ['jquery']
},
chosenImage: {
deps: ['jquery', 'chosen']
},
cookie: {
deps: ['jquery']
}
}
});
require(['globals', 'jquery', 'underscore'], function() {
var initial = ['main'];
if (!Modernizr.localstorage) {
initial.push('cookie');
}
require(initial, function(Main) {
$(function() {
if (!Modernizr.localstorage) {
$.cookie.json = true;
}
Main.init();
});
});
});
The app-built.js gets generated but when I include it in my index.php all the other modules get loaded as well. How can I prevent the loading of all modules and only load the app-built.js?
I recommend you look into http://webpack.github.io/
or http://browserify.org/ as these solve this problem for you.
They allow you to use require much as before, yet the code is compiled/concatenated into a single file.
Webpack allows for a bit more flexibility in loading different chunks of code for different parts of your site, but Browserify is the most well-known so far.
There may be a cost in switching over to these, as I don't think that they're 100% compatible requirejs, however they bring great advantages.
Here's someone's journey from RequireJS to Browserify with some Pros and Cons.
Separate modules into different files, e.g. app-built.js, user-built.js. Then load script when it's needed.
Here's a demo: http://plnkr.co/edit/s6hUOEHjRbDhtGxaagdR?p=preview .
When page loaded, requirejs only loads global.js. After clicking the Change Color button, requirejs starts to load colorfy.js and random-color.js, which required by colorfy.js.
I am not sure about the exact details, but, yet if you don't have an exports option, r.js doesn't define a named module for you, that causes to actually load the script.
I assume you have jquery plugins there so add this extra exports option:
shim: {
touchswipe: {
deps: ['jquery'],
exports: 'jQuery.fn.touchswipe'
},
This should force r.js to build a named module for touchswipe:
define("touchswipe", (function (global) {
return function () {
var ret, fn;
return ret || global.jQuery.fn.touchswipe;
};
}(this)));
Note that, exports option might not build this named module, in that case your best bet is to include this manually.
Again I am not sure about why and how this happens, It must be a bug in requirejs, it's unlikely there is a tweak for this.
Changing the r.js optimizer (to uglify2) solved the problem for me:
var config = {
baseUrl: __dirname,
paths: paths,
name: 'app',
out: 'app-built.js',
findNestedDependencies: true,
preserveLicenseComments: false,
removeCombined: true,
optimize: 'uglify2'
};
I'm running on severals issues when I'm trying to run the node RequireJS on my project.
This is my folder structure :
-root
-/src
-App.coffee
-/static
-/vendor
-/plugin
-r.js
-coffee-script.js
-/lib
-jquery.js
-main.js
-build.js
This is my build.js file :
({
appDir : './',
baseUrl : './static/js/',
dir : '../public',
optimize : 'uglify',
exclude : ['coffee-script'],
stubModules : ['cs'],
paths: {
// Libraries
'modernizr' : 'vendor/modernizr',
'jquery' : ['//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min', 'vendor/jquery'],
'jqueryui' : 'vendor/jquery-ui',
'backbone' : 'vendor/backbone',
'underscore' : 'vendor/underscore',
// Plugins
'plugin' : 'plugin/plugin',
// RequireJS
'cs' : 'plugin/cs',
'coffee-script' : 'plugin/coffee-script'
},
shim: {
'jqueryui' : ['jquery'],
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
},
modules: [{
name: "main"
}]
})
And finally this is my main.js file :
require({
baseUrl : '../../src/',
paths: {
cs: '../../cs',
'coffee-script': '../../coffee-script'
}
}, ['cs!App']);
I'm getting always error related to incorrect path setting and I can't figured out where I'm wrong.
Thanks !
The solution below worked in my case. It's a common issue with non-amd modules imported with shim or wrapped manually (for instance this one, with custom paths).
Try avoiding relative paths and use absolute 1 paths instead.
A dependency called from an aliased module will use its current location to find the required module.
require.config(
{
locale: window.GIS.i18n.locale,
deps: ['cs!modules/main'],
paths: {
'i18n' : 'i18n',
'underscore' : 'libs/underscore',
'cs' : 'libs/cs', // there's no '../something/else/libs/cs'
'CoffeeScript' : 'libs/coffeescript', // ibidem.
'text' : 'libs/text',
// ... other amd module aliases go here...
},
shim:{
// ...
}
});
define(['cs!modules/main'], function(){});
1 Of course, these are not absolute paths per se, but they are relative to the root of your module tree.