ESLint:全面指南

小沈是一個剛剛開始工作的前端實習(xí)生桌粉,第一次進行團隊開發(fā),難免有些緊張衙四。在導(dǎo)師的安排下铃肯,拿到了項目的 git 權(quán)限,開始進行 clone传蹈。

$ git clone git@github.com:company/project.git

小沈開始細細品味著同事們的代碼缘薛,終于在他的不懈努力下,發(fā)現(xiàn)了老王 2 年前寫的一個 bug卡睦,跟導(dǎo)師報備之后,小沈開始著手修改漱抓。年輕人嘛表锻,容易沖動,不僅修復(fù)了老王的 bug乞娄,還把這部分代碼進行了重構(gòu)瞬逊,使用了前兩天剛剛從書里學(xué)會的策略模式,去掉了一些不必要 if else 邏輯仪或。小沈瀟灑的摸了摸自己稀疏的頭發(fā)确镊,得意的準(zhǔn)備提交代碼,想著第一天剛來就秀了下自己的超強的編碼能力范删。接下來可怕的事情發(fā)生了蕾域,代碼死活不能通過 lint 工具的檢測,急得他面紅耳赤,趕緊跑去問導(dǎo)師旨巷,導(dǎo)師告訴他巨缘,只要按照控制臺的 warning 修改代碼就好。小沈反駁道采呐,這個 lint 工具非讓我去掉分號若锁,我在學(xué)校的時候,老師就教我分號是必不可少的锨阿,沒有分號的代碼是不完美的地梨。導(dǎo)師無奈的笑了笑觉阅,打開了小沈的實習(xí)評分表,在團隊合作一項中勾選『較差』仰冠。

不服氣的小沈,寫了一篇博客發(fā)布到了 CSDN 上涕侈,還收獲了不少閱讀量沪停。

問:工作第一天小沈犯了哪些錯誤?

  1. 對不了解的業(yè)務(wù)代碼進行重構(gòu)裳涛,這是業(yè)務(wù)開發(fā)的大忌木张;

  2. 沒有遵守團隊規(guī)范,團隊開發(fā)帶有太強的個人情緒端三;

當(dāng)然上面都是我編的舷礼,聽說現(xiàn)在寫文章開頭都要編個故事。

lint 工具簡史

在計算機科學(xué)中郊闯,lint是一種工具的名稱妻献,它用來標(biāo)記代碼中,某些可疑的团赁、不具結(jié)構(gòu)性(可能造成bug)的語句育拨。它是一種靜態(tài)程序分析工具,最早適用于C語言欢摄,在UNIX平臺上開發(fā)出來熬丧。后來它成為通用術(shù)語,可用于描述在任何一種編程語言中怀挠,用來標(biāo)記代碼中有疑義語句的工具析蝴。— by wikipedia

在 JavaScript 20 多年的發(fā)展歷程中绿淋,也出現(xiàn)過許許多多的 lint 工具闷畸,下面就來介紹下主流的三款 lint 工具。

  1. JSLint

  2. JSHint

  3. ESLint

JSLint

JSLint 可以說是最早出現(xiàn)的 JavaScript 的 lint 工具吞滞,由 Douglas Crockford (《JavaScript 語言精粹》作者) 開發(fā)佑菩。從《JavaScript 語言精粹》的筆風(fēng)就能看出,Douglas 是個眼里容不得瑕疵的人,所以 JSLint 也繼承了這個特色倘待,JSLint 的所有規(guī)則都是由 Douglas 自己定義的疮跑,可以說這是一個極具 Douglas 個人風(fēng)格的 lint 工具,如果你要使用它凸舵,就必須接受它所有規(guī)則祖娘。值得稱贊的是,JSLint 依然在更新啊奄,而且也提供了 node 版本:node-jslint渐苏。

JSHint

