В настоящее время я настраиваю сценарий автоматической сборки (с gruntjs) для require.js запущенный проект. Поэтому я хотел бы запустить jslint/jshint во всех необходимых файлах перед объединением и минимизацией их с помощью r.js . Поскольку папка js содержит много файлов разработки, которые я не хочу анализировать, я не могу просто передать js/**/*.js
в JSLint. Моей первой мыслью было запустить r.js с optimizer: 'none'
, линтинговать конкатенированный файл, а затем минимизировать его, но это не вариант по двум причинам. Во-первых, он будет включать в себя библиотеки поставщиков, которые я не хочу анализировать, а во-вторых, находить строку с ошибкой, находить ее класс, находить соответствующий js-файл в папке dev, исправлять его там, снова запускать r.js и, наконец, проверять его. опять же, это слишком много хлопот для нашего рабочего процесса. Поэтому я ищу возможность подключить линтинг к процессу оптимизатора r.js или, по крайней мере, каким-то образом получить список дерева зависимостей requirejs, который я могу проанализировать и передать в lint. Или любое практическое решение для автоматизированного процесса, которое вы придумаете.
Использование JSLint/Hint с requirejs
Ответы (4)
Этот ответ как бы обходит Grunt, но он должен работать для того, что вы хотите сделать. Я бы посмотрел на r.js и попытался переопределить функцию, которая получает путь к различным загружаемым модулям, перехватывает имя модуля и анализирует файлы, пока r.js загружает и компилирует модули. Я сделал это так:
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)
Затем, когда вы запускаете requirejs.optimize на своих модулях, вы должны получить все непустые URL-адреса JavaScript, зарегистрированные в консоли. Вместо того, чтобы записывать их в консоль, вы можете использовать URL-адреса для проверки файлов.
Сначала линтуй, потом компилируй. Просто укажите конкретные файлы, которые вы хотите проверить, и используйте ! префикс для игнорирования определенных файлов:
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']);
Я предпочитаю не переопределять методы r.js, иначе вы можете создать нежелательную зависимость от конкретной версии (вам нужно будет обновить свой код, если r.js изменится)
Это код, который я использую для той же цели, используя функцию onBuildRead из require и тот факт, что объекты в javascript передаются по ссылке. Я сначала запускаю требуемую сборку, а затем анализирую источники файлов js.
Недостатком является то, что вы будете ворсить после завершения сборки. Для моей установки это не проблема.
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
};
Вместо использования задачи lint
установите, загрузите и настройте grunt-contrib-jshint. . У него есть опция ignores
для игнорирования определенных файлов или шаблонов путей к файлам.
Вот моя задача:
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'
}
}