ESLint
A brief history...
A man named Crockford thought there were only a few good parts to JavaScript.
He also thought we were doing it wrong...
And made JSLint to police how you write JavaScript
Problems ...
- Too strict
- Too opinionated
- One mans opinions
- Made develoeprs cry
Solutions ...
JSHint
- The kinder linter
- Configuerable rules
ESLint
- Linting
- Configurable
- Every rule is a plugin
- Agenda free
- Style checking
The Philosophy of ESLint
- Every rule is Pluggable
- Every rule is standalone
- Every rule can be turned off or on
- Every rule can be a warning or an error
- Agenda free - ESLint does not promote any particular coding style
Configuring ESLint
.eslintrc
{
"env": {
"browser": true,
"node": true
},
"globals": {
"angular": true
},
"rules": {
"semi": 2,
"camelcase": 2,
"curly": 2,
"brace-style": [2, "1tbs"],
"quotes": [2, "single"],
"semi": [2, "always"],
"space-in-brackets": [2, "never"],
"space-infix-ops": 2,
"space-after-keywords": [2, "always"],
"dot-notation": 2,
"eqeqeq": [2, "smart"],
"no-use-before-define": 2,
"no-redeclare": 2,
"no-inner-declarations": "both",
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],
"no-floating-decimal": 2,
"no-spaced-func": 2,
"no-extra-parens": 1,
"no-underscore-dangle": 0,
"valid-jsdoc": 1,
"space-after-keywords": 2,
"max-len": [2, 120],
"no-use-before-define": [2, "nofunc"],
"no-warning-comments": 0,
"strict": 0,
"eol-last": 0
}
}
In file configuration
Disable everything
or just a rule
/* eslint-disable */
var obj = { key: 'value', }; // I don't care about IE8
/* eslint-enable */
/*eslint-disable no-alert */
alert('doing awful things');
/* eslint-enable no-alert */
or just tweak it
/* eslint no-comma-dangle:1 */
var obj = { key: 'value', } // Make this just a warning, not an error
your-project
├── .eslintrc
├── lib
│ └── source.js
└─┬ tests
├── .eslintrc
└── test.js
Cascading and Hirearchy
Project specific settings, and directory overrides.
Using ESLint
integrations and cli
Plugins available for...
- Sublime
- Vim
- Emacs
- TextMate2
- Atom.io
- WebStorm
Sublime
As you type ...
On save ...
Gulp
gulp-eslint
/**
* JavaScript Linting Task
*/
gulp.task('lint', function() {
return gulp.src('client/app/**/*.js')
.pipe(reload({stream: true, once: true}))
.pipe(eslint())
.pipe(eslint.format());
});
CLI
Possible Errors
- no-comma-dangle
- no-cond-assign
- no-console
- no-cosntant-condition
- valid-typeof
- no-debugger
- no-dupe-keys
- no-unreachable
- ...and more
Best Practices
- blocked-scope-var
- complexity
- consistent-return
- curly
- default-case
- dot-notation
- eqeqeq
- no-alert
- ... and more
What does it have rules for?
Variables
- no-catch-shadow
- no-delete-var
- no label-var
- no-shadow
- no-use-before-define
- ... and more
Node.js
- handle-callback-err
- no-mixed-requires
- no-new-requires
- no-path-concat
- no-process-exit
- ..and more
Stylistic issues
- indent
- brace-style
- camelcase
- func-style
- max-nested-callbacks
- no-space-before-semi
- no-underscore-dangle
- ... and more
.... and more
That isn't enough?
Write your own
module.exports = function(context) {
'use strict';
function report(node) {
context.report(node,
'You should use the $timeout service instead of the default window.setTimeout method',
{});
}
return {
'CallExpression': function(node) {
if (node.callee.type === 'MemberExpression' && node.callee.object.name ===
'window' && node.callee.property.name === 'setTimeout') {
report(node);
}
}
};
};
eslint-plugin-angular - ng_timeout_service
What is the downside?
... there is always a downside
Slower
2x-3x per file
[18:52:10] Finished 'jhint' after 1.3 s
[18:53:04] Finished 'lint' after 2.24 s
- 137 files
- 7062 lines of code
What is the practical impact on...
JSHint
ESLint
Why is it slower?
It uses Espree to construct an AST,
THEN
evaluates your code
JSHint evaluates your code as it parses.
Should we use it?
.... I think so
- Performance impact is worth the trade offs
- Can lint for common errors
- Can style check
- Can create custom rules
- Can specify language options
- Enable ES6 features
- Using react? enable JSX features
Useful Rules
no-shadow
var a = 3;
function b() {
var a = 10;
}
no-redeclare
var a = 3;
var a = 10;
no-inner-declarations
// Good
var foo = 42;
// Bad
while (test) {
var bar;
}
can help prevent issues with hoisting
no-unreachable
function fn() {
x = 1;
return x;
x = 3; // this will never execute
}
valid-jsdoc
/**
* Adds two numbers together.
* @param {int} num1 The first number.
* @param {int} num2 The second number.
* @returns {int} The sum of the two numbers.
*/
function sum(number1, num2) {
return number1 + num2;
}
if your going to document, document it right.
block-scoped-var
function doSomething() {
if (true) {
var build = true;
}
console.log(build);
}
Code Complexity
- complexity
- max-depth
- max-len
- max-statements
- max-nested-callbacks
- max-params
Make our own rules
Potential rules from our guidelines
- Use one var per variable
- Avoid function declarations in blocks
- Name your "anonymous" functions
- Consider the else
- Throw good errors
- Use braces with blocks
- Set to null to delete
- Keep your hands off prototypes of built-in objects
- Capitalize names of AngularJS controller
- Do not use "Hungarian notation"
- Do not use Angular's prefixes. Use your own
... some of these are already available
Potential rules from our guidelines
- Avoid long promis chains
- Catch errors in promises
- Use .then(null, errorHandler)
- Avoid $q.defer
... some of these are already available
When to lint?
early and often, but..
- pre-commit hooks?
- on CI?
- before merging?
Intro to ESLint
By Evan Schultz
Intro to ESLint
- 1,788