由于 JSLint 讓很多人無法忍受它的規(guī)則,感覺受到了壓迫菇夸,所以 Anton Kovalyov (現(xiàn)在在 Medium 工作) 基于 JSLint 開發(fā)了 JSHint琼富。JSHint 在 JSLint 的基礎(chǔ)上提供了豐富的配置項,給了開發(fā)者極大的自由庄新,JSHint 一開始就保持著開源軟件的風(fēng)格鞠眉,由社區(qū)進行驅(qū)動,發(fā)展十分迅速择诈。早期 jQuery 也是使用 JSHint 進行代碼檢查的械蹋,不過現(xiàn)在已經(jīng)轉(zhuǎn)移到 ESLint 了。

ESLint

ESLint 由 Nicholas C. Zakas (《JavaScript 高級程序設(shè)計》作者) 于2013年6月創(chuàng)建羞芍,它的出現(xiàn)因為 Zakas 想使用 JSHint 添加一條自定義的規(guī)則哗戈,但是發(fā)現(xiàn) JSHint 不支持,于是自己開發(fā)了一個荷科。

ESLint 號稱下一代的 JS Linter 工具唯咬,它的靈感來源于 PHP Linter,將源代碼解析成 AST畏浆,然后檢測 AST 來判斷代碼是否符合規(guī)則胆胰。ESLint 使用 esprima 將源代碼解析吃成 AST,然后你就可以使用任意規(guī)則來檢測 AST 是否符合預(yù)期刻获,這也是 ESLint 高可擴展性的原因煮剧。

但是,那個時候 ESLint 并沒有大火将鸵,因為需要將源代碼轉(zhuǎn)成 AST,運行速度上輸給了 JSHint 佑颇,并且 JSHint 當(dāng)時已經(jīng)有完善的生態(tài)(編輯器的支持)顶掉。真正讓 ESLint 大火是因為 ES6 的出現(xiàn)。

ES6 發(fā)布后挑胸,因為新增了很多語法痒筒,JSHint 短期內(nèi)無法提供支持,而 ESLint 只需要有合適的解析器就能夠進行 lint 檢查。這時 babel 為 ESLint 提供了支持簿透,開發(fā)了 babel-eslint移袍,讓ESLint 成為最快支持 ES6 語法的 lint 工具。

在 2016 年老充,ESLint整合了與它同時誕生的另一個 lint 工具:JSCS葡盗,因為它與 ESLint 具有異曲同工之妙,都是通過生成 AST 的方式進行規(guī)則檢測啡浊。

自此觅够,ESLint 在 JS Linter 領(lǐng)域一統(tǒng)江湖,成為前端界的主流工具巷嚣。

Lint 工具的意義

下面一起來思考一個問題:Lint 工具對工程師來說到底是代碼質(zhì)量的保證還是一種束縛喘先?

然后,我們再看看 ESLint 官網(wǎng)的簡介:

代碼檢查是一種靜態(tài)的分析廷粒,常用于尋找有問題的模式或者代碼窘拯,并且不依賴于具體的編碼風(fēng)格。對大多數(shù)編程語言來說都會有代碼檢查坝茎,一般來說編譯程序會內(nèi)置檢查工具涤姊。

JavaScript 是一個動態(tài)的弱類型語言,在開發(fā)中比較容易出錯景东。因為沒有編譯程序砂轻,為了尋找 JavaScript 代碼錯誤通常需要在執(zhí)行過程中不斷調(diào)試。像 ESLint 這樣的可以讓程序員在編碼的過程中發(fā)現(xiàn)問題而不是在執(zhí)行的過程中斤吐。

因為 JavaScript 這門神奇的語言搔涝,在帶給我們靈活性的同時,也埋下了一些坑和措。比如 == 涉及到的弱類型轉(zhuǎn)換庄呈,著實讓人很苦惱,還有 this 的指向派阱,也是一個讓人迷惑的東西诬留。而 Lint 工具就很好的解決了這個問題,干脆禁止你使用 == 贫母,這種做法雖然限制了語言的靈活性文兑,但是帶來的收益也是可觀的。

