如何快速寫出風(fēng)格統(tǒng)一的代碼(ESLint+Prettier+EditorConfig)

當(dāng)大家在公司工作時(shí),不可能永遠(yuǎn)是一個(gè)人維護(hù)一個(gè)項(xiàng)目,當(dāng)多個(gè)人參與一個(gè)項(xiàng)目,每個(gè)人寫的代碼風(fēng)格不一樣,甚至是使用的編輯器不一樣,都會(huì)導(dǎo)致最終產(chǎn)生的代碼千差萬別,后期維護(hù)項(xiàng)目的時(shí)候,如果進(jìn)行了自動(dòng)格式化代碼,則會(huì)導(dǎo)致浪費(fèi)大量的時(shí)間用來解決沖突,加大項(xiàng)目的維護(hù)難度。

那么如何能夠快速的寫出風(fēng)格統(tǒng)一的代碼成為了當(dāng)務(wù)之急。
在工程化項(xiàng)目里,最理想的方法當(dāng)然是通過借用可靈活配置的工具,實(shí)現(xiàn)自動(dòng)化解決,這里介紹的解決方案是EditorConfig+Prettier+ESLint 的組合。

  • EditorConfig: 跨編輯器和IDE編寫代碼,保持一致的簡單編碼風(fēng)格;
  • Prettier: 專注于代碼格式化的工具,美化代碼;
  • ESLint:作代碼質(zhì)量檢測(cè)、編碼風(fēng)格約束等;

EditorConfig

如果使用的是Vscode,先安裝插件 EditorConfig for vs code
然后在項(xiàng)目根目錄下新建.editorconfig文件

打開文件時(shí),EditorConfig插件會(huì)在打開的文件的目錄中以及每個(gè)父目錄中查找名為.editorconfig的文件。如果到達(dá)根文件路徑或找到root = true的EditorConfig文件,將停止對(duì).editorconfig文件的搜索。
離文件最近的配置規(guī)則生效,優(yōu)先級(jí)更高;一般在根目錄設(shè)置一個(gè)配置文件即可。
在文件開頭的root = true表示配置文件以此為準(zhǔn)

[*]表示匹配所有的文件

一、常用屬性配置

  • 1、root<boolean> : 是否是頂級(jí)配置文件,設(shè)置為true的時(shí)候才會(huì)停止搜索.editorconfig文件
  • 2、charset<"latin" | "utf-8" | "utf-8-bom" | "utf-16be" | "utf-16le"> : 文件編碼格式
  • 3、indent_style<"tab" | "space"> : 縮進(jìn)方式
  • 4、indent_size<number> : 縮進(jìn)大小
  • 5、end_of_line<"lf" | "cr" | "crlf"> : 換行符類型
  • 6、insert_final_newline<boolean> : 是否讓文件以空行結(jié)束
  • 7、trim_trailing_whitespace<boolean> : 是否刪除行尾空格
  • 8、max_line_length<number> : 最大行寬。

EditorConfig包含的內(nèi)容比較少,主要是配置我們的編輯器,編寫代碼時(shí)的簡單規(guī)則,不足以滿足項(xiàng)目更多需求。

Prettier

Prettier只關(guān)注格式化,并不具有l(wèi)int檢查語法等能力。它通過解析代碼并匹配自己的一套規(guī)則,來強(qiáng)制執(zhí)行一致的代碼展示格式。
它在美化代碼方面有很大的優(yōu)勢(shì),配合ESLint可以對(duì)ESLint格式化基礎(chǔ)上做一個(gè)很好的補(bǔ)充。

還是以VSCode為例,首先安裝Prettier插件。
VSCode內(nèi)置的代碼格式化工具可以指定為由Prettier接管,此時(shí)右下角會(huì)顯示為Prettier。可以自行配置格式化觸發(fā)機(jī)制:換行時(shí)格式化、保存文件時(shí)格式化、還是自行快捷鍵觸發(fā);
默認(rèn)情況下我都是使用默認(rèn)的手動(dòng)觸發(fā)。
當(dāng)在編輯器里格式化未生效時(shí),可以在.settings.json里檢查對(duì)應(yīng)文件格式指定的格式化程序并調(diào)整就可以:

"[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
}

這樣在VSCode編輯器里,觸發(fā)文件格式化時(shí)就能根據(jù)配置自動(dòng)美化格式代碼。
可以在VSCode 首選項(xiàng)-設(shè)置-擴(kuò)展或.settings.json中更改通用配置;
當(dāng)然還可以在具體項(xiàng)目根目錄設(shè)置.prettierrc單獨(dú)配置;
比如以下一些配置:

