Skip to content

Allow using a custom build of r.js #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* grunt-contrib-requirejs
* http://gruntjs.com/
*
* Copyright (c) 2016 Tyler Kellen, contributors
* Copyright (c) 2012-2016 Tyler Kellen, contributors
* Licensed under the MIT license.
*/

Expand Down Expand Up @@ -41,7 +41,8 @@ module.exports = function(grunt) {
options: {
baseUrl: 'test/fixtures',
name: 'project',
out: 'tmp/requirejs-template.js'
out: 'tmp/requirejs-template.js',
verbose: true
}
},
onOptimize: {
Expand All @@ -54,6 +55,44 @@ module.exports = function(grunt) {
done();
}
}
},
'custom-requirejs': {
options: {
requirejs: require('requirejs'),
baseUrl: 'test/fixtures',
name: 'project',
out: 'tmp/custom-requirejs.js'
}
},
'build-failure': {
options: {
baseUrl: 'test/failure',
name: 'project',
out: 'tmp/build-failure.js',
force: true
}
},
'done-failure': {
options: {
baseUrl: 'test/fixtures',
name: 'project',
out: 'tmp/done-failure.js',
done: function() {
throw new Error('in done');
},
force: true
}
},
'error-failure': {
options: {
baseUrl: 'test/failure',
name: 'project',
out: 'tmp/error-failure.js',
error: function() {
throw new Error('in error');
},
force: true
}
}
},

Expand Down
16 changes: 16 additions & 0 deletions docs/requirejs-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,19 @@ requirejs: {
}
}
```

#### Requirejs

```js
requirejs: {
compile: {
options: {
requirejs: require('@my/requirejs'),
baseUrl: 'path/to/base',
mainConfigFile: 'path/to/config.js',
include: [ 'src/main.js' ],
out: 'path/to/optimized.js'
}
}
}
```
21 changes: 20 additions & 1 deletion docs/requirejs-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,24 @@ For a full list of possible options, [see the r.js example build file](https://g

## done(done, build)

The done option is an optional hook to receive the r.js build output. The first argument is the grunt async callback that you are required to call if you provide the done hook. This informs grunt that the task is complete. The second parameter is the build output from r.js.
The `done` option is an optional hook to receive the `r.js` build output. The first argument is the grunt async callback that you are required to call if you provide the `done` hook. This informs grunt that the task is complete. The second parameter is the build output from `r.js`.

## error(done, error)

The `error` option is an optional hook to receive the `r.js` error. The first argument is the grunt async callback that you are required to call if you provide the `done` hook. This informs grunt that the task is complete. The second parameter is the error instance thrown from `r.js` in case of failure.

## requirejs

The `requirejs` option is an object exported from a module compatible with `r.js`. You can pass an alternative optimizer version to the task by this option. The module `requirejs` is used by `require('requirejs')` by default.

## logLevel

The `logLevel` option is a number to be passed to the `r.js` as the log level. The values can be 0 (tracing), 1 (information), 2 (warning) or 3 (error). The default if 2 (warning).

## verbose

The `verbose` option is a boolean to enable logging at the level 0 (tracing) if set to `true`. The default is `false`.

## force

The `force` option is a boolean, which if set to `true`, forces the grunt running and executing further tasks, although the current task failed. The default is `false`.
78 changes: 57 additions & 21 deletions tasks/requirejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,75 @@
* grunt-contrib-requirejs
* http://gruntjs.com/
*
* Copyright (c) 2016 Tyler Kellen, contributors
* Copyright (c) 2012-2016 Tyler Kellen, contributors
* Licensed under the MIT license.
*/

'use strict';

module.exports = function(grunt) {

var requirejs = require('requirejs');
var LOG_LEVEL_TRACE = 0, LOG_LEVEL_WARN = 2;
var force;

// TODO: extend this to send build log to grunt.log.ok / grunt.log.error
// by overriding the r.js logger (or submit issue to r.js to expand logging support)
requirejs.define('node/print', [], function() {
return function print(msg) {
if (msg.substring(0, 5) === 'Error') {
grunt.log.errorlns(msg);
grunt.fail.warn('RequireJS failed.');
} else {
grunt.log.oklns(msg);
}
};
});
function warning() {
/* c8 ignore next */
return force ? grunt.log.warn : grunt.fail.warn;
}

grunt.registerMultiTask('requirejs', 'Build a RequireJS project.', function() {
function fatal() {
/* c8 ignore next */
return force ? grunt.log.fatal : grunt.fail.fatal;
}

function initializeRequire(requirejs) {
if (!requirejs) {
requirejs = require('requirejs');
}

// TODO: extend this to send build log to grunt.log.ok / grunt.log.error
// by overriding the r.js logger (or submit issue to r.js to expand logging support)
requirejs.define('node/print', [], function() {
return function print(msg) {
if (msg.substring(0, 5) === 'Error') {
grunt.log.errorlns(msg);
warning()('RequireJS failed.');
/* c8 ignore next 3 */
} else {
grunt.log.oklns(msg);
}
};
});

return requirejs;
}

grunt.registerMultiTask('requirejs', 'Build a RequireJS project.', function() {
var done = this.async();
var options = this.options({
requirejs: undefined,
/* c8 ignore next */
logLevel: grunt.option('verbose') ? LOG_LEVEL_TRACE : LOG_LEVEL_WARN,
error: false,
force: false,
verbose: false,
done: function(done) {
done();
}
});
// If force is set, failures will be only logged and not abort the process.
force = options.force;
// If verbose is set, requirejs will print more about the progress on the console.
if (options.verbose) {
options.logLevel = LOG_LEVEL_TRACE;
}

// The following catches errors in the user-defined `done` function and outputs them.
var tryCatchDone = function(fn, done, output) {
try {
fn(done, output);
} catch (e) {
grunt.fail.warn('There was an error while processing your done function: "' + e + '"');
warning()('There was an error while processing your done function: "' + e + '"');
done();
}
};

Expand All @@ -51,15 +80,22 @@ module.exports = function(grunt) {
try {
fn(done, err);
} catch (e) {
grunt.fail.fatal('There was an error while processing your error function: "' + e + '"');
fatal()('There was an error while processing your error function: "' + e + '"');
done();
}
};

// Ensure that done() is always called. Not calling it would abort
// execution of still pending tasks after this one.
var doneNoArgs = function() {
done();
};

var requirejs = initializeRequire(options.requirejs);
requirejs.optimize(
options,
tryCatchDone.bind(null, options.done, done),
options.error ? tryCatchError.bind(null, options.error, done):undefined
tryCatchDone.bind(null, options.done, doneNoArgs),
options.error ? tryCatchError.bind(null, options.error, doneNoArgs) : doneNoArgs
);

});
};
1 change: 1 addition & 0 deletions test/failure/invalid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
define(function(){return "never";}
3 changes: 3 additions & 0 deletions test/failure/project.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require(['invalid'], function(invalid) {
console.log(invalid);
});