精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

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

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

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

ESLint 代碼質(zhì)量檢測(cè)

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

ESLint 基本使用

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

執(zhí)行 --init 命令后,可以選擇使用的框架、模塊類型、語(yǔ)言(JS/TS)等,隨后會(huì)生成一個(gè) .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: {}

對(duì)上述文件幾個(gè)配置做一些簡(jiǎn)單介紹:

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

jsx:?jiǎn)⒂?JSX

ecmaFeatures:想使用的額外的語(yǔ)言特性

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

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

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

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

忽略特定文件或目錄

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

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

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

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

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

安裝 eslint-config-airbnb[4] npm i eslint-config-airbnb -D,如果你不需要 React,可以參考 eslint-config-airbnb-base[5] 這個(gè)包,在 Node.js 服務(wù)端可以使用這個(gè)包。之后添加 "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 自動(dòng)提示

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

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

圖片圖片

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

圖片圖片

Prettier 代碼格式化

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

Prettier 基本使用

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

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

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

$ touch .prettierignore

# Ignore artifacts:
build
coverage

手動(dòng)觸發(fā)

命令行執(zhí)行 **npx prettier --write .** 手動(dòng)觸發(fā),對(duì)于一個(gè)大項(xiàng)目來(lái)說(shuō)可能會(huì)花費(fèi)一些時(shí)間,因此還可以指定目錄或文件來(lái)格式化。

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

有了 ESLint 為什么還要使用 Prettier

ESLint 提供了 eslint --fix 命令用來(lái)自動(dòng)修復(fù)代碼格式問(wèn)題,為什么還要用 Prettier 呢?

如果我說(shuō)在代碼格式化方面 Prettier 比 ESLint 更專業(yè),你可能也不會(huì)信服,畢竟沒(méi)有證據(jù)來(lái)證明這一點(diǎn)。下面我將通過(guò)一個(gè)例子來(lái)驗(yàn)證。

下面這段 JavaScript 代碼片段,存在兩個(gè)問(wèn)題,一個(gè)是 console.log(...args) 沒(méi)有縮進(jìn),另外一個(gè)是 createData()  這一行超出了最大長(zhǎng)度限制。

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

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

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

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

圖片圖片

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

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

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

圖片圖片

解決 ESLint 與 Prettier 沖突

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

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

// .eslintrc.yml
extends:
  - airbnb

// .prettierrc.json
{
 "singleQuote": false // 字符串默認(rèn)使用雙引號(hào)
}

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

圖片圖片

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

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

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

解決方案第二步:賦予 eslint --fix 以 Prettier 規(guī)則格式化代碼的能力,并以 ESLint 的方式報(bào)告錯(cuò)誤。開發(fā)時(shí)依賴安裝 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ī)則格式化代碼的能力

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

extends:
  - plugin:prettier/recommended

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

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

# .eslintrc.yml
prettier/prettier: ["error", {}, {
  "usePrettierrc": true # 默認(rèn)值
}]

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

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

圖片圖片

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

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

prettier/prettier: ["error", {
 "arrowParens": "avoid"
}, {
  "usePrettierrc": true # 默認(rèn)值
}]

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

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

root = true

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

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

Husky 攔截 git 操作命令

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

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

$ 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 的使用變得更加簡(jiǎn)單,同時(shí)也能解決,.git 目錄提交無(wú)法跟蹤的問(wèn)題。

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

Husky 推薦在 package.json 的 scripts 里設(shè)置 prepare,因?yàn)樵趫?zhí)行 npm install 命令時(shí),將會(huì)自動(dòng)執(zhí)行 prepare 腳本。

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

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

