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
- Lint
- Unit tests
- Integration tests
- Benchmarks
Talk
Analyze
Code
Test





This talk is about linters
- Lint
- Unit tests
- Integration tests
- 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
- mocha
- chai
-
eslint
- babel-preset-es2015
- 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)
-----
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☺