Prettier is an opinionated code formatter.css
從官網的介紹中咱們能夠看到,首先 Prettier 的定位是一個代碼格式化工具,而且比較任性(opinionated)。它移除了幾乎全部[1]原始格式,來確保全部輸出的代碼符合一致。html
就最初的設計目標來講,Prettier 面向的範圍主要仍是 Web 端的一些開發語言,如:node
不過做爲一款代碼格式化工具,Prettier 經過開放了插件(Beta)的能力,來對不一樣語言提供支持。git
對於代碼風格的聖戰,沒有一天真正中止過:程序員
就我的角度來講,這些爭論有意義嗎?我以爲是有的,由於不只體現了一個程序員對細節的追求,還鍛鍊了探索、深挖、求真的能力。可是就團隊的角度來講,我以爲這些爭論是沒有意義的,我的代碼的風格截然不同,從 ESlint 的規則數量就能夠明顯地看出這一點。若是從我的代碼風格的角度出發,制定一套適用於團隊層面的規範,討論到最後,很難有一個統一的結果。 因此,爲了統一團隊代碼風格,確實須要任性(opinionated),才能真正落地。github
當有新人進入一個團隊時,他不只須要熟悉業務流程,兼顧遺留代碼,若是在開發時還被一系列的格式化代碼規則磕磕絆絆,是很是不友好的一件事。而經過配置 Prettier,按下一個按鍵就能夠直接將代碼格式化,不須要爲了適配各類規則手動修改,能將更多精力放在代碼質量層面。npm
除了一些很是有爭議的風格做爲配置項,Prettier 內置的規則通過了屢次修改討論,對於大多數開發者來講,是比較容易接受的。json
咱們引入一個新工具,確定但願它是穩步上升的,若是用到一半就被廢棄,後續的解耦成本就會成爲一個新的問題。 因此一個工具的將來如何一個很是重要的考量點:promise
每當提到 Prettier,ESlint 必定是一個繞不過去坎。甚至有人以爲二者是衝突的,是包含與被包含的關係。可是在我看來,他們只是存在某些功能上的重合,硬要從這個角度來講,頂多也是存在交集的關係。sass
要搞清楚二者的關係,能夠先從定義上解讀它們之間的區別:
ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code, with the goal of making code more consistent and avoiding bugs.
簡單來看,它們相同的地方主要有如下幾點:
ESlint 規則成千上萬,主要能夠分爲兩大類:
理想狀況下,若是 ESlint 規則設置的足夠細緻,基本能保證兩個不一樣的開發者——採用相同的技術方案——在代碼風格上 90% 的一致性。 可是對於 Prettier 來講,它工做的領域僅限於第一類——格式化代碼,也就是說即便存在嚴重影響代碼質量(Code-quality)的問題——好比死循環——Prettier 不會作出任何反應。緣由將會在下文中作出(Rationale)說明。
ESlint 自己是一個代碼校驗工具,可是也提供了格式化代碼的功能,經過添加 --fix
參數,能夠將代碼格式成符合自定義規則的樣子。 Prettier 做爲專業的格式化工具,內部自建了一套關於代碼風格的規則,且這些規則沒法被修改,除了暴露出的 19 個的配置項。這麼作的目的,就是爲了中止對各類個性化風格優劣的爭論,從而將討論的重點轉移到這 19 個配置項中。
在咱們的平常開發過程當中,已經習慣了使用 ESlint 來保障代碼質量與統一風格。若是再加上 Prettier 做爲代碼格式化的工具,就能夠起到如虎添翼的效果。可是由於 Prettier 內建的規則可能和 ESlint 的規則產生衝突,因此須要經過配置插件來解決這些問題。
經過下面的步驟能夠達到上述條件所描述的:
yarn add --dev eslint-config-prettier eslint-plugin-prettier
複製代碼
// .eslintrc.json
{
"extends": ["plugin:prettier/recommended"]
}
複製代碼
若是在項目中使用 Prettier,咱們固然不但願每次都要手動去執行格式化的命令,經過定製 pre-commit
鉤子,能夠達到自動格式化的效果,詳見文檔。 我我的最經常使用的是 pretty-quick
,開箱即用。配置好後,每次將文件提交到 git 暫存區(stage)以前,都會自動對全部文件作格式化。這樣一來,只要開發者按照規範 [2] 的流程走,就避免了代碼格式不一致問題。
yarn add pretty-quick husky --dev
複製代碼
// package.json
{
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
}
}
複製代碼
除了經過使用 git hooks 的方式來格式化代碼,也能夠在編寫代碼的過程當中,直接對其進行格式化。以 VSCode 爲例:
{
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.formatOnPaste": true
}
複製代碼
這一步也能夠經過 Formatting Toggle 插件來實現。
第一原則。做爲一個代碼格式化工具,若是想要讓別人用的放心,在保證格式化代碼後不會出現 bug 的同時,也必不能對原代碼作任何入侵。這就是上文中提到的,即便出現了 bug,Prettier 也不會作出反應,僅關注如何更好地代碼的緣由。ESlint --fix
則不一樣,它會去格式化那些違反規則的代碼:
return '' + value;
// after eslint --fix
return `${value}`;
{ color: color }
// after eslint --fix
{ color }
let a = {}
// after eslint --fix
const a = {}
複製代碼
保證正確性的另外一個方面,就是可以提早預知格式化後可能會產生的 bug。看下面一個例子:
// semi.js
if (shouldAddLines) {
[-1, 1].forEach(delta => addLine(delta * 20))
}
複製代碼
經過 prettier semi.js --no-semi
命令對上述代碼格式化,最後獲得的結果是這樣的:
if (shouldAddLines) {
;[-1, 1].forEach(delta => addLine(delta * 20))
}
複製代碼
看上去彷佛不符合規則,其實這麼作事爲了不下述狀況:
if (shouldAddLines) {
+ console.log('Do we even get here??')
[-1, 1].forEach(delta => addLine(delta * 20))
}
// after fomate
if (shouldAddLines) {
console.log('Do we even get here??')[-1, 1].forEach(delta => addLine(delta * 20))
}
複製代碼
經過上面的例子,說明了 Prettier 並不是經過一刀切的方式對代碼進行格式化,還會考慮格式化後的代碼,在具體的應用場景中會如何。
在咱們平常開發的過程當中,常常會遇到一些涉及性能的問題。解法不少,可是我通常會選擇更加容易讓人看懂的那種。也就是說在通常狀況下,爲了代碼的可維護性是能夠犧牲一部分性能的。 格式化代碼不是目的,目的是爲了讓代碼更加易讀。能夠經過如下幾個列子看出 Prettier 是如何遵照這一規則的:
對象的書寫方式通常由如下兩種:短對象能夠寫在一行裏,而一些長對象或者類 CSS 對象咱們習慣多行書寫。
// single-line
const user = { name: "John Doe", age: 18 };
// multi-line
const css = {
fontSize: 12,
color: "red",
padding: 100
};
複製代碼
可是若是僅僅經過長短來格式化,就沒法針對不一樣類型的對象作格式化處理,Prettier 也考慮到了這一點,能夠經過下面的方式來本身選想要的格式化結果。
// before
const use = { name: "John Doe",
age: 18
};
// after
const user = { name: "John Doe", age: 18 };
// ---
// before
const use = {
name: "John Doe",
age: 18 };
// after
const user = {
name: "John Doe",
age: 18
};
複製代碼
在一些測試方法中,可能必有比較長的描述說明,致使長度(Print Width)超過了既定值。可是 Prettier 並不會去作強制換行處理,由於這樣作是沒有意義的,只會下降可讀性。
到目前位置,Prettier 的配置規則僅僅只有 19 條,雖然添加一個規則不是什麼難事,可是若是要將規則刪除,就存在很大的問題了。你能夠試想下若是未來某一天 Prettier 的一條規則被刪除了,會發生什麼?以 bracket-spacing爲例: 在刪除以前,不管個人配置是 true or false,格式化話後的對象都是遵循必定規則的: - true
- Example: { foo: bar }
. - false
- Example: {foo: bar}
. 可是若是規則被刪除,不復存在了,你的代碼中可能會存在 {foo: bar, }
這樣的結果,這是你們都不肯意看到的。就拿 PR 來講,我在代碼比對的過程當中看到的這個屬於格式上的不統一,在我引入了 Prettier 以後,這個問題理應是不會存在的,漸漸你們就會失去對這個工具的信任。
爲何要舉 bracket-spacing 這個例子哪,由於這是一個連 Prettier 的做者也不知道爲何會存在的配置規則,可是它如今依舊存在着。
最後,借用我偶像 Dan 對 Prettier 的一段描述來結尾:
I just wanted to take a moment to say there are some of us who actually appreciate tools with limited scope that don’t attempt to solve everybody’s use case, and instead do a specific thing well.