自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

構(gòu)建可靠的前端項目 - 少不了這些必備工具集

開發(fā) 前端
**在使用 ESLint 時,另一個被搭配使用的工具是 ****Prettier**[6],這是一個專業(yè)的代碼格式化工具,支持 JS、TS、HTML、CSS 等眾多語言 。

構(gòu)建可靠的前端項目少不了這些必備工具集: ESLint、Prettier、Editorconfig、Husky、lint-staged、commitlint,它能幫助我們約束編碼風(fēng)格與提及規(guī)范,下文介紹這些工具集的使用,文末提供一些可參考的項目。

ESLint 代碼質(zhì)量檢測

ESLint 是 JavaScript/TypeScript 編程中一個最受歡迎的代碼規(guī)范檢查工具,可避免一些由于低級的代碼錯誤而導(dǎo)致的項目崩潰,另一方面也能規(guī)范我們的編碼習(xí)慣。

ESLint 基本使用

為項目開發(fā)時依賴添加 eslint 插件 npm i eslint -D,緊接著我們需要設(shè)置一個配置文件,如果沒有全局安裝 eslint 插件,可能就需要這樣去做 ./node_modules/.bin/eslint --init,我不喜歡這樣,好在還有 npx 這個工具,我們可以這樣做 npx eslint --init。

執(zhí)行 --init 命令后,可以選擇使用的框架、模塊類型、語言(JS/TS)等,隨后會生成一個 .eslint{yml|js|json} 文件。

$ npx eslint --init
? How would you like to use ESLint? · problems
? What type of modules does your project use? · esm
? Which framework does your project use? · react
? Does your project use TypeScript? · No / Yes
? Where does your code run? · browser
? What format do you want your config file to be in? · YAML

ESLint 支持 JavaScript、JSON 或者 YAML 等多種文件格式,這里使用的是 YAML 格式,相比于 JSON 可以寫一些注釋。

env:
  browser: true
  es2021: true
extends:
  - eslint:recommended
  - plugin:react/recommended
  - plugin:@typescript-eslint/recommended
parser: '@typescript-eslint/parser'
parserOptions:
  ecmaFeatures:
    jsx: true
  ecmaVersion: 13
  sourceType: module
plugins:
  - react
  - '@typescript-eslint'
rules: {}

對上述文件幾個配置做一些簡單介紹:

  • extends:這是一個擴展,可以集成一些社區(qū)的最佳實踐,在其基礎(chǔ)之上做一些自定義配置,下文我們介紹如何使用 airbnb。
  • plugins:這里是用來加載第三方插件,在使用之前必須 NPM 安裝它。
  • parserOptions:指定想要支持的 JavaScript 語言

jsx:啟用 JSX

ecmaFeatures:想使用的額外的語言特性

  • rules:指定了代碼檢查的規(guī)則,參考 ESLint 官網(wǎng) Rules[1], 規(guī)則分為幾個等級,用來表示嚴重程度:
  • 關(guān)閉:'off' 或 0,

  • 警告級別:'warn' 或 1,不會導(dǎo)致程序退出

  • 錯誤級別:'error' 或 2,會導(dǎo)致程序退出。

有了以上配置后,就可以執(zhí)行 npx eslint ./your_file_or_directory 命令檢測指定的文件或目錄。

忽略特定文件或目錄

在項目根目錄創(chuàng)建 .eslintignore 文件告訴 ESLint 忽略掉某些特定的文件或目錄。忽略模式可以參照 .gitignore 規(guī)范[2]。

# dependencies
/node_modules
# testing
/coverage
# production
/build

站在巨人的肩膀上 - 制定編碼規(guī)范

怎么設(shè)計一套好的編碼規(guī)范呢?也無需重頭造輪子,借助一些社區(qū)開源的編碼規(guī)范最佳實踐,可以直接引入在我們的項目中,再根據(jù)自己的需求做一些定制。

我們這里以 Airbnb 為基礎(chǔ),做一些自定義的修改,參考 Airbnb JavaScript 風(fēng)格指南[3]。

安裝 eslint-config-airbnb[4] npm i eslint-config-airbnb -D,如果你不需要 React,可以參考 eslint-config-airbnb-base[5] 這個包,在 Node.js 服務(wù)端可以使用這個包。之后添加 "extends": "airbnb" 到你的 .eslintrc 文件。

env:
  browser: true
  es2021: true
extends:
  - airbnb
  - plugin:@typescript-eslint/recommended
  - plugin:react/jsx-runtime # React v17 需添加