還有就是作為一門動態(tài)語言腺劣,因為缺少編譯過程绿贞,有些本可以在編譯過程中發(fā)現(xiàn)的錯誤,只能等到運行才發(fā)現(xiàn)橘原,這給我們調(diào)試工作增加了一些負擔(dān)籍铁,而 Lint 工具相當(dāng)于為語言增加了編譯過程涡上,在代碼運行前進行靜態(tài)分析找到出錯的地方。

所以匯總一下拒名,Lint工具的優(yōu)勢:

  1. 避免低級bug吩愧,找出可能發(fā)生的語法錯誤。使用未聲明變量增显、修改 const 變量……

  2. 提示刪除多余的代碼雁佳。聲明而未使用的變量、重復(fù)的 case ……

  3. 確保代碼遵循最佳實踐甸怕「蚀可參考 airbnb style、javascript standard

  4. 統(tǒng)一團隊的代碼風(fēng)格梢杭。加不加分號温兼?使用 tab 還是空格?

使用方式

說了那么多武契,還是來看下有點實際意義的募判,ESLint 到底是如何使用的。

初始化

如果想在現(xiàn)有項目中引入 ESLint咒唆,可以直接運行下面的命令:

# 全局安裝 
ESLint$ npm install -g eslint
# 進入項目
$ cd ~/Code/ESLint-demo
# 初始化 package.json
$ npm init -f
# 初始化 ESLint 配置
$ eslint --init

在使用 eslint —init 后届垫,會出現(xiàn)很多用戶配置項,具體可以參考:eslint cli 部分的源碼全释。

經(jīng)過一系列一問一答的環(huán)節(jié)后装处,你會發(fā)現(xiàn)在你文件夾的根目錄生成了一個 .eslintrc.js 文件。

配置方式

ESLint 一共有兩種配置方式:

  1. 使用注釋把 lint 規(guī)則直接嵌入到源代碼中

這是最簡單粗暴的方式浸船,直接在源代碼中使用 ESLint 能夠識別的注釋方式妄迁,進行 lint 規(guī)則的定義。

/* eslint eqeqeq: "error" */ 
var num = 1num == '1'

當(dāng)然我們一般使用注釋是為了臨時禁止某些嚴格的 lint 規(guī)則出現(xiàn)的警告:

/* eslint-disable */alert('該注釋放在文件頂部李命,整個文件都不會出現(xiàn) lint 警告')
/* eslint-enable */alert('重新啟用 lint 告警')
/* eslint-disable eqeqeq */alert('只禁止某一個或多個規(guī)則')
/* eslint-disable-next-line */
alert('當(dāng)前行禁止 lint 警告')
alert('當(dāng)前行禁止 lint 警告') // eslint-disable-line
  1. 使用配置文件進行 lint 規(guī)則配置

在初始化過程中登淘,有一個選項就是使用什么文件類型進行 lint 配置(What format do you want your config file to be in?):

{    
 type: "list",   
 name: "format",   
 message: "What format do you want your config file to be in?",   
 default: "JavaScript",
 choices: ["JavaScript", "YAML", "JSON"]
}

官方一共提供了三個選項:

  1. JavaScript (eslintrc.js)

  2. YAML (eslintrc.yaml)

  3. JSON (eslintrc.json)

另外,你也可以自己在 package.json 文件中添加 eslintConfig 字段進行配置封字。

翻閱 ESLint 源碼可以看到黔州,其配置文件的優(yōu)先級如下:

const configFilenames = 
[  ".eslintrc.js",  ".eslintrc.yaml",  ".eslintrc.yml",  ".eslintrc.json",  ".eslintrc",  "package.json"];
.eslintrc.js > .eslintrc.yaml  > .eslintrc.yml > .eslintrc.json > .eslintrc > package.json

當(dāng)然你也可以使用 cli 自己指定配置文件路徑:

項目級與目錄級的配置

我們有如下目錄結(jié)構(gòu),此時在根目錄運行 ESLint阔籽,那么我們將得到兩個配置文件 .eslintrc.js(項目級配置) 和 src/.eslintrc.js(目錄級配置)流妻,這兩個配置文件會進行合并,但是 src/.eslintrc.js 具有更高的優(yōu)先級笆制。

