Eslint trick: lint only changed files to upgrade project codestyle

The f*cking problem

What if you are working on a large project, and after some meetings with your lovely team mates you decided it’s time to sharpen the good ‘ol eslint config.

Eslint errors

Everything fails, you got 2042234897234 errors help, 911 please help. WTF.

So you try eslint –fix, but still 999239 errors.

Calm down, I got the perfect solution for you.

What if you could only run Eslint on the commited changed files 😉 ? And by doing so, you can slowly migrate everything to adopt to the new code style. Plus when you have some time left over, you could refactor that auto-fetch-nudes component to the new code style. Fucking awesome.

The importance of a consistent code style

Ok lets get serious:

I believe it’s very important that a development team maintains a consistent code style, even for simple things like:

codestyle.js

// a space before and after the if's parenthesis
if ( ) {

 // a space before the functions parenthesis
function myFunction () {

Now it doesn’t really matter too much what kind of rules you apply, but it is important to be consistent

We probably all know that Eslint helps us with checking if we are all following these rules. We can use stuff like Husky to automatically trigger linting on precommit or even on prepush hooks.

The solution

First we are going to install Husky if you don’t already use it:

husky

npm install husky --save-dev

The next step is to setup our precommit hook, powered by Husky in your package.json like so:

package.json

{
  // ...
  "scripts": {
    // ...
    "lint": "eslint ./src",
    "precommit": "node ./precommit.js"
  }
}

Where the magic happens

We are going to create the file: precommit.js in the root directory of your project. This file is the file we’ve pointed to in our precommit script in our package.json.

So whenever we commit, this file is called. And it will lint and fix everything before commit. BUT: only on the files you are about to commit, holy shit.

precommit.js

/* eslint-disable no-console */

/**
 * Windows users use git-bash to make this work (https://git-for-windows.github.io/)
 */

const child_process = require('child_process');
const path = require('path');

let exitCode = 0;

const toError = stdout => {
  const error = stdout.toString('utf8');
  if(error.length > 0) {
    console.log(error);
    exitCode = 1;
  }
};

const getChangedFiles = () => {
  let changedFiles = null;

  try {
    const str = child_process.execSync('git diff --cached --name-only | grep \'.js$\'').toString('utf8');
    changedFiles = str.split(/(\r?\n)/g).filter(line =>  !(line === '\n' || line === '\r' || line.length < 1));
  } catch (e) {
    toError(e.stdout);
  }

  return changedFiles;
};

const lintFiles = files => {
  if(files) {
    files.forEach(file => {
      if(path.extname(file) !== '.js') {
        return;
      }

      try {
        child_process.execSync(`${path.join(__dirname, 'node_modules/.bin/eslint')} --fix ${file}`).toString('utf8');
      } catch (e) {
        toError(e.stdout);
      }
    });
  }
};

const changedFiles = getChangedFiles();
lintFiles(changedFiles);

process.exit(exitCode);

Get creative

Feel free to duplicate precommit.js and name it prepush.js. You can change the stuff that needs to happen in prepush (for example, I don’t –fix in my prepush) get creative with this. You get the idea.

Final thoughts

Feel free to leave comments and don’t forget to bookmark Codersmind 😉

Cheers,

Mike

  • http://www.natalink.ru/ Юрий Акимов

    Awesome. Thank you.

    Only one problem, you will fix files using –fex key, but commit unfixed files in the case autofix made his job and there is no more lint errors.