parser: '@typescript-eslint/parser' # 解析 TS
parserOptions:
  ecmaFeatures:
    jsx: true
  ecmaVersion: 13
  sourceType: module
plugins:
  - react
  - '@typescript-eslint'
settings:
  import/resolver:
    node:
      # https://github.com/import-js/eslint-plugin-import#resolvers
      extensions:
        - ".js"
        - ".jsx"
        - ".ts"
        - ".tsx"
rules: {
  # "@typescript-eslint/explicit-module-boundary-types": 2,
  no-console: 0,

  # https://stackoverflow.com/questions/55614983/jsx-not-allowed-in-files-with-extension-tsxeslintreact-jsx-filename-extensio
  react/jsx-filename-extension: [
    2,
    {
      extensions: ['.js', '.jsx', '.ts', '.tsx']
    }
  ],

  import/extensions: 0,

  # https://stackoverflow.com/questions/69928061/struggling-with-typescript-react-eslint-and-simple-arrow-functions-components
  react/function-component-definition: 0,

  comma-dangle: 0
}

IDE 自動提示

每改動代碼都運行 npx eslint ./ 命令執(zhí)行代碼檢測,效率還是有點低效的,我們希望改動代碼后,IDE 能夠給我們自動提醒格式錯誤的代碼片段。

在 VS Code 中,需要在應(yīng)用商店安裝 ESLint 插件。

圖片圖片

當(dāng)我沒有遵守 ESLint 規(guī)范去修改代碼后,編輯器會及時給我們一些錯誤提示。

圖片圖片

Prettier 代碼格式化

**在使用 ESLint 時,另一個被搭配使用的工具是 ****Prettier**[6],這是一個專業(yè)的代碼格式化工具,支持 JS、TS、HTML、CSS 等眾多語言 。

Prettier 基本使用

開發(fā)時依賴安裝 Prettier,并創(chuàng)建一個空的配置文件,讓編輯器和其它工具知道正在使用 Prettier。

$ npm install --save-dev --save-exact prettier
$ echo {}> .prettierrc.json

創(chuàng)建 .prettierignore 文件,讓編輯器和 Prettier CLI 知道哪些文件不需要格式化,它建立在 .gitignore .eslintignore 之上。

$ touch .prettierignore

# Ignore artifacts:
build
coverage

手動觸發(fā)

命令行執(zhí)行 **npx prettier --write .** 手動觸發(fā),對于一個大項目來說可能會花費一些時間,因此還可以指定目錄或文件來格式化。

npx prettier --write . # 格式化當(dāng)前目錄下的所有文件
npx prettier --write src/ # 格式化指定目錄下的所有文件
npx prettier --write src/App.tsx # 格式化指定的文件

有了 ESLint 為什么還要使用 Prettier

ESLint 提供了 eslint --fix 命令用來自動修復(fù)代碼格式問題,為什么還要用 Prettier 呢?

如果我說在代碼格式化方面 Prettier 比 ESLint 更專業(yè),你可能也不會信服,畢竟沒有證據(jù)來證明這一點。下面我將通過一個例子來驗證。

下面這段 JavaScript 代碼片段,存在兩個問題,一個是 console.log(...args) 沒有縮進,另外一個是 createData()  這一行超出了最大長度限制。

const createData = (...args) => {
console.log(...args);
}
createData({ name: 'name', age: 'age', sex: 'sex', birthday: 'birthday', ctime: 'ctime', utime: 'utime' })

調(diào)整 ESLint 行的最大長度限制。