但是绅这,我們只要在 src/.eslintrc.js 中配置 “root”: true,那么 ESLint 就會認為 src 目錄為根目錄项贺,不再向上查找配置君躺。

{ "root": true}

配置參數(shù)

下面我們一起來細細品味 ESLinte 的配置規(guī)則。

解析器配置
{
  // 解析器類型
  // espima(默認), babel-eslint, @typescript-eslint/parse
  "parse": "esprima",
  // 解析器配置參數(shù)
  "parseOptions": {
   // 代碼類型:script(默認), module
   "sourceType": "script",
   // es 版本號开缎,默認為 5棕叫,也可以是用年份,比如 2015 (同 6)
   "ecamVersion": 6,
   // es 特性配置
   "ecmaFeatures": {
        "globalReturn": true, // 允許在全局作用域下使用 return 語句
        "impliedStrict": true, // 啟用全局 strict mode
        "jsx": true // 啟用 JSX
   },
}}

對于 @typescript-eslint/parse 這個解析器奕删,主要是為了替代之前存在的 TSLint俺泣,TS 團隊因為 ESLint 生態(tài)的繁榮,且 ESLint 具有更多的配置項完残,不得不拋棄 TSLint 轉(zhuǎn)而實現(xiàn)一個 ESLint 的解析器伏钠。同時,該解析器擁有<a >不同的配置:

{
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "useJSXTextNode": true,
    "project": "./tsconfig.json",
    "tsconfigRootDir": "../../",
    "extraFileExtensions": [".vue"]
  }}
環(huán)境與全局變量

ESLint 會檢測未聲明的變量谨设,并發(fā)出警告熟掂,但是有些變量是我們引入的庫聲明的,這里就需要提前在配置中聲明扎拣。

{
  "globals": {
    // 聲明 jQuery 對象為全局變量
    "$": false // true表示該變量為 writeable赴肚,而 false 表示 readonly
  }}

在 globals 中一個個的進行聲明未免有點繁瑣,這個時候就需要使用到 env 二蓝,這是對一個環(huán)境定義的一組全局變量的預(yù)設(shè)(類似于 babel 的 presets)誉券。

{
  "env": {
    "amd": true,
    "commonjs": true,
    "jquery": true
  }
}

可選的環(huán)境很多,預(yù)設(shè)值都在這個文件中進行定義刊愚,查看源碼可以發(fā)現(xiàn)踊跟,其預(yù)設(shè)變量都引用自 globals 包。

規(guī)則設(shè)置

ESLint 附帶有大量的規(guī)則鸥诽,你可以在配置文件的 rules 屬性中配置你想要的規(guī)則商玫。每一條規(guī)則接受一個參數(shù),參數(shù)的值如下:

  • “off” 或 0:關(guān)閉規(guī)則

  • “warn” 或 1:開啟規(guī)則衙传,warn 級別的錯誤 (不會導(dǎo)致程序退出)

  • “error” 或 2:開啟規(guī)則决帖,error級別的錯誤(當(dāng)被觸發(fā)的時候,程序會退出)

舉個例子蓖捶,我們先寫一段使用了平等(equality)的代碼地回,然后對 eqeqeq 規(guī)則分別進行不同的配置。

// demo.js
var num = 1
num == '1'

這里使用了命令行的配置方式俊鱼,如果你只想對單個文件進行某個規(guī)則的校驗就可以使用這種方式刻像。

但是,事情往往沒有我們想象中那么簡單并闲,ESLint 的規(guī)則不僅只有關(guān)閉和開啟這么簡單细睡,每一條規(guī)則還有自己的配置項。如果需要對某個規(guī)則進行配置帝火,就需要使用數(shù)組形式的參數(shù)溜徙。

我們看下 quotes 規(guī)則湃缎,根據(jù)官網(wǎng)介紹,它支持字符串和對象兩個配置項蠢壹。

