<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從0到1開發(fā)一個簡單的 eslint 插件

          共 3914字,需瀏覽 8分鐘

           ·

          2021-05-16 16:27

          ?

          前言:eslint 我們常應用在代碼靜態(tài)掃描中,通過設定的 eslint 的語法規(guī)則,來對代碼進行檢查,通過規(guī)則來約束代碼的風格,以此來提高代碼的健壯性,避免因為代碼不規(guī)范導致應用出現(xiàn) bug 的可能。而規(guī)則是自由的,你可以設定內(nèi)部自己團隊適用的規(guī)則,也可以直接使用開源社區(qū)比較熱門的規(guī)則集合, 比如 airbnb、eslint-plugin-vue 等

          ?

          1.eslint 的配置

          ?

          手寫規(guī)則前,讓我們重溫下 eslint 配置,通常我們是使用.eslintrc.js來配置 eslint 的,或者也可以直接package.json中定義 eslintConfig 的屬性

          ?

          上圖 ?? 是 eslint 主要的配置,我們簡單回顧下每個配置的背后包含的意義

          1.1 parse

          ?

          parse 是用來定義 eslint 所使用的解析器,默認是使用Espree??, 解析器的作用是將代碼 code 轉(zhuǎn)化成為一種 AST 抽象語法樹,eslint 中叫ESTree,你可以理解為將 code 翻譯為ESLint能聽 ?? 懂的話

          ?

          關于 Espree 可以參考下面這個例子

          而常用的解析器還有包括以下幾種

          • Esprima: 上文提到 espree 就是基于 Esprima 改良的

          • Babel-esLint:一個對 Babel 解析器的包裝,當你項目中使用了 babel,babel 的解析器會把你的 code 轉(zhuǎn)換為 AST,然后該解析器會將其轉(zhuǎn)換為 ESLint 能懂的 ESTree。這個目前我們應用的較多,目前也不再維護和更新,升級為@babel/eslint-parser

          • @typescript-eslint/parser: 將 TypeScript 轉(zhuǎn)換成與 estree 兼容的形式,以便在 ESLint 中使用。

          對于 AST 的模擬生成,感興趣的同學可以使用astexplorer在線嘗試

          image.png

          總結:無論你使用那種解析器,本質(zhì)是都是為了將 code 轉(zhuǎn)換為 ESLint 能夠閱讀的語言ESTree??

          1.2 parseOption

          ?

          parserOptions 參數(shù)是用來控制 parse 解析器, 主要包括以下幾個屬性 ??,我們挑重點的講講

          ?
          parserOptions
          • ecmaVersion:用來指定你想要使用的 ECMAScript 版本,默認設置為 5,舉個例子:默認情況下,ESLint 支持 ECMAScript 5 語法,但如果你想讓 eslint 使用 es6 特征來支持,就可以通過修改 parserOptions 中"ecmaVersion": 6

          1.3 rules

          ?

          rules 就是 eslint 的規(guī)則,你可以在 rules 配置中根據(jù)在不同場景、不同規(guī)范下添加自定義規(guī)則詳情可參考之前 ?? 樹醬的 前端規(guī)范那些事

          ?

          1.4 extends(擴展) 與 plugins(插件)

          ?

          extends 和 plugins 很容易混淆,本質(zhì)是為了加強 eslint 的擴展性,使得我們可以直接使用別人已經(jīng)寫好的 eslint 規(guī)則,方便快捷的應用到項目中,有點類似之前文章中Babel 配置傻傻看不懂?提及的 babel 配置中的 present 和 plugin

          ?

          比如你使用 extends 去擴展 { "extends": [ "eslint:recommended", "plugin:react/recommended", "eslint-config-standard", ]}

          但是如果你想用插件,其實等價于 {"plugin": ['react','standard']}

          ? 提醒:官方規(guī)定 npm 包的擴展必須以 eslint-config- 開頭,我們使用過程中可以省略這個開頭,上面案例中 eslint-config-standard 可以直接簡寫成 standard。同樣,如果要開發(fā)一個 eslint 插件,也是需要以這種形式來命名,下節(jié)會介紹

          我們再舉個列子

          上圖我們通過上面這個配置例子,我們可以看到要么是plugins:[]要么是extends:[],通過上圖所示的配置二相對于配置一少了parser, parserOptionsplugins 等的信息配置,但其實這兩個配置最終實現(xiàn)的結果是一致的,這是因為配置二中定義的 extends:plugin:@typescript-eslint/recommended 會自動加載上述提到的其他幾個配置信息

          2 開發(fā) eslint 插件

          ?

          通過上一節(jié)對 eslint 的配置的了解,接下來看看如何從 0 到 1 開發(fā)一個 eslint 插件。

          ?

          2.1 eslint 插件初始化

          ?

          ESLint 官方為了方便開發(fā)者,提供了使用 Yeoman 腳手架的模板(generator-eslint??)。以此方便我們通過該腳手架拉取 eslint 插件模版,對 Yeoman 進一步了解可以閱讀 ?? 樹醬的前端工程化那些事 - yeoman

          ?
          • 第一步:安裝 npm install -g yo generator-eslint
          • 第二步:創(chuàng)建一個文件夾并然后通過命令行初始化 ESLint 插件的項目結構 yo eslint:plugin
          • 第三步:完成插件初始化創(chuàng)建

          2.2 創(chuàng)建 rule 規(guī)則

          ?

          完成插件項目結構初始化創(chuàng)建后,開始生成 ESLint 插件中具體規(guī)則,在 ESLint 插件的項目中執(zhí)行命令行 yo eslint:rule,來生成 eslint 規(guī)則的模版,實際效果如下所示

          ?

          創(chuàng)建成功后,我們看下最終的目錄結構

          • docs: 使用文檔,描述你編寫的規(guī)則
          • lib/rules 目錄:規(guī)則開發(fā)源碼文件 (例如,no-extra-semi.js)
          • tests/lib/rules 目錄:單元測試文件 (例如,no-extra-semi.js)

          2.3 編寫規(guī)則

          ?

          當完成上面一系列操作之后,eslint 插件模版初步完成,接下來我們找到目錄中lib/rules中對剛剛創(chuàng)建的 rule 進行開發(fā)

          ?

          假設我們有個場景,我們想創(chuàng)建一個規(guī)則,用來判讀代碼中是否存在console方法的調(diào)用,首先回到第一節(jié)提到的parse解析器,本質(zhì)上 rule 的邏輯判斷是通過識別 Espree 返回的抽象語法 ?? 去判斷,分別針對各種類型定義檢查方法。寫代碼之前,我們先看下 console 返回的 AST 是長啥樣?

          通過上圖我們可以清晰的看到 console.log()是屬于 ExpressionStatement(表達式語句)中的 CallExpression(調(diào)用語句),可以通過 callee 屬性中的 object 來判斷是否為console, 同時也可以利用其 property 屬性來判斷是 console 的哪種方法,比如loginfo

          so~ 我們開始造玩具,我們通過在 create 返回的對象中,定義一個 CallExpression 方法,當 ESLint 開始對 esTree 遍歷時,通過對調(diào)用語句的監(jiān)聽,來檢查該調(diào)用語句是否為 console 調(diào)用,代碼如下 ??

          每條 rule 就是一個 node 模塊,其主要由 meta 和 create 兩部分組成,重點講下下面兩個 ??

          • meta: 代表了這條規(guī)則的元數(shù)據(jù),包含類別,文檔,可接收的參數(shù)的 schema 等, 其中主要提下 schema,如果指定該選項,ESLint 可以通過識別的傳參,避免無效的規(guī)則配置(排除校驗),可參考下節(jié)介紹的單元測試的中傳遞的 options
          • context.report():它用來發(fā)布警告或錯誤(取決于你所使用的配置)

          ?? 推薦閱讀:

          • Eslint - Working with Rules

          2.4 單元測試

          ?

          當完成 eslit 插件開發(fā)后,我們需要對開發(fā)完的插件進行驗證,以此來保證規(guī)則校驗功能的正常使用。eslint 插件開發(fā)項目結構中默認使用了mocha作為單元測試框架

          ?

          我們對tests/rules/treegogo.js單元測試文件進行修改,定義 invalid 與 valid 的不同例子

          最后執(zhí)行

          2.5 關于發(fā)布

          ?

          在發(fā)布之前,還需要對 packjson 中 main 定義入口文件即lib/index.js,暴露出 rules 與 configs

          ?
          ?

          ???? 啊寬同學:那我如何定義一個包含配置的集合呢?

          ?

          是的,官方文檔描述:你可以在一個插件中在 configs 鍵下指定打包的配置。當你想提供不止代碼風格,而且希望提供一些自定義規(guī)則來支持它時,會非常有用。每個插件支持多配置,然后當你使用的時候,可以通過這樣使用 { "extends": ["plugin:tree-eslint/myConfig"] },這就包含預設好的規(guī)則配置

          最后是 npm 發(fā)布 npm pulish

          2.6 如何使用

          ?

          通過第一節(jié)的配置的介紹,我們需要有個.eslintrc文件,如果目錄沒用可以通過命令行eslint -init初始化,配置好后,安裝剛剛開放好的 eslint 插件

          ?

          配置一可以對我們開發(fā)的那個 rule 進行配置:error,warn,off,如果需要對部分做排除就加上 option,也可以像配置二引用預設好的擴展 extends

          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97色色大香蕉 | 欧美在线免费观看 | 天堂网最新网址 | 日本色色情视频 | 午夜久久久久久 |