Merge requireJS files with grunt - requirejs

I want to combine the js used in a simple requireJS solution.
This is my main.js
require.config({
paths: {
'jquery': 'jquery-2.0.3.min',
'dataTable': 'jquery.dataTables'
}
});
define(['jquery','dataTable'], function($) {
'use strict';
$(function () {
$('.tablesorter').dataTable();
});
});
And my gruntFile.js
module.exports = function(grunt) {
grunt.initConfig({
requirejs: {
production: {
options: {
name: "main",
baseUrl: "",
mainConfigFile: "main.js",
out: "optimized.js"
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.registerTask('default', 'requirejs');
};
WHen I load optimized.js in the html like this
<script src="optimized.js"></script>
I get
ReferenceError: require is not defined

You must include require.js on the page before including optimized.js.
Like so:
<script src="/path/to/require.js"></script>
<script src="/path/to/optimized.js"></script>

I found out that requireJS only accepts 'main' as the data-main src
So instead of
<script data-main="optimized" src="require.js"></script>
I got
<script data-main="prod/main" src="require.js"></script>
And changed the grunt config to
requirejs: {
production: {
options: {
name: "main",
baseUrl: "",
mainConfigFile: "main.js",
out: "prod/main.js"
}
}
}

Looking at the comments in addition to the question, first I see that George Raith hit on one problem with your code: you needed to include require.js.
Then you said that $('.tablesorter').dataTable() is not executed. That's because you use define rather than require. Use this:
require(['jquery','dataTable'], function($) {
'use strict';
$(function () {
$('.tablesorter').dataTable();
});
});
A call to define only registers a module with RequireJS. It does not execute a module. So it is not surprising that $('.tablesorter').dataTable() would not execute. You have to use the form of require that takes a callback to do what you want to do.
As for including RequireJS with your project into a single file, you have to ask for it explicitly. The optimizer's documentation gives this example:
node ../../r.js -o baseUrl=. paths.requireLib=../../require name=main include=requireLib out=main-built.js
Your configuration (updated from the one in the question) would look something like this:
grunt.initConfig({
requirejs: {
production: {
options: {
name: "main",
baseUrl: "",
mainConfigFile: "main.js",
paths: {
requireLib: <path to require js>
},
out: "optimized.js",
include: "requireLib"
}
}
}
});
(I've not run this code, so lookout for typos.) You have to put the path to your require.js file for requireLib. We have to use requireLib as a module name because require is reserved. With this kind of configuration, you should be able to load only your optimized.js file.

Related

requireJs first steps - $ undefined

try to get familiar with require JS - but I don't understand what is wrong with this setup - can't call the $(document).foundation() because $ is undefined.
requirejs.config({
baseUrl: '/js',
paths: {
jQuery: 'script.php?file=jquery.min.js',
foundation: 'script.php?file=foundation.min.js'
}
});
require(['jQuery'], function($) {
require(['foundation'], function() {
$(document).foundation(); // $ undefined?
});
// ... more code with different require sections
});
Consider moving your logic into a separate file, for example app.js
Then, change the require(['jQuery'], function($) { ... call to something like requirejs(['app']).
In app.js you should define a module, something like:
define(['jQuery', 'foundation'], function($, foundation) {
$(document).foundation();
});

Requirejs do not add ".js" for modules using karma

I have simple test, that must work in webstorm using karma and requirejs.
The problem is that for some reason requirejs do not add ".js" for modules i was loading for tests. So it crashed trying to load "../ts/mamats/mama", while "../ts/mamats/mama.js" exists
Test (main.jasmine.js):
define(["require", "exports", "../ts/mamats/mama"], function(require, exports, mama) {
describe("first test", function () {
it("should be true", function () {
var object = new mama.block();
expect(object instanceof mama.block).toBe(true);
});
});
});
//# sourceMappingURL=main.jasmine.js.map
every thing works correctly when i replace "../ts/mamats/mama" with "../ts/mamats/mama.js"
sourceMappingURL here because javaScript file generated from typeScript source file, and because of that i cannot add ".js" for modules manually
Test starts with this entry point (main-test.js):
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return (/\.jasmine\.js$/).test(file);
});
requirejs.config({
baseUrl: '/base',
deps: tests,
callback: window.__karma__.start
});
Why requirejs don't add ".js" for modules here?
Karma conf file:
module.exports = function(config) {
config.set({
basePath: '../',
frameworks: ['jasmine', 'requirejs'],
files: [
'static-tests/main-test.js',
{ pattern: 'static/**/*', included: false },
{ pattern: 'static-tests/**/*', included: false }
],
exclude: [],
preprocessors: {},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['Chrome'],
singleRun: false
});
};
Here is an interesting read on how RequireJs handles this:
http://requirejs.org/docs/api.html#jsfiles
Reading that makes it seem like an issue with RequireJS, but there seems to be some debate on whether or not that is true. Regardless, this gist seems to solve the issue.
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return /\.spec\.js$/.test(file);
}).map(function(file){
return file.replace(/^\/base\/src\/js\/|\.js$/g,'');
});
require.config({
baseUrl: '/base/src/js'
});
require(tests, function(){
window.__karma__.start();
});
It looks like trouble in require.js
The problem is in next:
1. When in deps appear absolute path - requirejs stop add ".js" for any require call
2. When in deps appear file with extension, for some reason requirejs again stop add ".js" for modules
Other Solution here - to replace bathUrl and add it to requirejs conf do not help.
For me solution is next:
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return (/\-jasmine\.js$/).test(file);
}).map(function (file) {
return file.replace(/^\/|\.js$/g, '');
});
and
baseUrl: '',
for requirejs.conf
and i have no idea why requirejs still add "/base" for all url that are requested, but now all works fine

Proper way to share dependencies in Karma with RequireJS

I use Karma and jasmine for my unit tests. I have a main-test.js file to configure karma, and a main.js to configure my application.
main-test.js:
//
...
//
require.config({
baseUrl: '/base',
paths: {
jquery: 'components/jquery/dist/jquery', // this is copypaste
//another dependencies
},
//
...configuration
//
});
main.js
require.config({
paths: {
jquery: 'components/jquery/dist/jquery', // this is copypaste
//another dependencies
},
//
...configuration
//
});
What is the proper way to share paths between those two configurations?
We met the same problem with my team and ended up by requiring the main config into test-main.js:
// requiring global requireJS config
require(['/base/config/require.conf.js'], function() {
'use strict';
// first require.config overload: Karma specific
require.config({
baseUrl: '/base/src',
paths: {
'angularMocks': '../bower_components/angular-mocks/angular-mocks'
},
shim: {
'angularMocks': {
deps: ['angular']
}
}
});
require(['angularMocks'], function() {
var specFiles = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (/\/base\/src\/.*_test\.js$/.test(file)) {
specFiles.push(file);
}
}
}
// second overload to include specFiles and start Karma
require.config({
deps: specFiles,
callback: window.__karma__.start
});
});
});
Our starter app structure for projects using AngularJS + RequireJS is available here: angular-requirejs-ready.
I do not claim this is the proper way, only our way ;)