# .eslintrc.yml
rules: {
  max-len: [2, { code: 80 }]

隨后控制臺執(zhí)行 eslint --fix 自動修復(fù)命令,發(fā)現(xiàn)雖然 console.log(...args) 這個縮進問題解決了,但是行的最大長度限制  max-len 還是未能解決。

圖片圖片

接下來看看 Prettier 的效果如何呢,修改配置文件同 ESLint 保持一致。

// .prettierrc.json
{
  "printWidth": 80
}

運行 prettier --write 命令后,它格式化了我們的代碼,結(jié)果是我們預(yù)期的。

圖片圖片

解決 ESLint 與 Prettier 沖突

ESLint 與 Prettier 之間存在交集部分,一起使用就少不了沖突。例如,我的 ESLint 配置規(guī)則繼承了 airbnb,而 airbnb 字符串默認使用單引號,而 Prettier 字符串默認使用雙引號。

// src/App.tsx
const str = "編程界";

// .eslintrc.yml
extends:
  - airbnb

// .prettierrc.json
{
 "singleQuote": false // 字符串默認使用雙引號
}

在第一次執(zhí)行 eslint --fix 格式化后的 str 為 const str = '編程界'; 幫我修復(fù)了這個格式問題,但是又運行了 Prettier 格式化后,ESLint 提示我們錯誤又出現(xiàn)了,這樣就陷入了一個死循環(huán)。

圖片圖片

正所謂術(shù)業(yè)有專攻,我們讓 ESLint 專注于代碼質(zhì)量檢測工作,Prettier 負責(zé)代碼的格式化工作。

解決方案第一步:開發(fā)時依賴安裝 eslint-config-prettier **npm i eslint-config-prettier -D** 插件,目的是禁用掉 ESLint 插件與 Prettier 之間沖突的規(guī)則。

# .eslintrc.yml
# extends 添加 prettier,此時沖突就已經(jīng)解決了
extends:
  - airbnb
  - prettier # eslint-config-prettier

解決方案第二步:賦予 eslint --fix 以 Prettier 規(guī)則格式化代碼的能力,并以 ESLint 的方式報告錯誤。開發(fā)時依賴安裝 eslint-plugin-prettier[7] npm i eslint-plugin-prettier -D 插件,按照以下規(guī)則配置。

# // .eslintrc.yml
plugins:
  - prettier # eslint-plugin-prettier
rules: {
  prettier/prettier: 2, # 賦予 ESLint 以 Prettier 規(guī)則格式化代碼的能力

上面的兩步操作也可以寫為一步,也是官方推薦的一個 https://github.com/prettier/eslint-plugin-prettier#recommended-configuration[8]

extends:
  - plugin:prettier/recommended

Prettier 與 ESLint 結(jié)合在 VS Code 中發(fā)現(xiàn)的一個提示問題

當(dāng)把 prettier 結(jié)合到 eslint 里時,usePrettierrc 這個參數(shù)表示是否使用 .prettierrc 文件中配置信息,默認是啟用的,無需配置。

# .eslintrc.yml
prettier/prettier: ["error", {}, {
  "usePrettierrc": true # 默認值
}]

prettier 規(guī)則默認箭頭函數(shù)如果只有一個參數(shù)也要加上 (),我想去掉這個規(guī)則,發(fā)現(xiàn)這個配置在 VSCode 展示有點問題無法讀取到修改后的 arrowParens 這個配置(其它配置例如  singleQuote,在 IDE 中是生效的), 編輯器會提示錯誤,但 eslint --fix 時沒有問題(此時證明 配置沒問題,手動執(zhí)行 eslint 還是生效的)。

# .prettierrc
{
 "arrowParens": "avoid",
  "singleQuote": true
}

圖片圖片

沒有好的解決方案,為了讓 IDE 不報錯,首先嘗試在 ESLint 配置里加上 arrowParens 這個配置,發(fā)現(xiàn)問題解決了,但是這樣 ESLint prettier 配置中、.prettierrc 要寫兩遍總歸不是太好。

另外一種是不在 ESLint 配置里加上 arrowParens 這個配置,編輯器關(guān)閉重新打開也是沒問題的,反復(fù)的試驗了下,發(fā)現(xiàn)改完 .prettierrc 這個配置文件,VS Code 編輯器提示不會立即生效還默認是打開前的配置,如果有遇到類似問題,可以嘗試關(guān)閉下再打開看看。

prettier/prettier: ["error", {
 "arrowParens": "avoid"
}, {
  "usePrettierrc": true # 默認值
}]

Editorconfig 編輯器代碼風(fēng)格

Editorconfig[9] 是用來維護不同編輯器之間代碼風(fēng)格,通過配置文件 .editorconfig 設(shè)置,該配置文件的優(yōu)先級會更高,會覆蓋任一編輯器的配置。

root = true

[*]
indent_style = space # 縮進使用空格
indent_size = 2 # 每一個縮進兩個空格
end_of_line = lf # 使用 Unix 風(fēng)格的換行符
insert_final_newline = true # 每個文件尾部都有一個新的換行符

# 為 JavaScript、Python 文件設(shè)置默認字符集
[*.{js,py}]
charset = utf-8

Husky 攔截 git 操作命令

團隊中既然制定了規(guī)則,大家就要共同遵守,如果不加以限制,別人改動代碼后不做 ESLint 檢查,或者提交代碼忘記執(zhí)行代碼檢查命令,就會導(dǎo)致未經(jīng)檢測的代碼被提交進項目倉庫,代碼規(guī)則的制定也就形同虛設(shè)了。

使用 git 版本控制的項目中,默認都有一個 .git/hooks 目錄,包含了 git 在 commit、push 時的一些 hooks 腳本,結(jié)合這些可以做一些代碼的校驗操作。

$ ls .git/hooks
applypatch-msg.sample           pre-commit.sample               prepare-commit-msg.sample
commit-msg.sample               pre-merge-commit.sample         push-to-checkout.sample
fsmonitor-watchman.sample       pre-push.sample                 update.sample
post-update.sample              pre-rebase.sample
pre-applypatch.sample           pre-receive.sample

使用 husky 工具,可以將 git hooks 的使用變得更加簡單,同時也能解決,.git 目錄提交無法跟蹤的問題。

在 husky 最新版本中,會生成一個 .husky/ 目錄,以往的版本中是在 package.json 中配置一個 { "husky": {"hooks": {} } } 實現(xiàn)的。

Husky 推薦在 package.json 的 scripts 里設(shè)置 prepare,因為在執(zhí)行 npm install 命令時,將會自動執(zhí)行 prepare 腳本。

注意在 npm version < 7 時 npm set-script 命令不支持,需要手動在 package.json 設(shè)置 { "scripts": { "prepare": "husky install" } } 或升級 Node.js 版本為 v16.x LTS。

$ npm install husky -D
$ npm set-script prepare "husky install"
$ npm run prepare # 設(shè)置 .husky 目錄

添加一個 hook,在 git commit 前執(zhí)行 eslint 命令檢測代碼規(guī)范。

$ npm set-script lint "eslint ./src/"
$ npx husky add .husky/pre-commit "npm run lint" # 設(shè)置在 git commit 前執(zhí)行 eslint 代碼檢查

現(xiàn)在執(zhí)行 git commit 命令如果存在不規(guī)范的代碼,本次 commit 就會被攔截。

圖片圖片

如果本次我只修改了 src/index.tsx 這個文件,由于歷史原因最開始沒有加 ESLint 規(guī)范,之前的一些未修改的文件也被檢查了,當(dāng)看到成百上千條 ESLint 報錯提示,是不是會出現(xiàn)想收回使用 ESLint 工具的想法?這種問題在團隊開發(fā)中,如果一開始沒有設(shè)定代碼規(guī)范,后期加入代碼規(guī)范時,這種問題還是會常見的,解決方案繼續(xù)往下看。

lint-staged 僅檢查修改的文件

每次只對修改的文件做檢查,就要用到 **lint-staged**[10] 這個工具了,解決老項目的歷史包袱問題。

lint-staged 是對 git add 進入暫存區(qū)的文件進行檢查,開發(fā)時依賴安裝 npm i lint-staged -D,修改 package.json 文件。

注意,**npx eslint --fix**** 后不要指定路徑,例如 **npx eslint --fix ./src/** 會出現(xiàn)只修改了 A 文件,但是其它有問題的 B、C 等文件也被檢測了**。

// package.json
{
  "srcripts": {
   "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,css,md,ts,tsx}": [
      "npx eslint --fix"
    ]
  }
}

修改 .husky 目錄下的 pre-commit 文件。執(zhí)行的流程是:

  • git commit 命令執(zhí)行后 git hook 被觸發(fā)
  • 進而執(zhí)行 precommit、該命令腳本又執(zhí)行了 lint-staged
  • lint-staged 則根據(jù)配置和只對 git add 到暫存區(qū)的文件進行掃描,執(zhí)行 eslint 代碼檢測。
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run precommit

commitlint 規(guī)范提交風(fēng)格

關(guān)于 commit 如果沒有進行規(guī)范,最終每個人寫出來的風(fēng)格也是不一樣的,所以這個還得借助于工具,幫助我們規(guī)范提交的習(xí)慣。

分享兩個 git commit message 的討論:Stackoverflow - Git Commit Messages: 50/72 Formatting[11]、知乎 - 如何寫好 Git commit log?[12]

commitlint

安裝 commitlint cli 和提交信息校驗規(guī)則 @commitlint/config-conventional[13],詳細的參考文檔 commitlint.js.org[14]。

# 安裝 commitlint cli and conventional config
$ npm install --save-dev @commitlint/{config-conventional,cli}

# 創(chuàng)建 commitlint.config.js 配置文件
# @commitlint/config-conventional 是推薦的 commit message 校驗配置,
$ echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

# husky 添加 commit-msg 文件
$ npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

使用格式 git commit -m '<type>[Optional scope]: <description>',介紹一下 type 屬性的幾種類型約束。

  • build:修改了構(gòu)建系統(tǒng),例如前端的 Webpack 構(gòu)建工具
  • chore:
  • ci:持續(xù)集成工具的修改,例如 Jenkins
  • docs:文檔
  • feat:新功能
  • fix:Bug 修復(fù),這個用的就比較多了~
  • perf:做的一些性能提升
  • refactor:重構(gòu)
  • revert:回滾之前某個 commit
  • style:代碼格式的修改,例如通過 Prettier 格式化代碼,但不會影響邏輯
  • test:測試

如果我這樣 git commit -m '添加 commitlint 工具' 提交代碼,就會收到以下錯誤提示。

圖片圖片

正確的做法是加上類型信息 git commit -m 'feat: 添加 commitlint 工具'。

commitzen

使用 commitlint 每次都需要輸入類型,需要我們記住這些規(guī)范,于是就有了 [commitizen](https://github.com/commitizen/cz-cli "commitizen")。

全局安裝 npm install -g commitizen,之后可以使用 git cz 替代 git commit 命令。還需要為 commitizen 指定一個 Adapter,例如 cz-conventional-changelog[15] 基于 commit message 的輕量級約定,提供了一組簡單的規(guī)則來創(chuàng)建明確的提交歷史,參考 約定式提交[16]。

$ commitizen init cz-conventional-changelog --save-dev --save-exact

執(zhí)行以上命令后,在 package.json 中會生成如下配置

{
 "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

對文件做一些任意修改,執(zhí)行 git cz 命令后,運行效果如下所示:

圖片圖片

當(dāng)選擇一個類型后,終端會出現(xiàn)一個交互式的操作,包括:影響范圍、簡短的變更描述(必須)、詳細的變更描述、是否存在不兼容的變更、是否影響某些打開的 Issues,這個里面只有簡短的變更描述是必填的。

圖片圖片

commit message 成功后,執(zhí)行 git log 看到的日志是這樣子的。

圖片圖片

如果想自定義 Adapter 而不是使用 cz-conventional-changelog,推薦看下 cz-customizable[17] 這個開源項目,這里不再過多描述。

standard-version

結(jié)合 standard-version[18] 實現(xiàn)自動生成  CHANGELOG。

$ npm i --save-dev standard-version

// package.json
{
  "scripts": {
    "release": "standard-version"
  }
}

以上介紹內(nèi)容,實際應(yīng)用可參考這個前后端項目 https://github.com/qufei1993/compressor[19],不同的是該項目是基于 TypeScript 編寫,正好也可以學(xué)習(xí)下。

參考資料

[1]ESLint 官網(wǎng) Rules: https://cn.eslint.org/docs/rules/

[2].gitignore 規(guī)范: https://git-scm.com/docs/gitignore

[3]Airbnb JavaScript 風(fēng)格指南: https://github.com/lin-123/javascript

[4]eslint-config-airbnb: https://www.npmjs.com/package/eslint-config-airbnb

[5]eslint-config-airbnb-base: https://www.npmjs.com/package/eslint-config-airbnb-base

[6]Prettier: https://prettier.io/

[7]eslint-plugin-prettier: https://github.com/prettier/eslint-plugin-prettier

[8]https://github.com/prettier/eslint-plugin-prettier#recommended-configuration: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration

[9]Editorconfig: https://editorconfig.org/

[10]lint-staged: https://github.com/okonet/lint-staged

[11]Stackoverflow - Git Commit Messages: 50/72 Formatting: https://stackoverflow.com/questions/2290016/git-commit-messages-50-72-formatting

[12]知乎 - 如何寫好 Git commit log?: https://www.zhihu.com/question/21209619/answer/257574960

[13]@commitlint/config-conventional: https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional

[14]commitlint.js.org: https://commitlint.js.org/

[15]cz-conventional-changelog: https://github.com/commitizen/cz-conventional-changelog

[16]約定式提交: https://www.conventionalcommits.org/zh-hans/v1.0.0/

[17]cz-customizable: https://github.com/leoforfree/cz-customizable

[18]standard-version: https://github.com/conventional-changelog/standard-version

[19]https://github.com/qufei1993/compressor: https://github.com/qufei1993/compressor

責(zé)任編輯:武曉燕 來源: 編程界
點贊
收藏

51CTO技術(shù)棧公眾號