Robots Must Suffer

linters and tools for front-end development

Andrey Sitnik

© Eric Joyner

Evil Martians

I am from Russia

Lead front-end developer at

Author of

Autoprefixer

PostCSS

Why did I create PostCSS

?

Two types of tasks

Creative tasks

Boring tasks

Humans vs. robots

Creative tasks

Boring tasks

Humans

Robots

Robots don’t make mistakes

Work process

Talk

Analyze

Code

Test

Robots!

Talk

Analyze

Code

Test

Robots must suffer

© Eric Joyner

© Eric Joyner

Part 2: What is linters?

Talk

Analyze

Code

Test

Test

  1. Lint
  2. Unit tests
  3. Integration tests
  4. Benchmarks

Talk

Analyze

Code

Test

This talk is about linters

  1. Lint
  2. Unit tests
  3. Integration tests
  4. Benchmarks

What are linters?

Linters find mistakes in source code

Source code

Parser

Analysis

Errors list

Linting process

Unit tests vs. linters

y = 2 − (−x)

Unit tests

in: 2 out: 0
y(2) = 4, !== 0

Linters

−(−n)+n

Unit tests vs. linters

Unit tests

Linters

Check input and output

Don’t find an error

Check source code

Tell exact line

Unit tests + linters =

"scripts": {
  "test": "npm run lint && npm run unit-test"

Part 3
Popular
linters

© Eric Joyner

Node.js app

app.all('/apps/:user_id', request => {
  initial = extract(request.body)
})

After 4 hours of debugging

app.all('/apps/:user_id', request => {
  initial = extract(request.body)
})

app.all('/apps/:user_id', request => {
  var initial = extract(request.body)
})
var

Real story. Tests didn’t help.

ESLint could fix it

app.all('/apps/:user_id', request => {
  initial = extract(request.body)
})
ESLint: initial is not defined app.js:2:3

The most popular dependencies

  1. mocha
  2. chai
     
  3. eslint
     
  4. babel-preset-es2015
  5. lodash

JS linters evolution

JSLint

JSHint

ESLint

CSS

.foo {
  margin-top: 20px;
  width: 100px;
  height: 100px;
}

Horizontal centering

.foo {
  margin-top: 20px;
  width: 100px;
  height: 100px;
  margin: 0 auto;
}

After 5 min of debugging

.foo {
  margin-top: 20px;
  width: 100px;
  height: 100px;
  margin: 0 auto;
}

Stylelint could fix it

.foo {
  margin-top: 20px;
  width: 100px;
  height: 100px;
  margin: 0 auto;
}
Stylelint: this overrides the longhand property before it app.css:5:3

Stylelint languages

*.pcss

*.scss

*.vue

postcss-scss

postcss-html

*.less

postcss-less

Stylelint users

Part 4 Why

© Eric Joyner

Writing code vs. debug time

Dev

Debug

10 min

30 min

Normal

#1 Linters reduce debug time

Dev

Debug

10 min

30 min

Normal

10 min

25 min

With linters

Code reviews

Senior

Junior

#2 Linters reduce code reviews

Senior

Junior

Linter

It is hard to be a junior

Junior

Senior

Fixes

#3 Linters make juniors happy

Junior

Linter

Fixes

Big companies → multiple teams

Team 1

Team 2

Idea

?

#4 Sharing ideas

Team 1

Team 2

Linter config

Idea

Part 5 How

© Eric Joyner

Step 1  Install linters via npm

npm install --save-dev eslint stylelint

Step 2  Create a config

.eslintrc

.stylelintrc

{
  "rules": {
    "no-console": "error"
  }
}

Too many rules

ESLint: 300 rules

Stylelint: 161 rules

Step 3  Extend shareable config

{
  "extends": "standard",
  "rules": {
    "no-console": "error"
  }
}
npm install --save-dev eslint-config-standard

Popular configs

ESLint

Stylelint

Step 4 Linter plugins for text editors

Linter plugins text editor

Sublime Text

VS Code

Too many errors?

ESLint: 250 errors in 100 files

Step 5 Fix automatically

eslint --fix src/**/*.js
stylelint --fix src/**/*.css

Other developers ignore linter

Good developer

Bad developer

git commit …
npm run test
npm run lint
git push …
git commit …
git push …

Step 6 lint-staged

git commit …
run pre-commit hook
git add a.css
run stylelint a.css
Stylelint: 1 error
git: commit canceled

Install lint-staged

npm install --save-dev lint-staged pre-commit

lint-staged config

"scripts": {
  "lint-staged": "lint-staged",
},
"lint-staged": {
  "*.css": "stylelint"
},
"pre-commit": ["lint-staged"]

Step 6 Write custom plugins

Stylelint rule = simple PostCSS plugin

Facebook custom rules

  • slow-css-properties
  • filters-with-svg-files
  • use-variables
  • mobile-flexbox

Happened twice → write custom rule

Senior

Junior

Linter

Custom rule

Part 6
Other linters

© Eric Joyner

The best ESLint plugins

My favorite ESLint plugins

  • eslint-config-import
  • eslint-plugin-security
  • eslint-plugin-node

The best Stylelint plugins

div {
  -moz-box-sizing: border-box;
  width: 100%;
  box-sizing: border-box;
  position: absolute;
  -webkit-box-sizing: border-box;
}
div {
  position: absolute;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 100%;
}

Sort CSS properties

Lint English

$ yaspeller /home/ai/Dev/postcss/README.md
✗ /home/ai/Dev/postcss/README.md 453 ms
-----
Typos: 1
1. transorming (suggest: transforming, transporting)
-----

nsp

Check security in Node.js dependencies

> nsp check

(+) 1 vulnerabilities found
┌───────────────┬───────────────────────────────────────────────────────┐
│               │ ReDoS via long string of semicolons                   │
├───────────────┼───────────────────────────────────────────────────────┤
│ Name          │ tough-cookie                                          │
├───────────────┼───────────────────────────────────────────────────────┤
│ Installed     │ 2.2.2                                                 │
├───────────────┼───────────────────────────────────────────────────────┤
│ Vulnerable    │ >=0.9.7 <=2.2.2                                       │
├───────────────┼───────────────────────────────────────────────────────┤
│ Patched       │ >=2.3.0                                               │
├───────────────┼───────────────────────────────────────────────────────┤
│ Path          │ my-test-project@undefined > honeybadger@1.1.2 > requ… │
├───────────────┼───────────────────────────────────────────────────────┤
│ More Info     │ https://nodesecurity.io/advisories/130                │
└───────────────┴───────────────────────────────────────────────────────┘

Check webpack bundle size

Check accessibility

pa11y --config ./path/to/config.json http://example.com

The end

© Eric Joyner

Links

@andreysitnik  VPN

@evilmartians​  VPN