從零構建前端 Lint 工做流(2020手把手版)

從零構建前端 Lint 工做流

  • eslint prettier husky lint-staged typescript eslint-config-alloy 爲構建項目代碼質量保駕護航
  • 傳承 ESLint 推崇的插件化、配置化的理念,知足個性化需求(即讓專業的工具作擅長的事)

選擇性閱讀

什麼是代碼檢查

  • 代碼檢查主要是用來發現代碼錯誤、統一代碼風格。
  • 在 JavaScript 項目中,咱們通常使用 ESLint 來進行代碼檢查,它經過插件化的特性極大的豐富了適用範圍,搭配 typescript-eslint 以後,甚至能夠用來檢查 TypeScript 代碼。

配置 ESLint

小試牛刀

一、新建一個文件夾,打開命令行,npm init -y建立package.json
二、安裝依賴npm install --save-dev eslint babel-eslint eslint-config-alloy
三、在項目根目錄下建立一個.eslintrc.js.eslintrc.json的配置文件:javascript

// .eslintrc.js
module.exports = {
    extends: [
        'alloy',
    ],
};

四、在項目根目錄下建立一個index.js,複製下面內容:css

var myName = 'Tom';
console.log(`My name is ${myNane}`);

五、在命令行輸入npx eslint index.jshtml

// eslint 報錯信息:
✖ 2 problems (2 errors, 0 warnings)
error  Unexpected var, use let or const instead  no-var
error  'myNane' is not defined                   no-undef

六、使用npx eslint index.js --fix自動修復某些規則前端

// 這時 var 變成了 let
// 還剩下一個沒法自動修復的錯誤 
✖ 1 problem (1 error, 0 warnings)
error  'myNane' is not defined  no-undef

配合 TypeScript

一、因爲 ESLint 默認使用 Espree 進行語法解析,沒法識別 TypeScript 的一些語法,故咱們須要安裝 @typescript-eslint/parser,替代掉默認的解析器,別忘了同時安裝 typescript:vue

npm install --save-dev typescript @typescript-eslint/parser

二、接下來須要安裝對應的插件 @typescript-eslint/eslint-plugin 它做爲 eslint 默認規則的補充,提供了一些額外的適用於 ts 語法的規則。java

npm install --save-dev @typescript-eslint/eslint-plugin

三、修改配置文件node

module.exports = {
    extends: [
        'alloy',
    ],
    parser: '@typescript-eslint/parser',
    plugins: ['@typescript-eslint'],
    rules: {
        // 禁止使用 var
        'no-var': "error",
        // 優先使用 interface 而不是 type
        '@typescript-eslint/consistent-type-definitions': [
            "error",
            "interface"
        ]
    }
}
  • 以上配置中,咱們自定義了兩個規則,其中 no-var是 ESLint 原生的規則(咱們剛剛已經用到了這個規則,它被包含在alloy中,此處會覆蓋),@typescript-eslint/consistent-type-definitions 是 @typescript-eslint/eslint-plugin 新增的規則
  • 規則的取值通常是一個數組(上例中的 @typescript-eslint/consistent-type-definitions),其中第一項是 off、warn 或 error 中的一個,表示關閉、警告和報錯。後面的項都是該規則的其餘配置。
  • 若是沒有其餘配置的話,則能夠將規則的取值簡寫爲數組中的第一項(上例中的 no-var)。
關閉、警告和報錯的含義以下:
  • 關閉:禁用此規則
  • 警告:代碼檢查時輸出錯誤信息,可是不會影響到 exit code
  • 報錯:發現錯誤時,不只會輸出錯誤信息,並且 exit code 將被設爲 1(通常 exit code 不爲 0 則表示執行出現錯誤)

四、新建index.ts文件:react

var myName = 'Tom';
console.log(`My name is ${myNane}`);
console.log(`My name is ${myName.toStrng()}`);
type Foo = {};

五、在命令行輸入npx eslint index.ts,以下能夠看到報錯信息以及可修復項jquery

1:1   error  Unexpected var, use let or const instead  no-var
  2:27  error  'myNane' is not defined                   no-undef
  4:6   error  Use an `interface` instead of a `type`    @typescript-eslint/consistent-type-definitions