添加一個(gè) hook,在 git commit 前執(zhí)行 eslint 命令檢測(cè)代碼規(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 就會(huì)被攔截。

圖片圖片

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

lint-staged 僅檢查修改的文件

每次只對(duì)修改的文件做檢查,就要用到 **lint-staged**[10] 這個(gè)工具了,解決老項(xiàng)目的歷史包袱問(wèn)題。

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

注意,**npx eslint --fix**** 后不要指定路徑,例如 **npx eslint --fix ./src/** 會(huì)出現(xiàn)只修改了 A 文件,但是其它有問(wèn)題的 B、C 等文件也被檢測(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ā)
  • 進(jìn)而執(zhí)行 precommit、該命令腳本又執(zhí)行了 lint-staged
  • lint-staged 則根據(jù)配置和只對(duì) git add 到暫存區(qū)的文件進(jìn)行掃描,執(zhí)行 eslint 代碼檢測(cè)。
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run precommit

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

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

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

commitlint

安裝 commitlint cli 和提交信息校驗(yàn)規(guī)則 @commitlint/config-conventional[13],詳細(xì)的參考文檔 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 校驗(yàn)配置,
$ 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ù),這個(gè)用的就比較多了~
  • perf:做的一些性能提升
  • refactor:重構(gòu)
  • revert:回滾之前某個(gè) commit
  • style:代碼格式的修改,例如通過(guò) Prettier 格式化代碼,但不會(huì)影響邏輯
  • test:測(cè)試

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

圖片圖片

正確的做法是加上類型信息 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 指定一個(gè) Adapter,例如 cz-conventional-changelog[15] 基于 commit message 的輕量級(jí)約定,提供了一組簡(jiǎn)單的規(guī)則來(lái)創(chuàng)建明確的提交歷史,參考 約定式提交[16]。

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

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

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

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

圖片圖片

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

圖片圖片

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

圖片圖片

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

standard-version

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

$ npm i --save-dev standard-version

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

以上介紹內(nèi)容,實(shí)際應(yīng)用可參考這個(gè)前后端項(xiàng)目 https://github.com/qufei1993/compressor[19],不同的是該項(xiàng)目是基于 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é)任編輯:武曉燕 來(lái)源: 編程界
相關(guān)推薦

2022-10-27 15:03:23

2021-01-08 13:00:12

CPU處理器軟件

2021-05-27 18:41:27

高可用nginxHAProxy

2023-03-30 10:22:42

數(shù)據(jù)處理前端

2016-04-07 10:31:39

Wi-Fi無(wú)線部署信銳技術(shù)

2020-02-03 09:29:32

JavaScript代碼斷點(diǎn)

2023-02-20 14:37:25

2023-10-14 15:36:14

PodKubernetes

2020-06-12 08:34:37

React開發(fā)工具

2017-09-14 18:33:29

Python編程語(yǔ)言開發(fā)

2017-07-06 12:58:13

算法MATLAB

2021-04-08 10:40:24

前端工具代碼

2023-03-15 23:59:13

前端構(gòu)建工具

2023-08-22 10:13:53

模塊工具JavaScrip

2024-06-04 22:04:39

2019-08-30 08:51:48

物聯(lián)網(wǎng)產(chǎn)品盈利物聯(lián)網(wǎng)

2017-01-03 19:01:33

WIFI網(wǎng)絡(luò)信號(hào)路由器

2016-07-28 10:34:12

云計(jì)算

2018-09-04 11:09:58

容災(zāi)災(zāi)備系統(tǒng)

2017-12-07 10:07:36

容災(zāi)備份
點(diǎn)贊
收藏

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

亚洲国产中文字幕久久网| 亚洲欧美一区二区久久| 国产成+人+综合+亚洲欧洲| av网在线播放| 免费精品一区二区三区在线观看| 亚洲va欧美va人人爽午夜| 日韩亚洲不卡在线| 亚洲精品久久久久久久久久久久久久 | 粉嫩av懂色av蜜臀av分享| 成人在线视频免费看| 亚洲综合一区二区精品导航| 日日骚一区二区网站| 高潮一区二区三区乱码| 日本vs亚洲vs韩国一区三区二区| 欧美激情精品久久久久久变态| 少妇真人直播免费视频| 欧美另类中文字幕| 欧美视频完全免费看| 免费超爽大片黄| 老司机午夜在线视频| 2023国产精品自拍| 国产 高清 精品 在线 a| 中国一级特黄视频| 香蕉成人久久| 午夜免费久久久久| 中文字幕影音先锋| 99精品视频在线| 亚洲午夜精品久久久久久性色| 苍井空张开腿实干12次| 亚洲伊人精品酒店| 欧美自拍偷拍午夜视频| 国产极品尤物在线| 国产福利在线免费观看| 亚洲三级在线免费观看| 亚洲国产午夜伦理片大全在线观看网站 | 中日韩午夜理伦电影免费 | 农村妇女精品一二区| 中文字幕有码在线观看| 成人欧美一区二区三区视频网页| 奇米精品在线| 免费黄网站在线观看| 99久久综合狠狠综合久久| 成人自拍偷拍| 亚洲国产精彩视频| 国产成人啪免费观看软件| 91在线观看免费高清| 亚洲一级黄色大片| 蜜桃在线一区二区三区| 国产精品永久在线| 国产乡下妇女三片| 蜜臀91精品一区二区三区| 国产精品大陆在线观看| 尤物视频免费观看| 日韩av一级片| 国产精品视频久久| 亚洲无码久久久久久久| 久久黄色级2电影| 成人网页在线免费观看| aaa一区二区| 丁香六月久久综合狠狠色| 亚洲japanese制服美女| www.麻豆av| 成人99免费视频| 久久久久久高清| 国产1区2区3区在线| 中文字幕不卡一区| 黄色a级在线观看| 宅男在线观看免费高清网站| 亚洲国产日韩a在线播放性色| 日韩精品一区在线视频| 欧美三级网址| 宅男噜噜噜66一区二区66| 男男受被啪到高潮自述| 开心激情综合| 原创国产精品91| 99久久99久久精品国产| 黄色另类av| 日韩av免费在线播放| 欧美激情一区二区三区免费观看 | 欧美吞精做爰啪啪高潮| 日本中文字幕观看| 澳门精品久久国产| 亚洲欧美国产高清va在线播| 日韩欧美视频免费观看| 精品av久久久久电影| 欧洲亚洲免费在线| 91亚洲视频在线观看| 成人国产精品免费网站| 茄子视频成人在线观看| www红色一片_亚洲成a人片在线观看_| 午夜久久久影院| 天天干在线影院| 一区二区三区免费在线看| 日韩精品免费观看| 丰满少妇被猛烈进入一区二区| 亚洲精品一级| 国产综合久久久久久| 韩国av免费在线观看| 久久精品这里都是精品| 日韩一二区视频| 搜成人激情视频| 欧美一级高清片| 精品无码国产污污污免费网站| 91精品秘密在线观看| 6080yy精品一区二区三区| 一区二区三区黄| 26uuu久久天堂性欧美| 成人高清dvd| 123成人网| 亚洲黄色在线观看| 四虎永久免费在线| 日韩不卡手机在线v区| 国产嫩草一区二区三区在线观看| 色综合久久影院| 欧美日韩在线观看视频| 苍井空张开腿实干12次| 国产精品x453.com| 国产福利精品在线| 天堂在线中文字幕| 亚洲一区二区欧美| 色姑娘综合天天| 久久精品高清| 国产精品va在线| 日本大片在线观看| 香蕉加勒比综合久久| 久久久久久国产精品日本| 成人系列视频| 国产精品www网站| 欧美91精品久久久久国产性生爱| 亚洲大片在线观看| 动漫av在线免费观看| 亚洲不卡av不卡一区二区| 国产精品视频免费观看www| 九色视频在线观看免费播放 | 国产一区二区三区在线观看| 久久精品一区蜜桃臀影院| 欧美黄色免费影院| 牛牛影视久久网| 97视频在线看| 天天操天天操天天| 好吊成人免视频| 欧产日产国产精品98| 夜夜嗨网站十八久久| 国产精品一级久久久| jizz一区二区三区| 精品国产一区二区三区久久久蜜月| 紧身裙女教师波多野结衣| 国产乱子伦视频一区二区三区 | aa亚洲婷婷| 精品国产乱码久久久久软件| 国产乱码精品一区二三赶尸艳谈| 精品成人在线观看| 九热这里只有精品| 91伊人久久大香线蕉| 青青艹视频在线| 亚洲精品播放| 国产精品jvid在线观看蜜臀| 精品乱码一区二区三四区视频| 色94色欧美sute亚洲线路二| 中日韩精品一区二区三区| 日韩精品国产欧美| 亚洲欧美日韩综合一区| 99热这里有精品| 欧美激情精品久久久久久黑人 | 久久精品五月天| 中文字幕的久久| 久久黄色一级视频| 亚洲美女网站| 日本成人三级电影网站| 亚洲国产91视频| 欧美激情综合色| 污视频在线免费观看| 91久久线看在观草草青青| 免费看一级黄色| 成人一区二区在线观看| 黑森林福利视频导航| 久久国产精品亚洲人一区二区三区| 亚洲a一级视频| 亚洲妇女成熟| xxxx性欧美| 亚洲欧美强伦一区二区| 色94色欧美sute亚洲线路二| 顶臀精品视频www| av亚洲产国偷v产偷v自拍| 天天爱天天操天天干| 欧美在线精品一区| 欧美日韩国产综合视频在线| 成人97精品毛片免费看| 91福利视频在线观看| 男人和女人做事情在线视频网站免费观看 | 欧美日本国产在线| 飘雪影院手机免费高清版在线观看| 欧美日韩一区二区三区在线看| 劲爆欧美第一页| 国产三级精品三级在线专区| 佐山爱在线视频| 久久综合图片| 久久av高潮av| 日韩欧美视频| 精品伦精品一区二区三区视频| 欧美天堂一区| 欧美一性一乱一交一视频| 黄网页免费在线观看| 日韩精品在线免费观看| 99热这里只有精品5| 日韩欧美精品网址| 久久黄色免费视频| 国产精品国产三级国产aⅴ入口| 国产精品手机在线观看| 国产专区欧美精品| 嫩草av久久伊人妇女超级a| 国产综合欧美| 色乱码一区二区三区熟女| 最近国产精品视频| 国产超碰91| 免费一级欧美在线大片 | 日韩视频在线直播| 国产精品亚洲综合天堂夜夜| 午夜激情在线播放| 久久久久久久久久婷婷| av免费在线观| 久久精品国产欧美激情| 国产永久免费高清在线观看| 日韩乱码在线视频| 四虎在线视频免费观看| 精品人在线二区三区| 国产欧美一级片| 在线不卡中文字幕| 国产精品久久久久久久久久久久久久久久久久 | 日本在线中文字幕一区二区三区| 97人人模人人爽人人喊中文字| 在线电影福利片| 久久国产精品首页| 国产激情在线观看| 久久久精品久久久久| 日本中文字幕在线视频| 在线观看久久av| 在线视频婷婷| 日韩一区二区欧美| 日本三级视频在线观看| 日韩在线中文字| 男人天堂手机在线| 精品国产一区二区三区久久狼5月| av中文资源在线| 日韩中文字幕在线精品| 午夜视频在线免费观看| 日韩视频在线免费| 国产原创精品视频| 欧美激情小视频| 岛国毛片av在线| 91精品国产色综合| 欧美少妇精品| 国产suv精品一区二区| 欧美成人精品三级网站| 成人春色激情网| 日日夜夜精品视频| 国产精品我不卡| 欧美激情在线免费| 一区二区免费在线视频| 综合视频在线| 美女扒开大腿让男人桶| 亚洲一区二区三区高清| 毛片av免费在线观看| 久久精品国产久精国产爱| 无码人妻少妇色欲av一区二区| 成人动漫中文字幕| b站大片免费直播| 亚洲婷婷综合久久一本伊一区| 久久国产在线观看| 色哟哟日韩精品| 一级做a爱片久久毛片| 日韩欧美国产麻豆| 日韩亚洲视频在线观看| 色噜噜国产精品视频一区二区| 国产理论在线观看| 97视频网站入口| 欧美亚洲人成在线| 国产精品国产精品| 成人精品影院| 久久av高潮av| 日韩电影免费在线观看网站| 亚洲精品无码久久久久久久| 91网站视频在线观看| 国产第一页精品| 亚洲一级在线观看| 久久久久精彩视频| 精品久久国产97色综合| 加勒比一区二区三区在线| 九色成人免费视频| 高清电影一区| 国产精品久久久久免费| 成人精品久久| 欧美网站免费观看| 国产美女精品人人做人人爽| 亚洲第一成人网站| 一区二区欧美视频| 亚洲中文一区二区三区| 日韩精品丝袜在线| 亚洲欧美成人影院| 国产精品视频一区二区三区四| 国产精品欧美大片| 亚洲精品偷拍视频| 玖玖精品视频| 黄色国产在线视频| 综合精品久久久| 免费黄色片视频| 亚洲国产精品嫩草影院久久| 黄色片网站在线| 国产精品午夜一区二区欲梦| 欧美色图五月天| 妞干网视频在线观看| 黄网站免费久久| 久久久久久久久福利| 疯狂蹂躏欧美一区二区精品| 国产激情无套内精对白视频| 少妇高潮久久77777| 成人免费看视频网站| 国产一区二区三区av在线| 一区二区蜜桃| 色91精品久久久久久久久| 国产色婷婷亚洲99精品小说| av大片免费观看| 亚洲国产高清高潮精品美女| 伊人影院蕉久影院在线播放| 成人免费黄色网| 日韩激情在线| 久久综合伊人77777麻豆最新章节| 99视频精品在线| 久久狠狠高潮亚洲精品| 日韩欧美国产系列| 青春草在线视频| 91香蕉视频在线下载| 欧美韩日精品| 欧美色图校园春色| 亚洲精品第1页| 国产成年妇视频| 久热99视频在线观看| www久久久| 最新av在线免费观看| 国产乱人伦精品一区二区在线观看| 亚洲波多野结衣| 欧美一区二区三区四区五区| 97影院秋霞午夜在线观看| 91亚洲一区精品| 欧美日本二区| 稀缺小u女呦精品呦| 欧美日韩亚洲视频一区| 久草视频视频在线播放| 国产精品国产福利国产秒拍| 日本a级不卡| 日本三级黄色网址| 日韩理论片在线| 高清国产mv在线观看| 欧美亚洲在线播放| 九一精品国产| 超碰在线公开97| ㊣最新国产の精品bt伙计久久| av中文在线观看| 性金发美女69hd大尺寸| 影视先锋久久| 最新天堂中文在线| 亚洲精品一二三四区| 人妻中文字幕一区| 国产成人精品在线观看| 日本久久综合| 日韩精品――色哟哟| 欧美日韩中文字幕日韩欧美| 国产三级电影在线| 91美女片黄在线观| 影音先锋久久久| 国产一级久久久久毛片精品| 91麻豆精品国产综合久久久久久 | 日韩av电影国产| 国产精品久久久久久久免费观看| 丰满人妻一区二区三区大胸 | 奇米影视777在线欧美电影观看| 亚洲熟妇av一区二区三区| 中文字幕一区二区在线播放| 亚洲国产精品久久久久久6q| 亲爱的老师9免费观看全集电视剧| 日韩久久精品网| 亚洲午夜久久久久久久久| 在线视频亚洲一区| 五月婷婷视频在线观看| 秋霞久久久久久一区二区| 国产精品综合二区| 欧美a视频在线观看| 欧美精品免费在线| 久草精品在线| 国产无套精品一区二区三区| 91电影在线观看| 国产乱码在线| 亚洲视频导航| 99精品视频在线观看| 国产精品久久久久久无人区| 欧洲成人性视频| 欧美日韩伊人| 性爱在线免费视频| 亚洲精品综合精品自拍| 蜜桃在线一区|