{
  "rules": {
    // 使用數(shù)組形式嗓违,對規(guī)則進行配置
    // 第一個參數(shù)為是否啟用規(guī)則
    // 后面的參數(shù)才是規(guī)則的配置項
    "quotes": [
      "error",
      "single",
      {
        "avoidEscape": true 
      }
    ]
  }
}

根據(jù)上面的規(guī)則:

// bad 
var str = "test 'ESLint' rule"
// good
var str = 'test "ESLint" rule'

擴展

擴展就是直接使用別人已經(jīng)寫好的 lint 規(guī)則,方便快捷图贸。擴展一般支持三種類型:

{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "eslint-config-standard",
  ]
}
  • eslint: 開頭的是 ESLint 官方的擴展蹂季,一共有兩個:eslint:recommended 、eslint:all疏日。

  • plugin: 開頭的是擴展是插件類型偿洁,也可以直接在 plugins 屬性中進行設(shè)置,后面一節(jié)會詳細講到沟优。

  • 最后一種擴展來自 npm 包涕滋,官方規(guī)定 npm 包的擴展必須以 eslint-config- 開頭,使用時可以省略這個頭净神,上面案例中 eslint-config-standard 可以直接簡寫成 standard何吝。

如果你覺得自己的配置十分滿意,也可以將自己的 lint 配置發(fā)布到 npm 包鹃唯,只要將包名命名為 eslint-config-xxx 即可爱榕,同時,需要在 package.json 的 peerDependencies 字段中聲明你依賴的 ESLint 的版本號坡慌。

插件

使用插件

雖然官方提供了上百種的規(guī)則可供選擇黔酥,但是這還不夠,因為官方的規(guī)則只能檢查標(biāo)準(zhǔn)的 JavaScript 語法洪橘,如果你寫的是 JSX 或者 Vue 單文件組件跪者,ESLint 的規(guī)則就開始束手無策了。

這個時候就需要安裝 ESLint 的插件熄求,來定制一些特定的規(guī)則進行檢查渣玲。ESLint 的插件與擴展一樣有固定的命名格式,以 eslint-plugin- 開頭弟晚,使用的時候也可以省略這個頭忘衍。

npm install --save-dev eslint-plugin-vue eslint-plugin-react
{
  "plugins": [
    "react", // eslint-plugin-react
    "vue",   // eslint-plugin-vue
  ]
}

或者是在擴展中引入插件,前面有提到 plugin: 開頭的是擴展是進行插件的加載卿城。

{
  "extends": [
    "plugin:react/recommended",
  ]
}

通過擴展的方式加載插件的規(guī)則如下:

extPlugin = `plugin:${pluginName}/${configName}`

對照上面的案例枚钓,插件名(pluginName) 為 react,也就是之前安裝 eslint-plugin-react 包瑟押,配置名(configName)為 recommended搀捷。那么這個配置名又是從哪里來的呢?

可以看到 eslint-plugin-react 的源碼多望。

module.exports = {
  // 自定義的 rule
  rules: allRules,
  // 可用的擴展
  configs: {
    // plugin:react/recommended
    recomended: {
      plugins: [ 'react' ]
      rules: {...}
    },
    // plugin:react/all
    all: {
      plugins: [ 'react' ]
      rules: {...}
    }
  }
}

配置名是插件配置的 configs 屬性定義的嫩舟,這里的配置其實就是 ESLint 的擴展氢烘,通過這種方式即可以加載插件,又可以加載擴展家厌。

開發(fā)插件

ESLint 官方為了方便開發(fā)者威始,提供了 Yeoman 的模板(generator-eslint)。

# 安裝模塊
npm install -g yo generator-eslint

# 創(chuàng)建目錄
mkdir eslint-plugin-demo
cd eslint-plugin-demo

# 創(chuàng)建模板
yo eslint:plugin

創(chuàng)建好項目之后像街,就可以開始創(chuàng)建一條規(guī)則了,幸運的是 generator-eslint 除了能夠生成插件的模板代碼外晋渺,還具有創(chuàng)建規(guī)則的模板代碼镰绎。打開之前創(chuàng)建的 eslint-plugin-demo 文件夾,在該目錄下添加一條規(guī)則木西,我希望這條規(guī)則能檢測出我的代碼里面是否有 console 畴栖,所以,我給該規(guī)則命名為 disable-console八千。

