前端要做代碼規(guī)范

Why

團(tuán)隊(duì)開發(fā)中,每個(gè)人的編碼習(xí)慣不同,代碼格式不同。這就會(huì)導(dǎo)致代碼難看,難以維護(hù)。統(tǒng)一代碼風(fēng)格可以:

  1. 增強(qiáng)代碼的可讀性,降低維護(hù)成本
  2. 有利于代碼審查
  3. 養(yǎng)成規(guī)范代碼的習(xí)慣,有利于自身成長(zhǎng)

How

推薦使用 eslint + prettier 來進(jìn)行代碼格式化。

通過 git hook 調(diào)用來實(shí)現(xiàn)代碼的自動(dòng)格式化,git hooks 工具推薦 husky。

既然用到了 git hook,順便把提交信息規(guī)范也做一下,這里推薦 commitlint。

用到的插件

  1. eslint: js/jsx 語法檢查插件
    按照已有配置檢查 js/jsx 語法,能拋出錯(cuò)誤、警告,并且能修復(fù)一部分錯(cuò)誤
  2. stylelint: css樣式格式化工具
  3. prettier: 代碼格式化插件
    按照已有配置進(jìn)行代碼格式化
  4. husky: git hooks 工具
    對(duì) git 執(zhí)行的一些命令,通過對(duì)應(yīng)的 hooks 觸發(fā),執(zhí)行自定義的腳本程序。
    比如,我們可以定義pre-commit鉤子的腳本為npm run test。這樣在代碼提交前就會(huì)執(zhí)行npm run test
  5. lint-staged: 在 git 暫存區(qū)運(yùn)行 linters 的工具
    只檢查暫存區(qū)內(nèi)容,避免每次 lint 執(zhí)行都針對(duì)所有代碼
    相當(dāng)于每次只對(duì)修改的內(nèi)容執(zhí)行 eslint + prettier 格式化
  6. commitlint: 提交信息檢查工具
    檢查提交信息是否符合規(guī)范

eslint 7.x

1. 安裝

cnpm install eslint -D

2. 使用

  • 配置 eslint
    eslint --init添加 eslint 配置文件。然后修改配置,具體配置如下:
module.exports = {
    // 特定項(xiàng)目下,不再檢索上級(jí)目錄
    root: true,
    env: {
        browser: true,
        es6: true,
        node: true,
        amd: true
    },
    extends: [
        'eslint:recommended',
        'plugin:react/recommended',
        // eslint-config-prettier的縮寫
        'prettier'
    ],
    plugins: ['react'],
    // 解析器選項(xiàng)
    parserOptions: {
        sourceType: 'module',
        ecmaFeatures: {
            jsx: true
        }
    },
    settings: {
        react: {
            version: 'detect'
        }
    },
    rules: {
        'no-unused-expressions': 'off',
        'no-unused-vars': 'warn',
        'no-debugger': 'error',
        'no-unreachable': 'warn',
        'react/prop-types': 'off'
    }
};

這里,我們用到了幾個(gè) eslint 的插件,需要安裝:

cnpm install eslint-config-prettier eslint-plugin-react -D

eslint-config-prettier 的作用是使用 Prettier 默認(rèn)推薦配置,并且關(guān)閉 eslint 自身的格式化功能,防止 Prettier 和 ESLint 的自動(dòng)格式化的沖突

在 package.json 的 scripts 里添加 eslint 腳本命令,如下:

"scripts": {
  // ...
  "eslint": "eslint --ext js,jsx src --fix",
},

值得注意的是,這里我們指定了 src 目錄,所以沒必要再加.eslintignore文件了。
npm run eslint即可進(jìn)行 eslint 檢查和修復(fù)(只能修復(fù)部分格式的問題)。

stylelint14.x

1. 安裝

cnpm install stylelint -D

2. 配置

創(chuàng)建.stylelintrc.js,增加以下配置:

module.exports = {
  extends: ["stylelint-config-standard-scss", "stylelint-config-prettier"],
  plugins: ["stylelint-order"],
  defaultSeverity: "warning",
  overrides: [],
  rules: {
    "color-no-invalid-hex": true,
    "annotation-no-unknown": true,
    "function-calc-no-unspaced-operator": true,
    "function-no-unknown": true,
    "block-no-empty": true,
    "unit-allowed-list": ["em", "rem", "s", "%", "px", "vw", "vh"],
    "no-duplicate-selectors": true,
    "selector-class-pattern": null,
    "order/properties-order": [
      "position",
      "top",
      "right",
      "bottom",
      "left",
      "z-index",
      "display",
      "justify-content",
      "align-items",
      "float",
      "clear",
      "overflow",
      "overflow-x",
      "overflow-y",
      "margin",
      "margin-top",
      "margin-right",
      "margin-bottom",
      "margin-left",
      "border",
      "border-style",
      "border-width",
      "border-color",
      "border-top",
      "border-top-style",
      "border-top-width",
      "border-top-color",
      "border-right",
      "border-right-style",
      "border-right-width",
      "border-right-color",
      "border-bottom",
      "border-bottom-style",
      "border-bottom-width",
      "border-bottom-color",
      "border-left",
      "border-left-style",
      "border-left-width",
      "border-left-color",
      "border-radius",
      "padding",
      "padding-top",
      "padding-right",
      "padding-bottom",
      "padding-left",
      "width",
      "min-width",
      "max-width",
      "height",
      "min-height",
      "max-height",
      "font-size",
      "font-family",
      "font-weight",
      "text-align",
      "text-justify",
      "text-indent",
      "text-overflow",
      "text-decoration",
      "white-space",
      "color",
      "background",
      "background-position",
      "background-repeat",
      "background-size",
      "background-color",
      "background-clip",
      "opacity",
      "filter",
      "list-style",
      "outline",
      "visibility",
      "box-shadow",
      "text-shadow",
      "resize",
      "transition"
    ]
  }
};