✖ 3 problems (3 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

腳本命令檢查整個項目

一、根目錄新建一個src文件夾,將咱們的index.jsindex.ts放進去
二、在package.json中的scripts新增:git

{
    "scripts": {
        // 由於eslint不是全局安裝的,因此要使用npx
        "eslint": "npx eslint src --ext .js,.ts,tsx"
        // eslint 默認不會檢查 .ts 後綴的文件,因此須要加上參數 --ext .ts
    }
}

三、而後npm run lint就能夠看到src下全部指定後綴文件的報錯信息

推薦使用 AlloyTeam 的配置

  • 上面手把手完成了ESLint的配置過程
  • 有必定經驗的推薦直接使用AlloyTeam實現可自定義拓展的ESLint規則
  • AlloyTeam/eslint-config-alloy已經幫咱們集成了各類技術棧

一、安裝技術棧相關依賴

// Eslint
npm install --save-dev eslint babel-eslint eslint-config-alloy
// React
npm install --save-dev eslint babel-eslint eslint-plugin-react eslint-config-alloy
// Vue
npm install --save-dev eslint babel-eslint vue-eslint-parser eslint-plugin-vue eslint-config-alloy
// TypeScript
npm install --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-alloy
// TypeScript React
npm install --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-config-alloy

二、配置.eslintrc.js文件

/* .eslintrc.js */
module.exports = {
    extends: [
        'alloy', // 都須要
        'alloy/vue', //vue項目須要
        'alloy/react', //react項目須要
        'alloy/typescript', //ts項目須要
    ],
    env: {
        // 你的環境變量(包含多個預約義的全局變量)
        //
        // browser: true,
        // node: true,
        // mocha: true,
        // jest: true,
        // jquery: true
    },
    globals: {
        // 你的全局變量(設置爲 false 表示它不容許被從新賦值)
        //
        // myGlobal: false
    },
    rules: {
        // 自定義你的規則
    }
};

三、接下來就能夠直接用eslint命令檢查文件了
四、這樣就引入了alloy團隊的lint規則了,而後能夠用rules覆蓋你不爽的規則,直接採用開源規則是爲了不重複造輪子,你也能夠選擇別的團隊,或者本身定義一套

VSCode 集成 ESLint 檢查

在編輯器中集成 ESLint 檢查,能夠在開發過程當中就發現錯誤,甚至能夠在保存時自動修復錯誤,極大的增長了開發效率

一、先安裝 ESLint 插件,打開 VSCode 點擊「擴展」按鈕,搜索 ESLint,而後安裝便可
二、在「文件 => 首選項 => 設置 => 工做區」中(也能夠在項目根目錄下建立一個配置文件 .vscode/settings.json),添加如下配置:

{
    // VSCode 中的 ESLint 插件默認是不會檢查 `.vue`、`.ts` 或 `.tsx` 後綴的
    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "vue",
        "typescript",
        "typescriptreact"
    ],
    // 開啓保存時自動修復
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    // 指定VSCode用於IntelliSense(智能感知)的ts版本,將內置版本更換爲工做區版本
    "typescript.tsdk": "node_modules/typescript/lib"
}

結合 Prettier 使用

Prettier 是一個代碼格式化工具,相比於 ESLint 中的代碼格式規則,它提供了更少的選項,可是卻更加專業。
AlloyTeam 推薦用 Prettier 管理格式化相關的規則,用 ESLint 來檢查它更擅長的邏輯錯誤。

配置 Prettier

一、安裝 Prettier

npm install --save-dev prettier

二、配置 .prettierrc.js 僅供參考:

// .prettierrc.js
module.exports = {
    // 一行最多 100 字符
    printWidth: 100,
    // 使用 4 個空格縮進
    tabWidth: 4,
    // 不使用縮進符,而使用空格
    useTabs: false,
    // 行尾須要有分號
    semi: true,
    // 使用單引號
    singleQuote: true,
    // 對象的 key 僅在必要時用引號
    quoteProps: 'as-needed',
    // jsx 不使用單引號,而使用雙引號
    jsxSingleQuote: false,
    // 末尾不須要逗號
    trailingComma: 'none',
    // 大括號內的首尾須要空格
    bracketSpacing: true,
    // jsx 標籤的反尖括號須要換行
    jsxBracketSameLine: false,
    // 箭頭函數,只有一個參數的時候,也須要括號
    arrowParens: 'always',
    // 每一個文件格式化的範圍是文件的所有內容
    rangeStart: 0,
    rangeEnd: Infinity,
    // 不須要寫文件開頭的 @prettier
    requirePragma: false,
    // 不須要自動在文件開頭插入 @prettier
    insertPragma: false,
    // 使用默認的折行標準
    proseWrap: 'preserve',
    // 根據顯示樣式決定 html 要不要折行
    htmlWhitespaceSensitivity: 'css',
    // 換行符使用 lf
    endOfLine: 'lf'
};

VSCode 集成 Prettier

一、在.vscode/settings.json中添加配置:

{
    // 保存時自動格式化全部支持文件 javascript/javascriptreact/typescript/typescriptreact/json/graphql
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode",
}

二、這時咱們保存文件的時候,已經能夠自動格式化了
三、也能夠指定格式化文件類型:

{
    // Set the default
    "editor.formatOnSave": false,
    // Enable per-language
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true
    }
}

Git 代碼預檢

  • 上面咱們配置了ESLint、Prettier集成了VSCode插件,實現了錯誤提示和保存自動修復
  • 然而自動修復的只是小部分,若是團隊成員不按規範,依然能夠將不規範的代碼推送至遠程代碼庫
  • 咱們經過Git 代碼預檢,必定程度防止不規範的代碼被提交

實現過程

  1. 待提交的代碼
  2. git add 添加到暫存區
  3. 執行 git commit(這時進行代碼預檢)
  4. husky註冊在git pre-commit的鉤子調起 lint-staged
  5. lint-staged 取得全部被提交的文件依次執行寫好的任務
  6. 若是有錯誤(沒經過ESlint檢查)則中止任務,等待下次commit,同時打印錯誤信息
  7. 成功提交後,git push推送到遠程庫