{
  // 設(shè)置強(qiáng)制單引號(hào)
  "singleQuote": true,
  // 為多行數(shù)組的非末尾行添加逗號(hào) es5的對(duì)象,數(shù)組等
  "trailingComma": "es5",
  // 每行最大寬度 100
  "printWidth": 100,
  // 設(shè)置語句末尾不加分號(hào)
  "semi": false,
  // jsx中使用單引號(hào)
  "jsxSingleQuote": true,
}

EsLint

ESLint 是一個(gè)在 JavaScript 代碼中通過規(guī)則模式匹配作代碼識(shí)別和報(bào)告的插件化的檢測(cè)工具,它的目的是保證代碼規(guī)范的一致性和及時(shí)發(fā)現(xiàn)代碼問題、提前避免錯(cuò)誤發(fā)生。
ESLint 的關(guān)注點(diǎn)是代碼質(zhì)量,檢查代碼風(fēng)格并且會(huì)提示不符合風(fēng)格規(guī)范的代碼。除此之外 ESLint 也具有一部分代碼格式化的功能。

使用方法:
1.安裝:ESLint 可以安裝在當(dāng)前項(xiàng)目中或全局環(huán)境下,但因項(xiàng)目間存在的差異性,我們一般會(huì)將它安裝在當(dāng)前項(xiàng)目中。安裝

yarn add --save-dev eslint

2.安裝插件和解析器
假如項(xiàng)目中使用了TypeScript和React,則安裝:

yarn add --save-dev typescript @typescript-eslint/parser
yarn add --save-dev eslint-plugin-react @typescript-eslint/eslint-plugin

其他的插件和解析器請(qǐng)根據(jù)實(shí)際項(xiàng)目需要安裝。

3.創(chuàng)建配置文件
我們?cè)陧?xiàng)目的根目錄下創(chuàng)建一個(gè) .eslintrc.js,內(nèi)容如下:


module.exports = {
    parser: '@typescript-eslint/parser',
    plugins: ['react','@typescript-eslint'],
    rules: {
        // 禁止使用 var
        'no-var': "error",
        // 優(yōu)先使用 interface 而不是 type
        '@typescript-eslint/consistent-type-definitions': [
            "error",
            "interface"
        ]
    }
}

如果是用腳手架工具創(chuàng)建的項(xiàng)目,創(chuàng)建的時(shí)候勾選了eslint,則上面的3步操作,都會(huì)自動(dòng)完成。

rules屬性是一個(gè)對(duì)象,對(duì)象中包含很多規(guī)則,規(guī)則的值主要有0,1和2這三種:
0 或者"off" ,表示關(guān)閉規(guī)則。
1或者"warn" ,打開規(guī)則,并且將規(guī)則視為一個(gè)警告(并不會(huì)導(dǎo)致檢查不通過)。
2或者"error" ,打開規(guī)則,并且將規(guī)則視為一個(gè)錯(cuò)誤 (退出碼為1,檢查不通過)。
在行內(nèi)書寫規(guī)則,需要寫在/* eslint ... */

我們需要的絕大多數(shù)規(guī)則都是在這個(gè)rules對(duì)象中:

比如說我們想要修改代碼縮進(jìn),就在配置文件中的rules對(duì)象中添加一個(gè)屬性:
使用瀏覽器默認(rèn)配置'indent':0
使用兩個(gè)空格作縮進(jìn)"indent": ["error", 2]
使用Tab作為縮進(jìn)"indent": ["error", "tab"]

比如說我們想要每行代碼末尾都要有分號(hào):'semi':["error","always"],這樣,你的 js 代碼每一個(gè)表達(dá)式的結(jié)尾就應(yīng)該以分號(hào)結(jié)尾,否則 eslint 會(huì)給出錯(cuò)誤提示。
如果你希望 eslint 不檢查分號(hào)這一項(xiàng),這個(gè)時(shí)候結(jié)尾的分號(hào),你加也可以,不加也可以,在 rules 字段配置:"semi": [0, "never"],

