eslint 與 prettier 實現代碼規范自動格式化
今天早上來看了一篇文章,一直煩惱prettier的設置,這篇文章寫的比較不錯,就直接down下來了。 該文首發於https://vsnail.cn/static/doc/blog/eslintPrettier.html
其實很早之前就想在工程中使用 eslint
和 prettier
來規范代碼。可是 eslint
和 prettier
的相愛相殺,再加上框架(vue
,react
)的特有寫法(jsx
,template
)等等總是讓自己開發過程很痛苦,很懵逼,不知所措。所以每次都啟用 esint
,然后又禁用,又啟用,又禁用,如此反復,周而復始。 前段時間看前端工程化相關的資料,發現其實工程代碼格式規范是其中重要的環節之一。顧而,借着周末好好捋一捋 eslint
和 prettier
,來達到開發的高效和規范。
在代碼規范的道路上,我們終極目標是:
團隊中的所有開發人員用一套代碼規范規則,並且無需我們花太大的精力去為了格式而格式。希望有一套自動化工具,幫我們檢測代碼是否規范,如果不規范,則自動能夠幫我們按照既定規范格式化。
通過對 eslint
和 prettier
的大致了解,其實可以發現,prettier
是用於格式化代碼的。而代碼規范規則的設置和代碼上的 warn
,error
等提醒,則是 eslint
來實現的。故而,我們的大目標應該是 eslint
,然后把 prettier
集成進來。
ESLint
ESLint
是一個開源的JavaScript
代碼檢查工具,由 Nicholas C. Zakas 於 2013 年 6 月創建。代碼檢查是一種靜態的分析,常用於尋找有問題的模式或者代碼,並且不依賴於具體的編碼風格。對大多數編程語言來說都會有代碼檢查,一般來說編譯程序會內置檢查工具。
ESLint
的所有規則都被設計成可插入的。ESLint
的默認規則與其他的插件並沒有什么區別,規則本身和測試可以依賴於同樣的模式。 因此可配置、插件式是 ESLint
的最大特點,也是我們熱衷使用它的原因。
如何配置
配置 ESLint
有兩種方式:
- 使用
JavaScript
注釋把配置信息直接嵌入到一個代碼源文件中 - 配置文件式
這兩種方式中,“配置文件”是最常見的配置方式。使用 JavaScript
、JSON
或者 YAML
文件為整個目錄(處理你的主目錄)和它的子目錄指定配置信息。ESLint
會查找和自動讀取它們,再者,你可以在命令行運行時指定一個任意的配置文件。
ESLint
支持幾種格式的配置文件:
JavaScript
- 使用.eslintrc.js
然后輸出一個配置對象。YAML
- 使用.eslintrc.yaml
或.eslintrc.yml
去定義配置的結構。JSON
- 使用.eslintrc.json
去定義配置的結構,ESLint
的JSON
文件允許JavaScript
風格的注釋。- (棄用) - 使用
.eslintrc
,可以使JSON
也可以是 YAML。 package.json
- 在package.json
里創建一個eslintConfig
屬性,在那里定義你的配置。
如果同一個目錄下有多個配置文件,ESLint
只會使用一個。優先級順序如下:
.eslintrc.js
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
.eslintrc
package.json
由於 js 里面可以很方便的書寫邏輯,並且它的優先級又比較高,故而建議使用 js 文件來當作配置文件。
這些配置啥意思
可配置是 ESLint
的特點之一。也就意味着我們必須了解每個配置項什么意思,才能玩轉 ESLint
。因此接下來我們來看看常用配置項是什么意思。
Parser
ESLint
默認使用 Espree 作為其解析器,你可以在配置文件中指定一個不同的解析器.
以下解析器與 ESLint
兼容:
- Esprima
- Babel-ESLint - 一個對 Babel 解析器的包裝,使其能夠與
ESLint
兼容。 - typescript-eslint-parser(實驗) - 一個把 TypeScript 轉換為 ESTree 兼容格式的解析器,這樣它就可以在
ESLint
中使用了。這樣做的目的是通過ESLint
來解析 TypeScript 文件(盡管不一定必須通過所有的ESLint
規則)。 注意,在使用自定義解析器時,為了讓ESLint
在處理非ECMAScript 5
特性時正常工作,配置屬性parserOptions
仍然是必須的。解析器會被傳入parserOptions
,但是不一定會使用它們來決定功能特性的開關。
parserOptions
這個屬性常用於設置語法解析器的一些配置。可用的選項有:
-
ecmaVersion
: 制定ECMAScript
的版本。
默認設置為 3,5(默認), 你可以使用 6、7、8 或 9 來指定你想要使用的 ECMAScript
版本。你也可以用使用年份命名的版本號指定為 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)
-
sourceType
: 源碼類型
設置為 "script
" (默認) 或 "module
"(如果你的代碼是 ECMAScript
模塊)。
-
ecmaFeatures
: 這是個對象,表示你想使用的額外的語言特性:
- 3.1
globalReturn
- 允許在全局作用域下使用return
語句 - 3.2
impliedStrict
- 啟用全局 strict mode (如果ecmaVersion
是 5 或更高) - 3.3
jsx
- 啟用JSX
- 3.4
experimentalObjectRestSpread
- 啟用實驗性的object rest
/spread properties
支持。(重要:這是一個實驗性的功能,在未來可能會有明顯改變。 建議你寫的規則 不要 依賴該功能,除非當它發生改變時你願意承擔維護成本。)
設置解析器選項能幫助
ESLint
確定什么是解析錯誤,所有語言選項默認都是false
Environments
該配置屬性定義來一組預定義的全局變量。可用的環境包括:
browser
- 瀏覽器環境中的全局變量。node
-Node.js
全局變量和Node.js
作用域。commonjs
-CommonJS
全局變量和CommonJS
作用域 (用於Browserify/WebPack
打包的只在瀏覽器中運行的代碼)。shared-node-browser
-Node.js
和Browser
通用全局變量。es6
- 啟用除了modules
以外的所有ECMAScript 6
特性(該選項會自動設置ecmaVersion
解析器選項為 6)。worker
-Web Workers
全局變量。amd
- 將require()
和define()
定義為像amd
一樣的全局變量。mocha
- 添加所有的Mocha
測試全局變量。jasmine
- 添加所有的Jasmine
版本 1.3 和 2.0 的測試全局變量。jest
-Jest
全局變量。phantomjs
-PhantomJS
全局變量。protractor
-Protractor
全局變量。qunit
-QUnit
全局變量。jquery
-jQuery
全局變量。prototypejs
-Prototype.js
全局變量。shelljs
-ShellJS
全局變量。meteor
-Meteor
全局變量。mongo
-MongoDB
全局變量。applescript
-AppleScript
全局變量。nashorn
-Java 8 Nashorn
全局變量。serviceworker
-Service Worker
全局變量。atomtest
-Atom
測試全局變量。embertest
-Ember
測試全局變量。webextensions
-WebExtensions
全局變量。greasemonkey
-GreaseMonkey
全局變量。 這些環境並不是互斥的,所以你可以同時定義多個。
Globals
我們使用第三方提供的全局變量的時候(例如:jQuery
,AMap
等對象),ESLint
並不能識別他們,總是會報錯。這個時候,該配置的作用就出現了。使用 globals
指出你要使用的全局變量。將變量設置為 true
將允許變量被重寫,或 false
將不允許被重寫。
Plugins
ESLint
支持使用第三方插件。在使用插件之前,你必須使用包管理工具安裝它。 在配置文件里配置插件時,可以使用 plugins
關鍵字來存放插件名字的列表。插件名稱可以省略 eslint-plugin-
前綴。
Rules
ESLint
附帶有大量的規則。你可以使用注釋或配置文件修改你項目中要使用的規則。要改變一個規則設置,你必須將規則 ID 設置為off
、warn
、error
三者之一。
繼承配置文件
基本要用的配置屬性在上面都已經涉及到了。但是我們之前講過 ESLint
不僅有可配性,還有插件的可插拔性。那么插件又是如何工作的呢?插件無外乎是增強某些功能,並且對外提供接口。在 ESLint
中,插件一般都是通過繼承的方式,來實現對外提供特定功能。
extends
一個配置文件可以從基礎配置中繼承已啟用的規則。
extends
屬性值可以是:
(1)、在配置中指定的一個字符串
(2)、字符串數組:每個配置繼承它前面的配置
ESLint
遞歸地進行擴展配置,所以一個基礎的配置也可以有一個 extends
屬性。
extends
里面可以引入 共享配置包,可以引入 插件
- 共享配置包
可共享的配置 是一個 npm
包,它輸出一個配置對象。
extends
屬性值可以省略包名的前綴 eslint-config-。
- 插件
插件 是一個 npm
包,通常輸出規則。一些插件也可以輸出一個或多個命名的 配置。
plugins
屬性值 可以省略包名的前綴 eslint-plugin-
。
extends
屬性值可以由以下組成:
(1)、plugin
: (2)、包名 (省略了前綴,比如,react
) (3)、/ (4)、配置名稱 (比如 recommended
)
Prettier
Prettier
是一個代碼格式化工具。能夠按照我們的規則,將我們的代碼格式化。
為什么我們用它,而不用其他的代碼格式化工具呢?Prettier 主要有以下優點:
- 可配置化
- 支持多種語言
- 集成多數的編輯器
- 簡潔的配置項
ESLint
+ Prettier
團隊中的所有開發人員用一套代碼規范規則,並且無需我們花太大的精力去為了格式而格式。希望有一套自動化工具,幫我們檢測代碼是否規范,如果不規范,則自動能夠幫我們按照既定規范格式化。------我們的終極目標
通過上面的了解,要想達到我們的終極目標似乎就是將這兩個一起使用即可。那么如何整合他們呢?
以vue
工程為例:
第一步: 下載相關包
最基本的,我們肯定要下載eslint
,prettier
這兩個包的。
其次,為了將其整合起來那么我們需要已寫好的“共享配置包”和插件。因此我們需要下載eslint-plugin-prettier
,eslint-config-prettier
。
再次,我們需要站在巨人的肩膀上看世界。也就是我們需要業界一些比較成熟的規范,來規范我們的代碼。因此我們可以使用大團隊提供的代碼規范插件。比較有名的就是airbnb
。這里我們選用的是airbnb-base
。故而我們需要下載eslint-config-airbnb-base
。
最后,為了完美使用我們 ES6 的一些新特性。我們需要將“詞法解析器”設置為babel-eslint
。因此我們還需要下載babel-eslint
.
對了,我們是vue
工程,那么肯定要有對 vue 配置的插件,因此我們需要下載eslint-plugin-vue
總結可得,我們需要下載以下包
npm install esint prettier eslint-plugin-prettier eslint-config-prettier eslint-config-airbnb-base babel-eslint eslint-plugin-vue
復制代碼
第二步 建立配置文件
如果仔細閱讀了之前eslint
的配置項,那么這一步是比較機械化的。因此我直接將工程中的配置文件拷貝過來,加以注釋吧。
在工程的根目錄,創建一個.eslintrc.js
文件,文件內容如下:
module.exports = {
env: {
browser: true,
jquery: true, //由於項目中使用來jquery。。。其實不用引入jquery的,以后有機會去掉jquery后,請移除該配置。
},
parserOptions: {
parser: 'babel-eslint', //詞法解析器使用babel-eslint,以更好的適配es6的新api
ecmaVersion: 6, //啟用 ES6 語法支持;默認設置為3,5(默認), 你可以使用 6、7、8 或 9 來指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本號指定為 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)
sourceType: 'module', //設置為 "script" (默認) 或 "module"(如果你的代碼是 ECMAScript 模塊)。
},
extends: [
'airbnb-base',
'eslint:recommended',
'plugin:vue/essential',
'plugin:prettier/recommended',
],
plugins: ['vue', 'prettier'],
rules: {
'prettier/prettier': 'error',
'generator-star-spacing': 'off',
'import/no-named-as-default': 'off',
'import/no-named-as-default-member': 'off',
'no-unused-vars': [
'error',
{ vars: 'all', args: 'none', ignoreRestSiblings: false },
], //沒有使用的參數,不會報錯。因為個人覺的把可用的參數寫上去 有利於以后的維護。
},
};
復制代碼
開發工具
其實到上一步的話,已經將ESlint
和Prettier
配置完了。但是要能夠自動格式化,那么我們還需要做一些集成。
實現自動格式化這一目標,可以在開發工具上做文章,也可以在webpack
上做文章。其實我比較傾向在開發工具上實現自動格式化,因為這樣子似乎比較快。
在開發工具中,我們希望在修改代碼保存后,能夠自動格式化代碼。如何實現這一目標呢?我們以VScode
為例
-
- 打開
VScode
的配置文件
- 打開
-
- 增加以下配置.
...
"prettier.eslintIntegration": true,
"eslint.autoFixOnSave": true,
"editor.formatOnSave": true,
//配置 ESLint 檢查的文件類型
"eslint.validate": ["javascript", "javascriptreact", "vue", "html"],
"eslint.options": {
"configFile": "./`.eslintrc`.js"
},
...
復制代碼
webpack
除了可以在開發工具上做文章,也可以在打包編譯工具上做文章,以實現自動格式化的目標。我們以webpack
為例:
因為vue
工程通常會用官方提供的腳手架,所以這里我直接上圖了,就不BB
了。(其實是時間太晚了,明天還要上班,老婆已經再催了)
后記
其實我們在代碼規范方面,利用eslint
還可以做很多很多事情。
比如,我們可以增加一個腳本,來檢測代碼是否規范。
我們也可以在git
提交前,做一次自動檢測,避免團隊中提交不規范的代碼。可以借閱code review
的一部分精力,可以把code review
的重點放在代碼邏輯本身的合理性上。
再貼一個 prettier官網鏈接 https://prettier.io/docs/en/options.html 設置就參考這里