Read more

Integrating ESLint

Johanna Schalk
January 31, 2022Software engineer at makandra GmbH

Introduction

To ensure a consistent code style for JavaScript code, we use ESLint Show archive.org snapshot . The workflow is similar to integrating rubocop for Ruby code.

1. Adding the gem to an existing code base

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

You can add the following lines to your package.json under devDependencies:

  "devDependencies": {
    "eslint": "^8.7.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^6.0.0"
  }

This should work for node 12+.
Then run yarn install.

Add an .eslintrc.js file, for example:

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module',
  },
  ignorePatterns: [
    '/coverage/',
    '/node_modules/',
    '/tmp/',
    ...
  ],
  globals: {
    up: 'readonly',
  },
  extends: [
    'standard',
  ],
}

This config is based on the standardjs.com ruleset Show archive.org snapshot and has been adjusted slightly.


Example ignorePatterns for a project with webpack:

ignorePatterns: [
  '/coverage/',
  '/node_modules/',
  '/public/packs/',
  '/public/packs-test/',
  '/tmp/',
],

Example ignorePatterns for a project with esbuild:

ignorePatterns: [
  '/app/assets/builds/',
  '/coverage/',
  '/node_modules/',
  '/public/assets/',
  '/public/assets-test/',
  '/tmp/',
],

2. Report all existing offenses and exclude them initially

Add an RSpec test, which runs ESLint (also during a full RSpec test run), e.g. in spec/eslint_spec.rb:

require 'open3'

RSpec.describe 'eslint' do
  it 'is not offended' do
    stdout, stderr, status = Open3.capture3('yarn', 'run', 'eslint', '.')
    failure_message = [stderr, stdout].reject(&:empty?).join("\n\n")

    expect(status.success?).to eq(true), failure_message	
  end	
end

Run the test or simply run yarn run eslint . from your console to check all files.
Now you should get a list of all existing offenses, for which you should disable the rules in your .eslint.rc.js at first:

rules: {
  'comma-dangle': 'off',
  'padded-blocks': 'off',
  'space-before-function-paren': 'off',
  'prefer-const': 'off',
  ...
},

This is only a temporary measure. We fix each offense in the next step.

3. Fixing each offense per commit

Now you should fix each offense in an own commit.

  1. Remove one of the disabled rules
  2. Run your spec or yarn run eslint .
  3. Fix all offenses, either manually or with the auto-correct yarn run eslint . --fix
  4. Check if tests are still green and everything works as expected
  5. Commit the changes with a message like [#180343876] Fix ESLint offense for rule "comma-dangle"

To run a single file, use yarn run eslint path/to/some_file.js.

3.1 Disable and configure specific rules

You can use comments to disable specific rules in your JavaScript code. Show archive.org snapshot .
Or you could use your own configuration for specific rules, like:

rules: {
  'padded-blocks': 'off',
  'space-before-function-paren': [
    'error', {
      anonymous: 'never',
      named: 'never',
      asyncArrow: 'always',
    },
  ],
},

3.2 Disable specific rules for a lot of files

If you have a lot of files for which you want to disable a specific rule, e.g. Jasmine specs, you could use overrides in your .eslintrc.js:

overrides: [
  {
    files: ['app/webpack/backend/index.js', 'app/webpack/frontend/index.js'],
    rules: {
      'import/first': 'off',
    },
  },
  {
    files: ['app/webpack/specs/**/*.js'],
    rules: {
      'no-undef': 'off',
    },
  },
],

With that you don't need to add a disabling comment to each file.

4. Finish the integration

In the end you have a long commit list, first for integrating ESLint and then for fixing each offense, e.g.:

...
[#180343876] Fix ESLint offense for rule "camelcase"
[#180343876] Fix ESLint offense for rule "space-before-blocks"
[#180343876] Fix ESLint offense for rule "no-useless-return"
[#180343876] Add ESLint without any offenses
Johanna Schalk
January 31, 2022Software engineer at makandra GmbH
Posted by Johanna Schalk to makandra dev (2022-01-31 17:06)