Recently I had to add a linter on a project in which the codebase was never linted before. I am talking about a big codebase in which a team have worked on it for years already.
Obviously, the amount of errors thrown from the linter, was such a big number to become an useless information.
With my team mates, we agreed on run the linter only on the “touched” files: the behaviour we wanted was to get the linter parsing every file that gets changes.
So, if I am working on the file A, until I don’t save it, the linter throw 0 errors (because of no file parsed). When I do save the file A, then the linter parses it and throw (maybe!) errors.
Looking around in the web, wasn’t obvious how to do it: so I planned to write the code to do it myself – using a watcher to detect file changes – as part of Webpack configuration (the best solution would be to relay on git to detect changes I believe, not a watcher, but will be the next step).
This is the implementation (inside the webpack.config.js), I paste it as it is now:
// Dependencies for Webpack (usually this goes at the top) var logger = require('reliable-logger'); var watch = require('watch'); var CLIEngine = require('eslint').CLIEngine // ... // place this when you want in the file, accordingly to your own organisation // preferences! // This is the function to run watcher and linter var configureLinterAndWatchFiles = function() { var changedFiles = []; var formatter; var report; var SEPARATOR = "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////"; // TODO I got the feeling that one of those settings is breaking the // linter (probably the path resolving?) var linter = new CLIEngine({ // TODO do I need this? Looks like I don't... // envs: ["node"], // TODO what is the default? useEslintrc: true, // TODO I find weird that I get no error with this: configFile: // "../.eslintrc1111" // make sure that the configuration file is correctly picked up configFile: ".eslintrc", // TODO useless if your root is src // ignorePath: "node_modules" // TODO probably both useless... the first I still don't get it, // the second you are enforcing the filtering yourself by checks // cache: false, // extensions: [".js", ".jsx"] }); var fileUpdatedFn = function(f) { // TODO I would prefer much more to get the list of changed files from // git status (how to?). Here I am building my own // resetting the array only for debug purpose // changedFiles = []; if(/.js$/.test(f) || /.jsx$/.test(f)) { changedFiles.push(f); logger.info(SEPARATOR); report = linter.executeOnFiles(changedFiles); logger.info(formatter(report.results)); } }; // get the default formatter formatter = linter.getFormatter(); watch.watchTree('src', function(f, curr, prev) { if (typeof f == "object" && prev === null && curr === null) { // Finished walking the tree } else if (prev === null) { // f is a new file } else if (curr.nlink === 0) { // f was removed } else { // f was changed fileUpdatedFn(f); } }); }; // last bit: running the function! module.exports = function(callback, options){ // ... configureLinterAndWatchFiles(); }
It is still to be improved but it does the job, so good to share it!
Thanks for reading!