這里, 我們用到了幾個(gè)插件:
stylelint-config-standard-scss: stylelint默認(rèn)規(guī)則只能格式化css,這里我們使用該插件的規(guī)則來格式化scss。
stylelint-config-prettier: 避免stylelint與prettier沖突的插件。
stylelint-order: 給屬性排序的插件。屬性會(huì)按照rules里 order/properties-order 所定義的順序排序。
此外,我們還要安裝stylelint-scss,因?yàn)閟tylelint默認(rèn)是沒有格式化scss的能力的。
安裝:

cnpm install stylelint-scss stylelint-config-standard-scss stylelint-config-prettier stylelint-order -D

在 package.json 的 scripts 里添加 stylelint 腳本命令,如下:

"scripts": {
  // ...
  "stylelint": "stylelint src/**/*.{less,scss,css} --fix",
},

使用npm run stylelint即可對(duì)src下的樣式文件進(jìn)行格式化。

prettier

1. 安裝

cnpm install prettier -D

2. 使用

  • 配置 prettier
    創(chuàng)建 prettierrc.js 文件:
echo module.exports = {}>.prettierrc.js

添加配置,這里可以根據(jù)自己需要調(diào)整風(fēng)格。比如:

module.exports = {
  printWidth: 120,
  tabWidth: 2,
  useTabs: false,
  semi: true,
  singleQuote: false,
  jsxSingleQuote: true,
  jsxBracketSameLine: true,
  trailingComma: "none",
  bracketSpacing: true
};

最好再加上.prettierignore文件,避免把不必要的文件也進(jìn)行格式化。

#ignore
node_modules
.DS_Store
yarn*
*-lock*
dist*
public/

prettier --write即可進(jìn)行 prettier 格式化。

lint-stated 13.x

1. 安裝

cnpm install lint-staged -D

2. 使用

  • 在 package.json 里添加 lint-staged 選項(xiàng)
"lint-staged": {
  "**/*.{js,jsx,ts,tsx}": [
    "eslint --fix"
  ],
  "**/*.{js,jsx,ts,tsx,cjs,json,less,scss,css,md}": [
    "prettier --write"
  ],
  "**/*.{less,scss,css}": [
    "stylelint --fix"
  ]
},
  • 在 package.json 的 scripts 里添加 lint-staged 腳本命令
"scripts": {
  // ...
  "lint-staged": "lint-staged"
},

這樣,當(dāng)我們使用npm run lint-staged的時(shí)候,就會(huì)自動(dòng)調(diào)用 eslint+prettier 格式化。

commitlint

1. 安裝

cnpm install --save-dev @commitlint/config-conventional @commitlint/cli

2. 使用

  • 初始化 commitlint 配置文件
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
  • 配置 commitlint
    1. 提交信息結(jié)構(gòu)
      通常 commitlint 認(rèn)為我們提交信息格式如下:
type(scope?): subject
body?
footer?

其中, scope/body/footer 這三個(gè)可有可無。

  1. 校驗(yàn)規(guī)則
    一般的校驗(yàn)規(guī)則格式如下:
    [規(guī)則名稱]: [level, when, value]
    level: 有三個(gè)參數(shù)。0 代表禁用, 1 代表警告, 2 代表錯(cuò)誤
    when: 有兩個(gè)參數(shù)。always 代表總是, never 代表從不
    value: 參數(shù)值
    比如:
"subject-empty": [2, "never"],
"body-empty": [2, "always"],
"type-enum": [2, "always", ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'revert']]

就是強(qiáng)制 body 必須為空,subject 不可為空,type 必須是上面數(shù)組里的其中一個(gè)。不然就報(bào)錯(cuò)。

git commit -m "feat: 增加了新功能"
git commit -m "fea: 增加了新功能" // 報(bào)錯(cuò),type 必須為'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'revert'中的一個(gè)

更多規(guī)則參考官網(wǎng)
https://commitlint.js.org/#/reference-rules

  1. 自定義校驗(yàn)規(guī)則
    如果已有的規(guī)則滿足不了需求,我們還可以自定義校驗(yàn)規(guī)則。自定義校驗(yàn)規(guī)則寫在 plugins 屬性中。
