I'm currently setting up a automated build script (with gruntjs ) for a require.js driven project . Therefor I would like to run jslint / jshint on all required files before concatenating and minifying it with r.js. Since the js folder contains a lot of development files I don't want to lint, I can't just pass js/**/*.js
to JSLint. My first thought was to run r.js with optimizer: 'none'
, lint the concatenated file and then minify it, but this is not an options for two reasons. First it will include vendor libs I don't want to lint and second finding the line with the error, find it's class, find the appropriate js-file in the dev folder, fix it there, run r.js again and finally lint it again, is way to much hassle for our workflow. So I'm looking for a possibility to hook up the linting into the r.js optimizer process or at least get a list of the requirejs dependency tree in some way, that I can parse and pass it to lint. Or any solution practicable for an automated process, you'll come up with.
Lint first, compile later. Just be specific about the files you want to lint and use the ! prefix to ignore specific files:
grunt.initConfig({
lint: {
// Specify which files to lint and which to ignore
all: ['js/src/*.js', '!js/src/notthisfile.js']
},
requirejs: {
compile: {
options: {
baseUrl: 'js/src',
name: 'project',
out: 'js/scripts.js'
}
}
}
});
// Load the grunt-contrib-requirejs module.
// Do `npm install grunt-contrib-requirejs` first
grunt.loadNpmTasks('grunt-contrib-requirejs');
// Our default task (just running grunt) will
// lint first then compile
grunt.registerTask('default', ['lint', 'requirejs']);
I prefer not overriding r.js's methods, or you might create an unwanted dependency on a specific version (you'll need to update your code should r.js change)
This is the code I use for the same purpose, making use of require's onBuildRead function and the fact that objects in javascript are passed by reference. I make sure I run the require build first, then lint the js file sources.
The downside is that you'll lint after build complete. For my setup that is not a problem.
module.exports = function(grunt) {
var jsHintOptions = {
options: {
curly: true,
eqeqeq: true,
eqnull: true,
browser: true,
globals: {
jQuery: true
}
},
all: [] // <--- note this is empty! We'll fill it up as we read require dependencies
};
var requirejsOptions = {
compile: {
options: {
paths: {
"jquery": "empty:"
},
baseUrl: "./",
name: "src/mypackage/main",
mainConfigFile: "src/mypackage/main.js",
out: 'build/mypackage/main.js',
onBuildRead: function (moduleName, path, contents) {
jsHintOptions.all.push(path); // <-- here we populate the jshint path array
return contents;
}
}
}
};
grunt.initConfig({
pkg: grunt.file.readJSON('packages/mypackage.package.json'),
requirejs: requirejsOptions,
jshint: jsHintOptions
});
// load plugin that enabled requirejs
grunt.loadNpmTasks('grunt-contrib-requirejs');
// load code quality tool
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['requirejs', 'jshint']); // <-- make sure your run jshint AFTER require
};
This answer sort of bypasses Grunt, but it should work for what you want to do. The way I would do it is look at r.js and try to override a function that receives the path to the various modules being loaded, intercept the module name, and lint the files while r.js is loading and compiling the modules. I've done it like so:
var requirejs = require('requirejs');
var options = {/*r.js options as JSON*/};
var oldNewContext = requirejs.s.newContext;
requirejs.s.newContext = function(){
var context = oldNewContext.apply(this, arguments);
var oldLoad = context.Module.prototype.load;
context.Module.prototype.load = function(){
var module = oldLoad.apply(this, arguments);
if(/\.js$/.test(this.map.url) && !/^empty:/.test(this.map.url))
console.log(this.map.url);
return module;
}
return context;
}
requirejs.optimize(options)
Then when you run requirejs.optimize on your modules, you should get all the non-empty JavaScript urls logged to the console. Instead of logging them to the console, you could use the urls to lint the files.
Instead of using the lint
task, install, load, and set up grunt-contrib-jshint . It has an ignores
option to ignore specific files or file path patterns.
Here's my task:
jshint: {
options: {
// options here to override JSHint defaults
boss : true, // Suppress warnings about assignments where comparisons are expected
browser : true, // Define globals exposed by modern browsers (`document`, `navigator`)
curly : false, // Require curly braces around blocks
devel : false, // Define `console`, `alert`, etc. (poor-man's debugging)
eqeqeq : false, // Prohibit the use of `==` and `!=` in favor of `===` and `!==`
"-W041" : false, // Prohibit use of `== ''` comparisons
eqnull : true, // Suppress warnings about `== null` comparisons
immed : true, // Prohibit the use of immediate function invocations w/o wrapping in parentheses
latedef : true, // Prohibit the use of a var before it's defined
laxbreak: true, // Suppress warnings about possibly unsafe line breaks
newcap : true, // Require you to capitalize names of constructor functions
noarg : true, // Prohibit the use of `arguments.caller` and `arguments.callee`
shadow : true, // Suppress warnings about var shadowing (declaring a var that's declared somewhere in outer scope)
sub : true, // Suppress warnings about using `[]` notation, e.g. `person['name']` vs. `person.name`
trailing: true, // Trailing whitespace = error
undef : false, // Prohibit the use of explicitly undeclared variables
unused : false, // Warn when you define and never use your variables
white : false, // Check JS against Douglas Crawford's coding style
jquery : true, // Define globals exposed by jQuery
// Define global functions/libraries/etc.
globals : {
amplify : true
},
ignores: [
'src/app/templates/template.js',
'src/scripts/plugins/text.min.js'
]
},
gruntfile: {
src: 'Gruntfile.js'
},
app: {
src: 'src/app/**/*.js'
},
scripts: {
src: 'src/scripts/**/*.js'
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.