什麼是 git hook

  • git hook就是.git文件夾的hooks下的一些鉤子函數,特定時機他們將被調用
  • 查看全部 git 鉤子函數:
cd .git/hooks
ls -l
// 打印以下:
total 96
-rwxr-xr-x  1 zzc  staff   478 10 21  2019 applypatch-msg.sample
-rwxr-xr-x  1 zzc  staff   896 10 21  2019 commit-msg.sample
-rwxr-xr-x  1 zzc  staff  3327 10 21  2019 fsmonitor-watchman.sample
-rwxr-xr-x  1 zzc  staff   189 10 21  2019 post-update.sample
-rwxr-xr-x  1 zzc  staff   424 10 21  2019 pre-applypatch.sample
-rwxr-xr-x  1 zzc  staff  1638 10 21  2019 pre-commit.sample
-rwxr-xr-x  1 zzc  staff  1348 10 21  2019 pre-push.sample
-rwxr-xr-x  1 zzc  staff  4898 10 21  2019 pre-rebase.sample
-rwxr-xr-x  1 zzc  staff   544 10 21  2019 pre-receive.sample
-rwxr-xr-x  1 zzc  staff  1492 10 21  2019 prepare-commit-msg.sample
-rwxr-xr-x  1 zzc  staff  3610 10 21  2019 update.sample
  • .sample爲各個鉤子的案例腳本,能夠把sample去掉,直接編寫shell腳原本執行。
  • 而前端能夠用插件husky與pre-commit,來使鉤子生效。

husky 註冊 git hook

Requires Node >= 10 and Git >= 2.13.0.
  • husky新老版本的配置方式和使用變化較大,老版本請自行升級,詳見 husky

一、安裝 husky

npm install husky --save-dev

二、編輯 package.json 文件:

{
    "husky": {
        "hooks": {
            "pre-commit": "eslint src/**/*.js"
        }
    },
}

三、嘗試 git commit 提交,就會先執行eslint src/**/*.js,代碼沒有問題纔會被真正提交
四、這樣每次提交代碼,eslint都會檢查全部文件,若是報錯過多,必定會崩潰

lint-staged 只 Lint 改動代碼

lint-staged requires Node.js version 10.13.0 or later.
  • v10.0.0 之後對原始暫存文件的任何新修改都將自動添加到提交中。若是您的任務之前包含一個git add步驟,請刪除此步驟,同時運行多個git操做一般會致使錯誤,詳見 lint-staged

一、安裝 lint-staged

npm install lint-staged --save-dev

二、新增 package.json 配置:

{
    "lint-staged": {
        "src/**/*.js": "eslint"
    }
}

三、如此husky只負責註冊git hook,後續操做交給lint-staged,只對改動的文件執行任務,並且能夠很方便
地配置多條命令:

{
    "husky": {
        "hooks": {
            "pre-commit": "lint-staged"
        }
    },
    "lint-staged": {
        "src/**/*.js": ["eslint --fix", "prettier --write"]
    }
}

四、如上,咱們提交代碼以前,程序會自動修復eslint配置,格式化prettier配置

幾點建議

  • 建議代碼提交只作檢查和測試,攔截問題代碼比較好,仍是在保存時,自動修復eslint、prettier配置,並且大部分還須要手動修復才行
  • 實在緊急,也可經過git commit -m -n "跳過代碼代碼預檢"跳過檢查,慎用
  • 和構建有關的包建議使用--save-dev安裝在項目內部
  • 老版本husky lint-staged配置都放在package.json中,如今eslint prettier husky lint-staged都支持多種後綴配置文件,建議採用.js統一格式,也方便拓展:

統一配置文件格式

// .eslintrc.js
module.exports = {
    extends: [
        'alloy',
    ],
};
// .prettierrc.js
module.exports = {
    // 一行最多 100 字符
    printWidth: 100,
    // 使用 4 個空格縮進
    tabWidth: 4,
    // ...
};
// .huskyrc.js
module.exports = {
  'hooks': {
    'pre-commit': "lint-staged"
  }
}
// .lintstagedrc.js
module.exports = {
  "src/**/*.{js,ts}": "eslint"
}

拓展現例

  • .huskyrc.js
// 數組方式配置多條命令
const tasks = arr => arr.join(' && ')
module.exports = {
  'hooks': {
    'pre-commit': tasks([
      'npm run lint',
      'npm test'
    ])
  }
}
  • .lintstagedrc.js
module.exports = {
    // 若是超過10個暫存文件,則在整個存儲庫上運行eslint
    '**/*.js?(x)': (filenames) =>
    filenames.length > 10 ? 'eslint .' : `eslint ${filenames.join(' ')}`,
    "*.css": "stylelint",
    "*.scss": "stylelint --syntax=scss",
    // 對ts文件運行tsc,但不傳遞任何參數
    '**/*.ts?(x)': () => 'tsc -p tsconfig.json --noEmit'
}
相關文章
相關標籤/搜索