常用的規(guī)則:
與Javascript代碼中可能的錯(cuò)誤有關(guān)的規(guī)則
禁止條件表達(dá)式中出現(xiàn)模棱兩可的賦值操作符:no-cond-assign
禁用console:no-console
禁止在條件中使用常量表達(dá)式:no-constant-condition
禁用 debugger :no-debugger
禁止 function 定義中出現(xiàn)重名參數(shù) :no-dupe-args
禁止對(duì)象字面量中出現(xiàn)重復(fù)的 key :no-dupe-keys
禁止出現(xiàn)重復(fù)的 case 標(biāo)簽 :no-duplicate-case
禁止出現(xiàn)空語句塊 :no-empty
禁止對(duì) catch 子句的參數(shù)重新賦值 :no-ex-assign
禁止不必要的布爾轉(zhuǎn)換 :no-extra-boolean-cast
禁止不必要的括號(hào) :no-extra-parens
禁止不必要的分號(hào) :no-extra-semi
禁止對(duì) function 聲明重新賦值 :no-func-assign
禁止在嵌套的塊中出現(xiàn)變量聲明或 function 聲明 :no-inner-declarations
禁止在字符串和注釋之外不規(guī)則的空白 :no-irregular-whitespace
禁止把全局對(duì)象作為函數(shù)調(diào)用 :no-obj-calls
禁用稀疏數(shù)組 :no-sparse-arrays
禁止直接使用Object.prototypes 的內(nèi)置屬性 :no-prototype-builtins
禁止出現(xiàn)令人困惑的多行表達(dá)式 :no-unexpected-multiline
禁止在return、throw、continue 和 break語句之后出現(xiàn)不可達(dá)代碼 :no-unreachable
要求使用 isNaN() 檢查 NaN :use-isnan
強(qiáng)制 typeof 表達(dá)式與有效的字符串進(jìn)行比較:valid-typeof

下面這些規(guī)則是關(guān)于最佳實(shí)踐的,幫助你避免一些問題:
強(qiáng)制數(shù)組方法的回調(diào)函數(shù)中有 return 語句 :array-callback-return
強(qiáng)制把變量的使用限制在其定義的作用域范圍內(nèi) :block-scoped-var
指定程序中允許的最大環(huán)路復(fù)雜度 :complexity
要求 return 語句要么總是指定返回的值,要么不指定 :consistent-return
強(qiáng)制所有控制語句使用一致的括號(hào)風(fēng)格 :curly
要求 switch 語句中有 default 分支 :default-case
強(qiáng)制在點(diǎn)號(hào)之前和之后一致的換行 :dot-location
強(qiáng)制在任何允許的時(shí)候使用點(diǎn)號(hào) :dot-notation
要求使用 === 和 !== :eqeqeq
要求 for-in 循環(huán)中有一個(gè) if 語句 :guard-for-in
禁用 alert、confirm 和 prompt :no-alert
不允許在 case 子句中使用詞法聲明 :no-case-declarations
禁止 if 語句中有 return 之后有 else :no-else-return
禁止出現(xiàn)空函數(shù) :no-empty-function
禁止在沒有類型檢查操作符的情況下與 null 進(jìn)行比較 :no-eq-null
禁用 eval() :no-eval
禁止不必要的 .bind() 調(diào)用 :no-extra-bind
禁止 case 語句落空 :no-fallthrough
禁止數(shù)字字面量中使用前導(dǎo)和末尾小數(shù)點(diǎn) :no-floating-decimal
禁止使用短符號(hào)進(jìn)行類型轉(zhuǎn)換 :no-implicit-coercion
禁止在全局范圍內(nèi)使用 var 和命名的 function 聲明 :no-implicit-globals
禁止 this 關(guān)鍵字出現(xiàn)在類和類對(duì)象之外 :no-invalid-this
禁用不必要的嵌套塊 :no-lone-blocks
禁止在循環(huán)中出現(xiàn) function 聲明和表達(dá)式 :no-loop-func
禁用魔術(shù)數(shù)字 :no-magic-numbers
禁止使用多個(gè)空格 :no-multi-spaces
禁止使用多行字符串 :no-multi-str
禁止在非賦值或條件語句中使用 new 操作符 :no-new
禁止對(duì) Function 對(duì)象使用 new 操作符 :no-new-func
禁止對(duì) String,Number 和 Boolean 使用 new 操作符 :no-new-wrappers
不允許對(duì) function 的參數(shù)進(jìn)行重新賦值 :no-param-reassign
禁止使用 var 多次聲明同一變量 :no-redeclare
禁止在 return 語句中使用賦值語句 :no-return-assign
禁止使用 javascript: url :no-script-url
禁止自我賦值 :no-self-assign
禁止自身比較 :no-self-compare
禁用逗號(hào)操作符 :no-sequences
禁用一成不變的循環(huán)條件 :no-unmodified-loop-condition
禁止出現(xiàn)未使用過的表達(dá)式 :no-unused-expressions
禁止不必要的 .call() 和 .apply() :no-useless-call
禁止不必要的字符串字面量或模板字面量的連接 :no-useless-concat
要求所有的 var 聲明出現(xiàn)在它們所在的作用域頂部:vars-on-top

