做者:JowayYoung
倉庫:Github、CodePen
博客:官網、掘金、思否、知乎
公衆號:IQ前端
特別聲明:原創不易,未經受權不得轉載或抄襲,如需轉載可聯繫筆者受權css
大部分前端項目都配置Stylelint
、Eslint
、Tslint
和Prettier
四大前端代碼校驗工具。代碼校驗工具如下簡稱Lint
,爲了解決代碼不嚴謹,經過預設規則校驗代碼,檢測其是否存在錯誤/漏洞
,並對錯誤/漏洞
提示修復方案並儘量依據修復方案格式化出正確代碼。該功能稱爲格式化代碼,基本上全部編輯器都需配置該功能。html
Lint
其實就是編輯器裏運行的一個腳本進程,將代碼解析成抽象語法樹
,遍歷抽象語法樹
並經過預設規則作一些判斷和修改,再將新的抽象語法樹
轉換成正確代碼。整個校驗過程都跟抽象語法樹
相關,若暫未接觸過抽象語法樹
,可閱讀babel源碼
或eslint源碼
瞭解其工做原理。前端
開發過程當中啓用Lint
能帶來如下好處。vue
團隊編碼規範
,讓新舊組員編碼習慣獲得一致提高團隊編碼風格
,讓預設規則符合新舊組員心理預期可維護性
和可接入性
,讓新組員能快速適應項目的架構與需求無用代碼
、重複代碼
、錯誤代碼
和漏洞代碼
的產生概率千萬不能自私node
有些同窗可能一時適應不了Lint
帶來的強制性操做,會在本身編輯器裏關閉項目全部校驗功能,這種自私行爲會帶來很嚴重的後果。react
若上傳無任何校驗痕跡的代碼塊,當其餘組員將該代碼塊更新合併到原有代碼上時,因爲編輯器一直配置着團隊編碼規範
,致使被拉下來的代碼塊立馬報錯甚至產生衝突。git
上述狀況會讓其餘組員花費更多時間解決由於你不遵照規矩而帶來的問題,還浪費團隊爲了研究如何讓總體編碼風格更適合組員的精力。github
這種自私行爲不可取,若團隊無任何編碼規範可隨意編碼,若已承認團隊編碼規範
那就努力遵照,不給團隊帶來麻煩。web
本文着重講解一鍵格式化代碼的部署,像Lint
經常使用配置就不會講解,畢竟百度谷歌一搜一大堆。這個一鍵固然是ctrl+s
或cmd+s
保存文件啦。在保存文件時觸發Lint
自動格式化代碼,這個操做固然不能100%
保證將代碼格式化出最正確代碼,而是儘量依據修復方案格式化出正確代碼。言下之意就是可能存在部分代碼格式化失敗,但將鼠標移至紅色下劃線上會提示修復方案,此時可依據修復方案自行修正代碼。typescript
爲什麼寫下本文?筆者有着嚴謹的代碼邏輯和優雅的編碼風格,因此特別喜歡格式化代碼。然而又不想爲每一個項目配置Lint
,這些重複無腦的複製粘貼讓筆者很反感,因此筆者只想一次配置全局運行Lint
,這樣就無需爲每一個項目配置Lint
。在大量百度谷歌都未能搜到一篇相關文章(搜到的所有文章都是單獨爲一個項目配置,害
),筆者就花了半年多時間探討出本方案,真正作到一次配置全局運行。若使用本方案,相信能將全部項目的Stylelint
、Eslint
、Tslint
和Prettier
相關依賴和配置文件所有移除,使項目目錄變得超級簡潔,如同下圖。
筆者選用VSCode
做爲前端開發的編輯器,其餘編輯器不是性能差就是配置麻煩,因此通通放棄,只認VSCode
。
在此強調兩個重要問題,這兩個問題影響到後面可否成功部署VSCode
的一鍵格式化代碼。
Tslint
官方已宣佈廢棄Tslint
,改用Eslint
代替其全部校驗功能Eslint
部分配置與Prettier
部分配置存在衝突且互相影響,爲了保證格式化性能就放棄接入Prettier
因此部署VSCode
的一鍵格式化代碼只需安裝Stylelint
和Eslint
兩個插件。爲了方便表述,統一如下名詞。
VSCode插件
NPM依賴
前方高能,兩大步驟就能爲VSCode
部署一鍵格式化代碼,請認真閱讀喔!
安裝依賴
爲了搞清楚兩個插件集成哪些NPM依賴
,如下區分安裝stylelint
和eslint
及其相關依賴(看看便可,不要安裝,重點在後頭)。筆者有個習慣,就是喜歡將依賴更新到最新版本,在享受新功能的同時也順便填坑。
# Stylelint
npm i -D stylelint stylelint-config-standard stylelint-order
複製代碼
# Eslint
npm i -D eslint babel-eslint eslint-config-standard eslint-plugin-html eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-react eslint-plugin-standard eslint-plugin-vue vue-eslint-parser
複製代碼
# TypeScript Eslint
npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser typescript eslint-config-standard-with-typescript
複製代碼
安裝完成後需配置多份對應配置文件,CSS方面有css/scss/less/vue
文件,JS方面有js/ts/jsx/tsx/vue
文件。查看插件文檔,發現Stylelint
只能在settings.json
上配置,而Eslint
可配置成多份對應配置文件,並在settings.json
上經過特定字段指定Eslint
配置文件路徑。
settings.json是VSCode的配置文件,用戶可經過插件暴露的字段自定義編輯器功能。
複製代碼
因爲配置文件太多很差管理,筆者開源了本身日常使用的配置文件集合,詳情可查看vscode-lint。
js文件
jsx文件
vue文件
TypeScript
ts文件
tsx文件
vue文件
配置文件裏的rule
可根據本身編碼規範適當調整,在此不深刻講解,畢竟簡單得來誰都會。建議使用vscode-lint
,若校驗規則不喜歡可自行調整。
如下會基於vscode-lint
部署VSCode
的一鍵格式化代碼,找個目錄經過git
克隆一份vscode-lint
,並安裝其NPM依賴
。若使用vscode-lint
,上述依賴就不要安裝了🙅。
git clone https://github.com/JowayYoung/vscode-lint.git
cd vscode-lint
npm i
複製代碼
配置插件
VSCode
工具欄
的插件
,搜索並安裝Stylelint
和Eslint
,安裝完成後重啓VSCode
文件 → 首選項 → 設置
,設置
裏可選用戶
和工做區
若大部分項目都是單一的React應用或Vue應用推薦使用全局配置
)設置
右上角中間圖標打開設置(json)
,打開的對應文件是settings.json
(上述有說起)用戶
選項下插入如下配置,遇到其餘項目需覆蓋配置時在工做區
選項下插入eslint.options.configFile
指定Eslint
配置文件路徑VSCode
:爲了保障每次修改配置後都能正常格式化代碼,必須重啓VSCode
{
"css.validate": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
"eslint.nodePath": "path/vscode-lint/node_modules",
"eslint.options": {
"configFile": "path/vscode-lint/eslintrc.js"
},
"less.validate": false,
"scss.validate": false,
"stylelint.configBasedir": "path/vscode-lint",
"stylelint.configOverrides": {
"extends": "stylelint-config-standard",
"plugins": [
"stylelint-order"
],
"rules": {
"at-rule-empty-line-before": "never",
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": [
"content",
"each",
"error",
"extend",
"for",
"function",
"if",
"include",
"mixin",
"return",
"while"
]
}
],
"color-hex-case": "lower",
"comment-empty-line-before": "never",
"declaration-colon-newline-after": null,
"declaration-empty-line-before": "never",
"function-linear-gradient-no-nonstandard-direction": null,
"indentation": "tab",
"no-descending-specificity": null,
"no-missing-end-of-source-newline": null,
"no-empty-source": null,
"number-leading-zero": "never",
"rule-empty-line-before": "never",
"order/order": [
"custom-properties",
"declarations"
],
"order/properties-order": [
// 佈局屬性
"display",
"visibility",
"overflow",
"overflow-x",
"overflow-y",
"overscroll-behavior",
"scroll-behavior",
"scroll-snap-type",
"scroll-snap-align",
// 佈局屬性:浮動
"float",
"clear",
// 佈局屬性:定位
"position",
"left",
"right",
"top",
"bottom",
"z-index",
// 佈局屬性:列表
"list-style",
"list-style-type",
"list-style-position",
"list-style-image",
// 佈局屬性:表格
"table-layout",
"border-collapse",
"border-spacing",
"caption-side",
"empty-cells",
// 佈局屬性:彈性
"flex-flow",
"flex-direction",
"flex-wrap",
"justify-content",
"align-content",
"align-items",
"align-self",
"flex",
"flex-grow",
"flex-shrink",
"flex-basis",
"order",
// 佈局屬性:多列
"columns",
"column-width",
"column-count",
"column-gap",
"column-rule",
"column-rule-width",
"column-rule-style",
"column-rule-color",
"column-span",
"column-fill",
"column-break-before",
"column-break-after",
"column-break-inside",
// 佈局屬性:格柵
"grid-columns",
"grid-rows",
// 尺寸屬性
"box-sizing",
"margin",
"margin-left",
"margin-right",
"margin-top",
"margin-bottom",
"padding",
"padding-left",
"padding-right",
"padding-top",
"padding-bottom",
"border",
"border-width",
"border-style",
"border-color",
"border-colors",
"border-left",
"border-left-width",
"border-left-style",
"border-left-color",
"border-left-colors",
"border-right",
"border-right-width",
"border-right-style",
"border-right-color",
"border-right-colors",
"border-top",
"border-top-width",
"border-top-style",
"border-top-color",
"border-top-colors",
"border-bottom",
"border-bottom-width",
"border-bottom-style",
"border-bottom-color",
"border-bottom-colors",
"border-radius",
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-image",
"border-image-source",
"border-image-slice",
"border-image-width",
"border-image-outset",
"border-image-repeat",
"width",
"min-width",
"max-width",
"height",
"min-height",
"max-height",
// 界面屬性
"appearance",
"outline",
"outline-width",
"outline-style",
"outline-color",
"outline-offset",
"outline-radius",
"outline-radius-topleft",
"outline-radius-topright",
"outline-radius-bottomleft",
"outline-radius-bottomright",
"background",
"background-color",
"background-image",
"background-repeat",
"background-repeat-x",
"background-repeat-y",
"background-position",
"background-position-x",
"background-position-y",
"background-size",
"background-origin",
"background-clip",
"background-attachment",
"bakground-composite",
"mask",
"mask-mode",
"mask-image",
"mask-repeat",
"mask-repeat-x",
"mask-repeat-y",
"mask-position",
"mask-position-x",
"mask-position-y",
"mask-size",
"mask-origin",
"mask-clip",
"mask-attachment",
"mask-composite",
"mask-box-image",
"mask-box-image-source",
"mask-box-image-width",
"mask-box-image-outset",
"mask-box-image-repeat",
"mask-box-image-slice",
"box-shadow",
"box-reflect",
"filter",
"mix-blend-mode",
"opacity",
"object-fit",
"clip",
"clip-path",
"resize",
"zoom",
"cursor",
"pointer-events",
"user-modify",
"user-focus",
"user-input",
"user-select",
"user-drag",
// 文字屬性
"line-height",
"line-clamp",
"vertical-align",
"direction",
"unicode-bidi",
"writing-mode",
"ime-mode",
"text-overflow",
"text-decoration",
"text-decoration-line",
"text-decoration-style",
"text-decoration-color",
"text-decoration-skip",
"text-underline-position",
"text-align",
"text-align-last",
"text-justify",
"text-indent",
"text-stroke",
"text-stroke-width",
"text-stroke-color",
"text-shadow",
"text-transform",
"text-size-adjust",
"src",
"font",
"font-family",
"font-style",
"font-stretch",
"font-weight",
"font-variant",
"font-size",
"font-size-adjust",
"color",
// 內容屬性
"tab-size",
"overflow-wrap",
"word-wrap",
"word-break",
"word-spacing",
"letter-spacing",
"white-space",
"caret-color",
"quotes",
"content",
"content-visibility",
"counter-reset",
"counter-increment",
"page",
"page-break-before",
"page-break-after",
"page-break-inside",
// 交互屬性
"will-change",
"perspective",
"perspective-origin",
"backface-visibility",
"transform",
"transform-origin",
"transform-style",
"transition",
"transition-property",
"transition-duration",
"transition-timing-function",
"transition-delay",
"animation",
"animation-name",
"animation-duration",
"animation-timing-function",
"animation-delay",
"animation-iteration-count",
"animation-direction",
"animation-play-state",
"animation-fill-mode",
// Webkit專有屬性
"-webkit-overflow-scrolling",
"-webkit-box-orient",
"-webkit-line-clamp",
"-webkit-text-fill-color",
"-webkit-tap-highlight-color",
"-webkit-touch-callout",
"-webkit-font-smoothing",
"-moz-osx-font-smoothing"
]
}
}
}
複製代碼
以上配置的path
爲vscode-lint
所在的根目錄,若剛纔的vscode-lint
克隆到E:/Github
,那麼path
就是E:/Github
。
上述步驟完成後就可愉快敲代碼了。每次保存文件就會自動格式化CSS代碼
或JS代碼
,這個格式化代碼不只會將代碼按照規範整理
和排序
,甚至儘量依據修復方案格式化出正確代碼。
這樣就無需爲每一個項目配置Lint
,將全部項目的Stylelint
、Eslint
、Tslint
和Prettier
相關依賴和配置文件所有移除,使項目目錄變得超級簡潔。
css/scss/less/vue文件
js/ts/jsx/tsx/vue文件
不少同窗反映eslint v6+
在VSCode
上失效,最高版本只能控制在v5.16.0
。其實這自己就是配置問題,跟版本無關。vscode-lint
的eslint
使用v7
照樣能使用Eslint
,只要配置正確就能正常使用。
上述安裝行爲使用了NPM
,那麼settings.json
的eslint.packageManager
必須配置爲npm
(小寫),但最新版本Eslint
已默認此項,因此無需配置。若上述安裝行爲變成yarn install
,那麼必須在settings.json
裏添加如下配置。
{
"eslint.packageManager": "yarn"
}
複製代碼
這個配置就是解決該問題的關鍵了。
首次安裝Eslint
可能會在js/ts/jsx/tsx/vue
文件裏看到如下警告。
Eslint is disabled since its execution has not been approved or denied yet. Use the light bulb menu to open the approval dialog.
複製代碼
說明Eslint
被禁用了,雖然配置裏無明確的禁用字段,但仍是被禁用了。此時移步到VSCode
右下角的工具欄,會看到禁用圖標+ESLINT
的標紅按鈕,單擊它會彈出一個彈框,選擇Allow Everywhere
就能啓用Eslint
全部校驗功能。
總體過程看似簡單,其實筆者這半年填了不少坑纔有了vscode-lint
,中間已省略了不少未記錄的問題,這些疑問不重要卻影響到不少地方。相信本文能讓不少同窗體驗VSCode
一鍵格式化代碼所帶來的快感,最關鍵的部分仍是無需爲每一個項目配置Lint
,這省下多少時間和精力呀!以爲牛逼給vscode-lint點個Star吧!
回看筆者往期高贊文章,也許能收穫更多喔!
4200+
點贊量,15.6w+
閱讀量4300+
點贊量,13w+
閱讀量3300+
點贊量,4.5w+
閱讀量1600+
點贊量,5w+
閱讀量700+
點贊量,2.3w+
閱讀量700+
點贊量,1.8w+
閱讀量500+
點贊量,1.6w+
閱讀量❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創做更多高質量文章
關注公衆號IQ前端
,一個專一於CSS/JS開發技巧的前端公衆號,更多前端小乾貨等着你喔
資料
免費領取學習資料進羣
拉你進技術交流羣IQ前端
,更多CSS/JS開發技巧只在公衆號推送