yo eslint:rule

接下來我們看看如何來指定 ESLinte 的一個規(guī)則:

打開 lib/rules/disable-console.js 吗讶,可以看到默認的模板代碼如下:

module.exports = {
  meta: {
    docs: {
      description: "disable console",
      category: "Fill me in",
      recommended: false
    },
    schema: []
  },
  create: function (context) {
    // variables should be defined here
    return {
      // give me methods
    };
  }
};

簡單的介紹下其中的參數(shù)(更詳細的介紹可以查看官方文檔):

  • meta:規(guī)則的一些描述信息

  • descrition(string):規(guī)則的簡短描述

  • category(string):規(guī)則的類別(具體類別可以查看官網(wǎng))

  • recommended(boolean):是否加入 eslint:recommended

  • docs:規(guī)則的描述對象

  • schema(array):規(guī)則所接受的配置項

  • create:返回一個對象,該對象包含 ESLint 在遍歷 JavaScript 代碼 AST 時恋捆,所觸發(fā)的一系列事件勾子照皆。

在詳細講解如何創(chuàng)建一個規(guī)則之前,我們先來談?wù)?AST(抽象語法樹)沸停。ESLint 使用了一個叫做 Espree 的 JavaScript 解析器來把 JavaScript 代碼解析為一個 AST 膜毁。然后深度遍歷 AST,每條規(guī)則都會對匹配的過程進行監(jiān)聽愤钾,每當(dāng)匹配到一個類型瘟滨,相應(yīng)的規(guī)則就會進行檢查。為了方便查看 AST 的各個節(jié)點類型能颁,這里提供一個網(wǎng)站能十分清晰的查看一段代碼解析成 AST 之后的樣子:astexplorer杂瘸。如果你想找到所有 AST 節(jié)點的類型,可以查看 estree伙菊。

可以看到 console.log() 屬于 ExpressionStatement(表達式語句) 中的 CallExpression(調(diào)用語句)败玉。

{
  "type": "ExpressionStatement",
  "expression": {
    "type": "CallExpression",
    "callee": {
      "type": "MemberExpression",
      "object": {
        "type": "Identifier",
        "name": "console"
      },
      "property": {
        "type": "Identifier",
        "name": "log"
      },
      "computed": false
    }
  }
}

所以,我們要判斷代碼中是否調(diào)用了 console占业,可以在 create 方法返回的對象中绒怨,寫一個 CallExpression 方法,在 ESLint 遍歷 AST 的過程中谦疾,對調(diào)用語句進行監(jiān)聽南蹂,然后檢查該調(diào)用語句是否為 console 調(diào)用。

module.exports = {
  create: function(context) {
    return {
      CallExpression(node) {
        // 獲取調(diào)用語句的調(diào)用對象
        const callObj = node.callee.object
        if (!callObj) {
          return
        }
        if (callObj.name === 'console') {
          // 如果調(diào)用對象為 console念恍,通知 ESLint
          context.report({
            node,
            message: 'error: should remove console'
          })
        }
      },
    }
  }
}

可以看到我們最后通過 context.report 方法六剥,告訴 ESLint 這是一段有問題的代碼晚顷,具體要怎么處理,就要看 ESLint 配置中疗疟,該條規(guī)則是 [off, warn, error] 中的哪一個了该默。

之前介紹規(guī)則的時候,有講到規(guī)則是可以接受配置的策彤,下面看看我們自己制定規(guī)則的時候栓袖,要如何接受配置項。其實很簡單店诗,只需要在 mate 對象的 schema 中定義好參數(shù)的類型裹刮,然后在 create 方法中,通過 context.options 獲取即可庞瘸。下面對 disable-console 進行修改捧弃,畢竟禁止所有的 console 太過嚴格,我們可以添加一個參數(shù)擦囊,該參數(shù)是一個數(shù)組违霞,表示允許調(diào)用的 console 方法。