How to setup Gruntfile.js to watch for SASS (compass) and JS

I'm new to using gruntjs and nodejs. I wanted to know how can I setup the gruntfile so that it watches both the sass files and the js files compiles using watch.
This is what I have so far:
module.exports = function ( grunt ) {
"use strict";
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
compass: {
dist: {
options: {
config: 'config.rb',
watch: true
}
}
}
});
grunt.registerTask('default', []);
};
Any help will be much appreciated. Thank you!
Try grunt-contrib-watch with grunt-contrib-sass. They're both Grunt plugins specifically for this kind of thing:
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/global.css': 'scss/screen.scss'
}
}
},
watch: {
css: {
files: ['scss/*.scss'],
tasks: ['sass'],
options: {
spawn: false
}
}
},
The watch plugin configuration above will watch for changes in any .scss files, and will run the sass tasked (also defined above). You can even hook into livereload this way. You can also have multiple watches (the above only defines a css watch); creating a second watch to minify JS would be easy with grunt-contrib-uglify
I have an example you can look at that also concatenates JavaScript and does some minification with grunt-contrib-uglify. Here is the example.

Trying to use grunt-contrib-requirejs to minify all JS to one file

I have the following directory structure (relevant bits only):
app
- build
- script.js
- js
- lib
- require.js
- jquery-1.10.2.js
- app.js
- index.html
Gruntfile.js
Gruntfile.js contains the following:
module.exports = function (grunt) {
var gruntConfig = {
pkg: grunt.file.readJSON('package.json'),
requirejs: {
compile: {
options: {
name: 'app',
baseUrl: 'app/assets/js',
out: 'app/assets/build/script.js',
include: ['lib/require'],
uglify: {
// beautify: true,
defines: {
DEBUG: ['name', 'false']
}
},
paths: {
jquery: "lib/jquery-1.10.2"
}
}
}
},
};
grunt.initConfig(gruntConfig);
grunt.loadNpmTasks('grunt-contrib-requirejs');
};
app.js contains the following:
require(['jquery'], function ($) {
// Do stuff
});
How do I set it up so that it copies all the JavaScript needed into build/script.js, not just app.js and require.js when I tell it to (erroring when I try to use jQuery)? I also want to be able to add modules without adding them to my Gruntfile, just by adding them to script.js.
You can have a mainConfigFile defined and inside config file have paths to you lib code like this
Contents of gruntfile:
requirejs: {
compile: {
options: {
baseUrl: "app/js/",
mainConfigFile: app/config.js",
out: "build/script.js",
name: "config"
}
}
}
Contents of config file:
require.config({
paths: {
lib: "<path to>/js/lib",
jquery: "<path to>/js/lib/jquery-1.10.2.min",
.
and particular file required
.
}
Requirejs will add the contents of all path files to the optimized code.
Try adding this to your options object:
findNestedDependencies: true
This way grunt-contrib-requirejs (actually just requirejs) will find whatever dependencies are listed on your config file.
Hope it works for you.

Resources