與使用嚴(yán)格模式和嚴(yán)格模式指令有關(guān)規(guī)則:
要求或禁止使用嚴(yán)格模式指令 :strict

與變量聲明有關(guān)規(guī)則:
要求或禁止 var 聲明中的初始化 : init-declarations
不允許 catch 子句的參數(shù)與外層作用域中的變量同名 :no-catch-shadow
禁用特定的全局變量 :no-restricted-globals
禁止 var 聲明 與外層作用域的變量同名 :no-shadow
禁用未聲明的變量,除非它們?cè)?/global / 注釋中被提到 :no-undef
禁止將變量初始化為 undefined :no-undef-init
禁止出現(xiàn)未使用過的變量 :no-unused-vars
不允許在變量定義之前使用它們 :no-use-before-define

關(guān)于Node.js 或 在瀏覽器中使用CommonJS 的規(guī)則:
要求 require() 出現(xiàn)在頂層模塊作用域中 :global-require
要求回調(diào)函數(shù)中有容錯(cuò)處理 :handle-callback-err
禁止混合常規(guī) var 聲明和 require 調(diào)用 :no-mixed-requires
禁止調(diào)用 require 時(shí)使用 new 操作符 :no-new-require
禁止對(duì) dirname 和 filename進(jìn)行字符串連接 :no-path-concat
禁用指定的通過 require 加載的模塊 :no-restricted-modules

如何保存代碼的時(shí)候自動(dòng)格式化代碼

vscode 中寫完代碼 Ctrl + s 保存即可格式化代碼 或者 (Shift+Alt+f)
找到settings.json,settings.json里所有的配置都是在一個(gè)對(duì)象中,給這個(gè)對(duì)象添加屬性

"editor.fontSize": 14,
"editor.formatOnType": true,
"editor.formatOnSave": true

editor.fontSize可以修改編輯器的字號(hào),默認(rèn)是14號(hào),修改之后保存即可。

Prettier和EsLint的區(qū)別

prettier主要功能是用來做代碼風(fēng)格格式化的,eslint主要是做語法驗(yàn)證的,這2個(gè)一開始我也不懂,而且有部分像是否加分號(hào),字符串使用單引號(hào)還是雙引號(hào)這些他們都可以配置

我是這么理解的eslint是給你指出問題的,它告訴你你的代碼有哪里不規(guī)范然后讓你自己改(它可以幫你改一小部分),而prettier是你給它指定規(guī)則,然后它幫你完成格式化,它只有一個(gè)功能就是根據(jù)你的規(guī)則格式化代碼,

因?yàn)閑slint有一部分代碼它也可以幫你格式化,并且使用了prettier-eslint后它的權(quán)重比prettier高,所以你給prettier設(shè)置的規(guī)則不生效,就要考慮是不是eslint影響了它

beautify和prettier

beautify和prettier都是能夠格式化代碼的插件
.jsbeautifyrc文件添加配置代碼,也是在settings.json中添加vscode對(duì)beautify的使用,但是因?yàn)槲覀冞x用的Prettier,自然就舍棄Beautify了
Vscode編輯器里卸載掉Beautify插件

LF和CRLF引起的Git沖突

CRLF 是 carriage return line feed 的縮寫,中文意思是回車換行。
LF 是 line feed 的縮寫,中文意思也是換行。
它們都是文本換行的方式。

CRLF: "\r\n", windows系統(tǒng)環(huán)境下的換行方式
LF: "\n", Linux系統(tǒng)環(huán)境下的換行方式

他們之間的不同經(jīng)常會(huì)導(dǎo)致不同會(huì)導(dǎo)致使用不同系統(tǒng)的同事之間的代碼沖突問題。
在你使用git拉取代碼的時(shí)候,git會(huì)自動(dòng)將代碼當(dāng)中與你當(dāng)前系統(tǒng)不同的換行方式轉(zhuǎn)化成你當(dāng)前系統(tǒng)的換行方式,從而造成這種沖突。
前面有說使用EditorConfig,在配置里添加end_of_line = lf可以讓項(xiàng)目里的文件改為統(tǒng)一的LF。
在git提交代碼的時(shí)候,git status查看有對(duì)應(yīng)文件的修改,但是git diff的時(shí)候查看不到修改內(nèi)容的時(shí)候,很有可能是當(dāng)前文件的換行方式發(fā)生了變化,雖然在絕大多數(shù)情況下這并不會(huì)引起沖突,但在團(tuán)隊(duì)協(xié)作的過程中,每次提交修改的代碼應(yīng)盡量減少修改不必要的文件,這是一個(gè)良好的習(xí)慣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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