module.exports = {
  meta: {
    docs: {
      description: "disable console", // 規(guī)則描述
      category: "Possible Errors",    // 規(guī)則類別
      recommended: false
    },
    schema: [ // 接受一個參數(shù)
      {
        type: 'array', // 接受參數(shù)類型為數(shù)組
        items: {
          type: 'string' // 數(shù)組的每一項為一個字符串
        }
      }
    ]
  },

  create: function(context) {
    const logs = [ // console 的所以方法
        "debug", "error", "info", "log", "warn", 
        "dir", "dirxml", "table", "trace", 
        "group", "groupCollapsed", "groupEnd", 
        "clear", "count", "countReset", "assert", 
        "profile", "profileEnd", 
        "time", "timeLog", "timeEnd", "timeStamp", 
        "context", "memory"
    ]
    return {
      CallExpression(node) {
         // 接受的參數(shù)
        const allowLogs = context.options[0]
        const disableLogs = Array.isArray(allowLogs)
          // 過濾掉允許調(diào)用的方法
          ? logs.filter(log => !allowLogs.includes(log))
          : logs
        const callObj = node.callee.object
        const callProp = node.callee.property
        if (!callObj || !callProp) {
          return
        }
        if (callObj.name !== 'console') {
          return
        }
        // 檢測掉不允許調(diào)用的 console 方法
        if (disableLogs.includes(callProp.name)) {
          context.report({
            node,
            message: 'error: should remove console'
          })
        }
      },
    }
  }}

規(guī)則寫完之后瞬场,打開 tests/rules/disable-console.js 买鸽,編寫測試用例。

var rule = require("../../../lib/rules/disable-console")var RuleTester = require("eslint").RuleTestervar ruleTester = new RuleTester()
ruleTester.run("disable-console", rule, {
  valid: [{
    code: "console.info(test)",
    options: [['info']]
  }],
  invalid: [{
    code: "console.log(test)",
    errors: [{ message: "error: should remove console" }]
  }]});

最后贯被,只需要引入插件癞谒,然后開啟規(guī)則即可。

// eslintrc.js
module.exports = {
  plugins: [ 'demo' ],
  rules: {
    'demo/disable-console': [
      'error', [ 'info' ]
    ],
  }}

最佳配置

業(yè)界有許多 JavaScript 的推薦編碼規(guī)范刃榨,較為出名的就是下面兩個:

  1. airbnb style

  2. javascript standard

同時這里也推薦 AlloyTeam 的 eslint-config-alloy弹砚。

但是代碼規(guī)范這個東西,最好是團隊成員之間一起來制定枢希,確保大家都能夠接受桌吃,如果實在是有人有異議,就只能少數(shù)服從多數(shù)了苞轿。雖然這節(jié)的標(biāo)題叫最佳配置茅诱,但是軟件行業(yè)并有沒有什么方案是最佳方案,即使 javascript standard 也不是 javascript 標(biāo)準(zhǔn)的編碼規(guī)范搬卒,它僅僅只是叫這個名字而已瑟俭,只有適合的才是最好的。

最后安利一下契邀,將 ESLint 和 Prettier 結(jié)合使用摆寄,不僅統(tǒng)一編碼規(guī)范,也能統(tǒng)一代碼風(fēng)格。具體實踐方式微饥,請參考我的文章:使用ESLint+Prettier來統(tǒng)一前端代碼風(fēng)格逗扒。

總結(jié)

