- Column address: Front-end compilation and engineering
- Author: NSGUF Sauce
1 background
Javascript is a dynamic, weakly typed language that is compiled at run time, which results in many errors that are exposed only at run time and difficult to detect during coding. Eslint is a plug-in JS code detection tool that allows developers to write their own rules and find rules that do not conform to the rules in the source code to help developers find problems during programming.
2 Lint tools
- JSLint: The granddaddy of checking, directly checking source file strings; The configuration is small, the specification is strict, and the scalability is poor. Therefore, the corresponding rule cannot be located according to the error.
- JSHint: Based on JSHint development; The parameters of rules can be configured, and a complete editor plug-in is provided. Some common library classes and ES6 are supported. However, custom rules are not supported, and corresponding rules cannot be located based on errors.
- ESLint: AST tree-based detection rules; Extensible parsers, extensible rules and configurations;
JSHint and ESlint features:
- JSHint checks the source file strings directly, whereas ESLint converts the source code into an AST to determine all rules, so JSHint executes faster than ESLint;
- ESLint has good scalability; The core of ESLint is to check whether the AST complies with rules;
- Step 1: The parser converts the source code into an AST; ESLint’s parser can be customized. If the source code uses advanced syntax or TS, you can directly replace the parser to get the final AST, and ESLint can do rule matching;
- Step 2: Enforce rules; ESLint’s detection rules are customizable;
3 Basic Usage
- Project install ESLint:
yarn add eslint -D
; - To initialize ESLint configuration: eslint –init;
- Checking ESLint: Run ESLint;
3.1 Basic Parameters
Eslint can configure parameters in either a configuration file or on the command line. The parameters in the configuration file may not contain command lines. To facilitate viewing and using, you are advised to configure them in the configuration file first.
3.1.1. Eslintrc parameters
Check out eslint.org/docs/user-g… ;
module.exports = {
// If there are multiple subprojects in the project, and each project has.eslintrc, the subproject will look up all.eslintrc until it finds root:true eslintrc, and then merge all.eslintrc
'root': true./ / on the environment defined by a set of global variables default details see: https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments
'env': {
// Browser global variables
browser: true.// node.js global variables and scopes
node: true.// CommonJS global variables and CommonJS scopes
commonjs: true.// Enable all ECMAScript 6 features except modules
es6: true
},
// Provide data to each rule to be executed
"settings": {
"sharedData": "Hello"
},
// Inherit all features from another configuration file
'extends': [
'eslint:recommended'.'plugin:@typescript-eslint/recommended'].// Plugins that add various extensions to ESLint to define rules, environments, or third-party modules for configuration
'plugins': [
'@typescript-eslint'].// Global variables
'globals': {
// False, readable, and readOnly are equivalent, indicating that the variable can only be read but not written.
// true, writeable, and writable are equivalent, indicating that a variable can be read and written.
'$': true.'console': false
},
/ / interpreter
'parser': '@typescript-eslint/parser'.// Interpreter configuration
'parserOptions': {
// Code module type, optional script(default), module
'sourceType': 'module'.// Specify the ECMAScript version, default is 5
'ecamVersion': 6.// Additional language features, all options are false by default
'ecmaFeatures': {
// Whether to allow return statements in the global environment
'globalReturn': true.// Whether to enable global script mode
'impliedStrict': true.// Whether to enable JSX
'jsx': true./ / whether to enable support for experimental objectRest/spreadProperties
'experimentalObjectRestSpread': false}},/ / rules
'rules': {
// Disable alert
'no-alert': 'off'.// There is no space before the comma and space after it
'comma-spacing': [2, {
'before': false.'after': true}]}};Copy the code
3.1.2 Command Line Parameters
Check out eslint.cn/docs/user-g… ;
eslint [options] file.js [file.js] [dir] Basic configuration: --no-eslintrc disallows the use of configuration files. --config path::String Specifies the path to use.eslintrc.* configuration file (may not be the name) --env [String] specifies the environment --ext [String] Specifies the JavaScript file extension. Default: .js --global [String] Defines global variables --parser String Specifies the parser --parser-options Object Specifies the parser configuration --resolve-plugins-relative-to Path ::String Specifies the folder from which the plug-in should be resolved, the default being CWD Specifying rules and plugins: Fixing problems: --rulesdir [path::String] -- Plugin [String] -- Rule Object --fix Fixes esLint problems --fix-dry-run Fixes problems automatically but does not save changes to files --fix-type Array Specifies the repair type (problem, suggestion, layout) to apply. Ignoring files: --ignore-path path::String Specifies a file to be ignored. Eslintignore --no-ignore Disables the use of ignored files and patterns. --ignore-pattern [String] File modes to ignore (except files in.eslintignore) Using stdin: --stdin < stdin > provides Lint code - default: false --stdin-filename String specifies the filename Handling warnings for stdin: --quiet Reports only errors - Default: false --max-warnings Int Number of warnings that trigger the exit code - Default: -1 Output: -o, --output-file path::String Specifies the file to write the report to -f, --format String uses a specific output format. - Default: Stylish --color, --no-color Enforces/disables color Inline configuration comments: --no-inline-config Prevents comments from changing configurations or rules -- report-unused-disable-caching Adds error information to the unused ESlint-disable directive Caching: -- report-unused-disable-caching adds error information to the unused ESlint-disable directive Caching: --cache checks only changed files - Default: false --cache-file path::String Path to the cache file. This parameter is not recommended: use --cache-location - Default: .eslintCache --cache-location path::String Path to the cache file or directory. Miscellaneous: --init Runs the configuration initialization wizard - Default: false --debug prints debugging information -h, --help displays help documents -v, --version prints the version number --print-config path::String Prints the configuration of a given fileCopy the code
3.2 Supplementary concepts of common Parameters
3.2.1 parser
- Esprima: an early parser used by ESLint;
- Espree: Developed based on Esprema V1.2.2, now the default parser;
- @babel/eslint-parser: parser for js high-level syntax;
- @typescript-eslint/parser: ts parser;
3.2.2 Rule Configuration
- “Off” or 0: turns off the rule;
- “Warn” or 1: opens the rule and uses a warning level error: WARN (will not cause the program to exit);
- “Error” or 2: enable the rule, using error level errors: error (when triggered, the program will exit);
3.2.3 extends Configuration types supported
- Eslint: official extension of ESLint;
- Plugin beginning: plug-in type extension; Corresponds to the configS configuration.
- Eslint-config: NPM package, used without the prefix eslint-config-;
- File path;
Common extensions:
- Eslint :recommended: built-in esLint recommended Rules, i.e. Rules that are checked in the list of ESLint Rules;
- Eslint :all: All rules built into ESLint;
- Eslint-config-standard: the JS specification for standard;
- Eslint-config-prettier: Shuts off a rule that conflicts with ESLint and other extensions;
- 12. eslint-plugin-vue: the official ESlint configuration plugin for Vue. The configuration shares are:
- Plugin :vue/base;
- Plugin :vue/essential;
- Plugin :vue/recommended:
- Plugin :vue/strongly-recommended:
3.3 Configuring files or directories that don’t need Lint
You can specify the corresponding file or directory in.eslintignore so that esLint does not detect when executing (esLint itself ignores node_modules and bower_components); Such as:
mock
build/*.js
config/*.js
Copy the code
4 ESLint configures sharing
The specifications of each team are different, and the company internally expects the specifications of each product line to be consistent. Therefore, the configuration can be shared into NPM packages for different teams to directly configure and use.
How to write a configuration share?
- Create a folder named eslint-config-myconfig;
- perform
yarn init -y
; (The module name must start with eslint-config-, and the project file name is optional); - Create index.js and write the.eslintrc.js configuration to share.
- Declare dependent ESLint with the peerDependencies field (make it clear that plug-ins need ESLint to function properly);
- The package can be sent;
PS: write plugins in @scope/eslint-xxx-xxx format.
How do I use the package above?
- Installation package, such as:
yarn add eslint-config-myconfig -D
; - Configure the extends configuration in the. Eslintrc section of the project.
5 ESLint plug-in
5.1 What is an ESLint plug-in?
Plugins can add various extensions to ESLint, and are third-party modules that define rules, environments, processors, or configurations;
How to customize an ESLint plug-in?
Use generator-eslint to create a project whose module name begins with eslint-plugin-, without the eslint-plugin-;
For example, NPM package name: eslint-plugin-myplugin;
5.1.1 Defining rules
Rules: How esLint checks rules; Define how: specifies that a rules object must be exposed;
// This is the plugin's index.js
module.exports = {
rules: {
'my-rule': {
// Some data configuration for the rule
meta: {
// Rule type "problem", "suggestion", or "layout"
type: 'suggestion'.// Document information can be omitted from custom rules or plug-ins, and is required for esLint core rules
docs: {
description: 'Short description of rules, shown on the front page of ESLint rules'.category: 'Classification of rules on the first page of rules'.recommended: true.// "extends": "esLint :recommended" property whether the rule is enabled
url: 'https://eslint.org/docs/rules/no-extra-semi' // Access the full document URL
},
// Enable fixes, ESLint will not fix rules even if they implement fixes if there is no fixable attribute. Omit the fixable attribute if the rule is not fixable
fixable: 'code'.// Specify the configuration of the rule to verify that the configured options are valid
schema: [{"enum": ["always"."never"] {},"type": "object"."properties": {
"exceptRange": {
"type": "boolean"}},"additionalProperties": false}},// create returns an object of the form key corresponding to a callback method; This object contains methods that ESLint uses to access nodes while iterating through the AST tree (ESTree defined AST) of JavaScript code.
// Context The context object in which ESLint is currently executed. This object contains various related data, such as configuration information for ESLint, information about the node being traversed, and methods for reporting problems.
create: function (context) {
return {
// callback functions
ReturnStatement: function (node) {
// at a ReturnStatement node while going down
},
// at a function expression node while going up:
'FunctionExpression:exit': function checkLastSegment (node) {
// report problem for function if last code path segment is reachable
},
'ArrowFunctionExpression:exit': function checkLastSegment (node) {
// report problem for function if last code path segment is reachable
},
onCodePathStart: function (codePath, node) {
// at the start of analyzing a code path
},
onCodePathEnd: function (codePath, node) {
// at the end of analyzing a code path}}; }}}};Copy the code
Usage:
module.exports = {
"plugins": ["myplugin"]."rules": {
"myplugin/my-rule": [2."never", { "exceptRange": true}].}}Copy the code
5.1.1.1 Rules Parameters
The meta parameter of Rules fills in some basic information, and the value of the create parameter is used to execute the callback method that detects AST rules.
Create context parameter:
- Id: specifies the rule name configured in rules of. Eslintrc, as described above
myplugin/my-rule
; - [“never”, {exceptRange: true}] [“never”, {exceptRange: true}]
- Report: used to issue warnings or errors and to judge calls in a callback Specific parameters;
More context parameters: eslint.cn/docs/develo… ;
Create’s return object:
- If a key is a node type or selector, ESLint calls the visitor function while iterating down the tree;
- If a key is a node type or selector with :exit, ESLint calls the visitor function while traversing up the tree;
- If a key is an event name, ESLint calls handler functions for code path analysis;
Node type: node type of the AST.
Details are as follows:
The serial number | Type original name | Chinese name | describe |
---|---|---|---|
1 | Program | application | The body of the entire code |
2 | VariableDeclaration | Variable declarations | Declare a variable, such as var let const |
3 | FunctionDeclaration | Function declaration | Declare a function, such as function |
4 | ExpressionStatement | Expression statement | Usually a function is called, such as console.log() |
5 | BlockStatement | Block statements | Code wrapped in {} blocks, such as if (condition){var a = 1; } |
6 | BreakStatement | Break statement | Usually refers to break |
7 | ContinueStatement | Last statement | Usually refers to the continue |
8 | ReturnStatement | Return statement | Usually refers to the return |
9 | SwitchStatement | A Switch statement | Usually refers to the Switch in a Switch Case statement |
10 | IfStatement | If control flow statement | Control flow statements, usually if(condition){}else{} |
11 | Identifier | identifier | Identifies, for example, identi in var identi = 5 when declaring a variable |
12 | CallExpression | Call expression | Usually refers to calling a function, such as console.log() |
13 | BinaryExpression | Binary expression | Usually refers to an operation, such as 1+2 |
14 | MemberExpression | Member expression | Usually refers to the member of the calling object, such as the log member of the Console object |
15 | ArrayExpression | Array expression | Usually an array, such as [1, 3, 5] |
16 | NewExpression | New expressions | This usually means using the New keyword |
17 | AssignmentExpression | Assignment expression | Usually refers to assigning the return value of a function to a variable |
18 | UpdateExpression | Update expression | Usually refers to updating member values, such as i++ |
19 | Literal | literal | literal |
20 | BooleanLiteral | Boolean literals | Boolean values, such as true false |
21 | NumericLiteral | Numeric literals | A number, such as 100 |
22 | StringLiteral | Character literals | A string, for example, vansenb |
23 | SwitchCase | A Case statement | Usually refers to a Case in a Switch statement |
Take a look at the node types of vue: github.com/vuejs/vue-e…
A selector is a string that matches a node in an abstract syntax tree (AST). This is useful for describing specific syntactic patterns in your code. Selectors are not limited to matching a single node type. For example, the selector “VariableDeclarator > Identifier” will match all identifiers that have VariableDeclarator. For details.
Events: Events triggered by parsing code paths;
module.exports = function(context) {
return {
/** * This is called at the beginning of parsing the code path, where the code path object has only the initial segment. * *@param {CodePath} codePath - The new code path.
* @param {ASTNode} node - The current node.
* @returns {void}* /
"onCodePathStart": function(codePath, node) {
// do something with codePath
},
/** * this is called at the end of the parse code path. At this point, the code path object is complete. * *@param {CodePath} codePath - The completed code path.
* @param {ASTNode} node - The current node.
* @returns {void}* /
"onCodePathEnd": function(codePath, node) {
// do something with codePath
},
/** * this is called when the code path segment is created. * This means that the code path is forked or merged. * During this time, the segment has a previous segment and has been judged to be reachable or unreachable. * *@param {CodePathSegment} segment - The new code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}* /
"onCodePathSegmentStart": function(segment, node) {
// do something with segment
},
/** * this is called when the code path segment leaves. * The next stage has not yet been reached. * *@param {CodePathSegment} segment - The leaved code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}* /
"onCodePathSegmentEnd": function(segment, node) {
// do something with segment
},
/** * is called when the code path segment is looped. * Usually each segment is created with a previous segment, * Usually segments have each previous segments when created, * but when looped, a segment is added as a new previous segment into a * existing segment. * * This is called when a code path segment was looped.Usually segments have each previous segments when created,but when looped, A segment is added as a new previous segment into aexisting segment. Normally when a segment is created, it has each previous segment, but as a loop, the segment is added to the existing segment as the new previous segment. *@param {CodePathSegment} fromSegment - A code path segment of source.
* @param {CodePathSegment} toSegment - A code path segment of destination.
* @param {ASTNode} node - The current node.
* @returns {void}* /
"onCodePathSegmentLoop": function(fromSegment, toSegment, node) {
// do something with segment}}; };Copy the code
Eslint. Cn/docs/develo…
5.1.2 Defining the Environment
Context: a set of configurations, such as all global variables in jquery;
The plug-in environment can define the following objects: globals: Same as globals in the configuration file. ParserOptions: Same as parserOptions in the configuration file.
Define how: Must expose environments objects;
// This is the plugin's index.js
module.exports = {
environments: {
jquery: {
globals: {
$: false
},
parserOptions: {}}}};Copy the code
Usage:
module.exports = {
"plugins": ["myplugin"]."env": {
"myplugin/jquery": true,}}Copy the code
5.1.3 Defining processors
Eslint can only detect JS files, if other files need to be configured with custom handlers; How it is defined: You must expose processors, take the file suffix as key, contain functions that take the file content and filename as arguments, and return an array of strings to examine;
// This is the plugin's index.js
// processor-name
module.exports = {
processors: {
// Different suffix names (.js,.jsx,.html, etc.)
".ext": {
// Get the text and filename of the file
preprocess: function(text, filename) {
// Here, you can strip out any non-JS content and split it into multiple strings for lint
return [string]; // return an array of strings to lint
},
// Get Message[][] and filename
postprocess: function(messages, filename) {
The 'messages' argument is a two-dimensional array of message objects, where the first argument of each entry contains the text-related Lint message array returned by the preprocess() method
The postProcess method accepts a two-dimensional array containing the detection message and the file name. Each entry in the input array corresponds to the part returned from the preProcess method. The preProcess method must adjust the locations of all errors to correspond to the locations in the original unprocessed code, aggregate them into a flattened array and return them.
// Return the one-dimensional array you want to keep
return messages[0];
},
supportsAutofix: true // (optional, defaults to false)}}};Copy the code
Usage:
// Method 1: unity
module.exports = {
"plugins": ["myplugin"]."processor": "myplugin/processor-name"
}
// Method 2: Specify a handler for a particular type of file
module.exports = {
"plugins": ["myplugin"]."overrides": [{"files": ["*.md"]."processor": "a-plugin/markdown"
},
{// Specify additional configurations for named code blocks in the config section
"files": ["**/*.md/*.js"]."rules": {
"strict": "off"}}}]Copy the code
5.1.4 Defining the Configuration
In addition to sharing the configuration directly by sending a package (as in point 4 of this chapter), you can also share the configuration by plug-in, and multiple configurations of a plug-in are supported. For example, if you write some rules and want to share several code styles, you can use this.
// This is the plugin's index.js
module.exports = {
configs: {
myConfig: {
plugins: ["myPlugin"].env: ["browser"].rules: {
semi: "error"."myPlugin/my-rule": "error"."eslint-plugin-myPlugin/another-rule": "error"}},myOtherConfig: {
plugins: ["myPlugin"].env: ["node"].rules: {
"myPlugin/my-rule": "off"."eslint-plugin-myPlugin/another-rule": "off"
"eslint-plugin-myPlugin/yet-another-rule": "error"}}}};Copy the code
Usage:
- Add the plug-in to the plugins configuration;
- Extends configuration is used directly;
module.exports = {
plugins: ['myPlugin'].extends: ['plugin:myPlugin/myConfig'.'plugin:myPlugin/myOtherConfig']}Copy the code
5.2 How to Write Rules separately in a Project?
To write a plug-in separately, you need to send a package, which leads to a long process of adding rules and may not be suitable for other product lines. In this case, you need to add custom rules in a single project.
5.2.1 Mode 1: IDE does not recognize
Use esLint’s own –rulesdir parameter to retrieve rules from additional files in the project; This only works when the eslint command is run;
Configuration steps:
- Add the eslint-rules folder to the project’s.eslintrc hierarchy and add custom rules to this directory (rule creation: 5.1.1);
- Add XXX: 2 to.eslintrc rules;
- Change the eslint command to:
eslint --rulesdir eslint-rules --ext .vue,.js,.ts src
; (Can also be configured in WebPack or Vite)
Result: The rule is detected when the command is executed. Disadvantages: the editor does not recognize, and will mark the first line of each file in red to say that the corresponding rule cannot be found, while the real problem is not marked in red;
5.2.2 Mode 2: IDE identification
Use the eslint-plugin-rulesdir plugin; Steps:
- Add the eslint-rules folder to the project’s.eslintrc hierarchy and add custom rules to this directory (rule creation: 5.1.1);
- The installationThe plug-in:
yarn eslint-plugin-rulesdir -D
; - Modify the. Eslintrc configuration.
const rulesDirPlugin = require('eslint-plugin-rulesdir');
// The directory for the rule can be a string or an array of strings
rulesDirPlugin.RULES_DIR = 'eslint-rules';
module.exports = {
// ...
plugins: ['rulesdir'].rules: {
// XXX indicates the corresponding user-defined rule
'rulesdir/xxx': ['error'],}};Copy the code
Result: No need to specify –rulesdir, rules recognized, editor recognized;
6. Optimal use scheme of related engineering
The engineering of the project can improve the development efficiency and reduce some easily avoided mistakes; Here are some useful tools that work with ESLint:
- Husky: run the eslint command before committing. If eslint fails, the commit fails.
- Lint-passage: Husky hooks only apply to passively obtained documents;
- Prettier: Modify code style, no matter low-level problems If there are configurations that conflict with ESLint, use eslint-plugin-prettier alongside ESLint.
- MRM: Husky and Lint-staged are automatically installed and configured from package.json, so be sure to install and configure all code quality tools, such as Prettier and ESlint, before doing so;
The use of these tools is not described, relatively simple, check the official documents can;