module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "type-empty": [2, "always"],
    "scope-empty": [2, "always"],
    "subject-empty": [2, "always"],
    "header-max-length": [2, "always", 100],
    "body-empty": [2, "always"],
    "footer-empty": [2, "always"],
    "action-enum": [
      2,
      "always",
      ["Fixed", "Feature",  "Add", "Modify", "Update", "Delete"]
    ],
    "issue-rule": [2, "always", ["TMP", "TTT"]] // 根據(jù)自己需要輸入即可
  },
  plugins: [
    {
      rules: {
        "action-enum": ({ raw }, when = "always", value = []) => {
          return [
            value.includes(raw.split(" ")[0]),
            `提交信息不合規(guī)范! {Action}錯(cuò)誤!
    必須以 "{Action}{空格}#{標(biāo)號(hào)}{空格}" 開頭。
    {Action}可選:${value.join("|")}
    比如: Fixed #TMP-111 修復(fù)接口傳參錯(cuò)誤的問題
    ${when === "never" ? "另外: action-enum規(guī)則第二個(gè)參數(shù)必須是always, 建議修改" : ""}...`
          ];
        },
        "issue-rule": ({ raw }, when, value = []) => {
          const issueStr = `^([A-Z][a-z]*\\s#(${value.join("|")})\\-[1-9][0-9]*)`;
          const issueReg = new RegExp(issueStr, "g");
          return [
            issueReg.test(raw),
            `提交信息不合規(guī)范! {標(biāo)號(hào)}錯(cuò)誤!
    必須以 "{Action}{空格}#{標(biāo)號(hào)}{空格}" 開頭。
    {標(biāo)號(hào)}可選: ${value.join("|")}
    比如: Fixed #TMP-111 修復(fù)接口傳參錯(cuò)誤的問題
    ${when === "never" ? "另外: action-enum規(guī)則第二個(gè)參數(shù)必須是always, 建議修改" : ""}...`
          ];
        }
      }
    }
  ]
};

這里,我把 type, scope, subject, body, footer 都強(qiáng)制為空,然后自定義了兩個(gè)規(guī)則action-enumissue-rule。
提交代碼的時(shí)候,如果不符合'必須以 "{Action}{空格}#{標(biāo)號(hào)}{空格}" 開頭'的規(guī)則,就會(huì)報(bào)錯(cuò),提交失敗。例如:

git commit -m "Fixed #TMO-222 修復(fù)了傳參錯(cuò)誤的bug"

由于我們定義的標(biāo)號(hào)前綴里面沒有TMO,因此會(huì)報(bào)錯(cuò):


husky 8.x

1. 安裝

cnpm install husky -D

2. 使用

npm set-script prepare "husky install"
npm run prepare

這里我們?cè)?scripts 加了一個(gè) prepare 命令,這個(gè)命令會(huì)在執(zhí)行 npm install 時(shí)自動(dòng)執(zhí)行。

npx husky add .husky/pre-commit "npm run lint-staged"
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

這里我們添加了兩個(gè)鉤子,pre-commit 與 commit-msg。

pre-commit 會(huì)在提交前執(zhí)行npm run lint-staged命令

commit-msg 會(huì)在提交時(shí)執(zhí)行npx --no-install commitlint --edit "$1"

至此,我們的配置完成。代碼提交的時(shí)候會(huì)自動(dòng)對(duì)修改的代碼進(jìn)行格式化,同時(shí)會(huì)按照 commitlint 里的設(shè)置來進(jìn)行提交信息校驗(yàn)。
如果有問題,則會(huì)報(bào)錯(cuò),且代碼會(huì)提交失敗。

vscode 插件

1. eslint 和 prettier 插件

推薦使用 vscode 插件 eslint 和 prettier,可以在 settings.json 中設(shè)置:

"editor.formatOnSave": true,
"eslint.run": "onSave"

當(dāng)我們保存的時(shí)候,會(huì)自動(dòng)進(jìn)行格式化, 會(huì)自動(dòng)把 eslint 的錯(cuò)誤語法用波浪線標(biāo)出來。

2. 把 eslint 和 prettier 插件配置加到項(xiàng)目目錄

vscode 的配置分兩類,工作區(qū)和用戶區(qū)。工作區(qū)的優(yōu)先級(jí)高于用戶區(qū)。
在項(xiàng)目根目錄加上.vscode 文件夾,里面是 settings.json 文件。
那么我們的項(xiàng)目就是一個(gè)工作區(qū)了。
修改 settings.json 配置如下:

{
  "[javascriptreact]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "editor.formatOnSave": true,
  "eslint.run": "onSave"
}

這樣就完成了 vscode 配置的共享。


參考資料:
husky官方文檔
lint-staged官方文檔
commitlint官方網(wǎng)站
commitlint 從0到1 (git commit 校驗(yàn)工具)
前端架構(gòu)師神技,三招統(tǒng)一代碼風(fēng)格(一文講透)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容