看到這里我們做一個總結(jié),JavaScript 的 linter 工具發(fā)展歷史其實也不算短欠橘,ESLint 之所以能夠后來者居上矩肩,主要原因還是 JSLint 和 JSHint 采用自頂向下的方式來解析代碼,并且早期 JavaScript 語法萬年不更新肃续,能這種方式夠以較快的速度來解析代碼黍檩,找到可能存在的語法錯誤和不規(guī)范的代碼。但是 ES6 發(fā)布之后始锚,JavaScript 語法發(fā)生了很多的改動建炫,比如:箭頭函數(shù)、模板字符串疼蛾、擴展運算符……,這些語法的發(fā)布艺配,導(dǎo)致 JSLint 和 JSHint 如果不更新解析器就沒法檢測 ES6 的代碼察郁。而 ESLint 另辟蹊徑,采用 AST 的方式對代碼進行靜態(tài)分析转唉,并保留了強大的可擴展性和靈活的配置能力皮钠。這也告訴我們,在日常的編碼過程中赠法,一定要考慮到后續(xù)的擴展能力麦轰。

正是因為這個強大擴展能力,讓業(yè)界的很多 JavaScript 編碼規(guī)范能夠在各個團隊進行快速的落地砖织,并且團隊自己定制的代碼規(guī)范也可以對外共享款侵。

最后,希望你通過上面的學(xué)習(xí)已經(jīng)理解了 ESLint 帶來的好處侧纯,同時掌握了 ESLint 的用法新锈,并可以為現(xiàn)有的項目引入 ESLint 改善項目的代碼質(zhì)量。

參考

  • ESLint 官網(wǎng)

  • JS Linter 進化史

  • ESLint 工作原理探討

作者:自然醒
原文地址:https://mp.weixin.qq.com/s/BD827cLWrPNtMgDvGgi0qg

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眶熬,一起剝皮案震驚了整個濱河市妹笆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娜氏,老刑警劉巖拳缠,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贸弥,居然都是意外死亡窟坐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狸涌,“玉大人切省,你說我怎么就攤上這事∨恋ǎ” “怎么了朝捆?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長懒豹。 經(jīng)常有香客問我芙盘,道長,這世上最難降的妖魔是什么脸秽? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任儒老,我火速辦了婚禮,結(jié)果婚禮上记餐,老公的妹妹穿的比我還像新娘驮樊。我一直安慰自己,他們只是感情好片酝,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布囚衔。 她就那樣靜靜地躺著,像睡著了一般雕沿。 火紅的嫁衣襯著肌膚如雪练湿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天审轮,我揣著相機與錄音肥哎,去河邊找鬼。 笑死疾渣,一個胖子當(dāng)著我的面吹牛篡诽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播榴捡,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼霞捡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了薄疚?” 一聲冷哼從身側(cè)響起碧信,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎街夭,沒想到半個月后砰碴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡板丽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年呈枉,在試婚紗的時候發(fā)現(xiàn)自己被綠了趁尼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡猖辫,死狀恐怖酥泞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啃憎,我是刑警寧澤芝囤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站辛萍,受9級特大地震影響悯姊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贩毕,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一悯许、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辉阶,春花似錦先壕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至店印,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間倒慧,已是汗流浹背按摘。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纫谅,地道東北人炫贤。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像付秕,于是被迫代替她去往敵國和親兰珍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一询吴、JSLint JSHint ESLint 參考前端工具考 - ESLint 篇JS Linter 進化史 C ...
    合肥黑閱讀 76,658評論 0 47
  • EsLint入門學(xué)習(xí)整理 這兩天因為公司要求掠河,就對ESLint進行了初步的了解,網(wǎng)上的內(nèi)容基本上都差不多猛计,但是內(nèi)容...
    點柈閱讀 26,027評論 3 42
  • 兩個月之前在項目中就開始使用 Eslint 唠摹,當(dāng)時直接 copy 別人的 .eslintrc.js 文件,感覺好復(fù)...
    dkvirus閱讀 111,970評論 33 190
  • 17-11-27星期一07:3霧霾天 最后的沖刺奉瘤,拼啊—— 17-11-29星期三09:05霧霾 繼續(xù)加油 17-...
    魏雨self閱讀 193評論 0 0
  • 相對而言勾拉,在讀書、旅行、音樂藕赞、香薰成肘、飲茶、電影等等這些小胡格外喜愛的內(nèi)容里斧蜕,電影双霍,一直都是我以為可以輕松獲得...
    胡月琦Sierra閱讀 277評論 0 1