新聞中心
當(dāng)我們的代碼庫(kù)有很多人維護(hù)時(shí),經(jīng)常會(huì)出現(xiàn)代碼風(fēng)格不一致或者代碼質(zhì)量不過(guò)關(guān),提交信息雜亂的情況,當(dāng)然啦,即使是一個(gè)人的代碼庫(kù),有的時(shí)候,自己寫代碼時(shí)不太注意細(xì)節(jié),也會(huì)出現(xiàn)風(fēng)格不一致的情況。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、長(zhǎng)壽網(wǎng)站維護(hù)、網(wǎng)站推廣。
本文正是為了解決這個(gè)問(wèn)題而生,閱讀本篇文章并不需要很長(zhǎng)時(shí)間,如果你的代碼庫(kù)還沒(méi)有進(jìn)行這些配置,正是你大展身手的好時(shí)機(jī),武裝一下你的代碼庫(kù)。
1. 規(guī)范 commit 信息
首先,看下 angular 的代碼庫(kù)的 commit 記錄,如圖:
我們可以利用 commitizen 和 husky 來(lái)規(guī)范代碼庫(kù)的 commit。
安裝以下依賴:
- npm install @commitlint/cli @commitlint/config-conventional husky -D
如果你還沒(méi)有安裝過(guò) commitizen,那么先全局安裝:
- npm install commitizen -g
在 package.json 中增加 husky 字段。
- {
- "husky": {
- "hooks": {
- "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
- }
- },
- }
husky 是 git hook 工具,使用 husky,我們可以方便的在 package.json 中配置 git hook 腳本,例如: pre-commit、 pre-push、 commit-msg 等的。
(1) 創(chuàng)建 commitlint.config.js 文件
- module.exports = {
- extends: ["@commitlint/config-conventional"],
- };
此刻開(kāi)始,請(qǐng)使用 git cz 來(lái)替代 git commit 提交信息,我們來(lái)看看,假設(shè)我們隨便寫一個(gè) git commit -m 'fixbug' 會(huì)提示什么?
使用 git cz 來(lái)進(jìn)行填寫 commit 的內(nèi)容。
git cz 的 type 說(shuō)明:
雖然,我們現(xiàn)在已經(jīng)可以規(guī)范提交信息了,但是我們可能不喜歡默認(rèn)的交互,例如,一個(gè)精簡(jiǎn)的描述就可以了,不希望再提示我去寫詳細(xì)的描述,那么就可以使用 cz-customizable 來(lái)進(jìn)行定制。
(2) 自定義提交說(shuō)明
安裝 cz-customizable:
- npm install cz-customizable -D
cz-customizable 是可自定義的 Commitizen 插件,可幫助實(shí)現(xiàn)一致的 commit message。
cz-customizable 適合大型團(tuán)隊(duì)去自定義 scope,和 commit type。
新建 .cz-config.js:
在項(xiàng)目根目錄下創(chuàng)建 .cz-config.js 文件:
官方提供了一份配置信息,可以去這個(gè)地址查看:
https://github.com/leoforfree/cz-customizable/blob/master/cz-config-EXAMPLE.js
- //.cz-config.js
- module.exports = {
- types: [
- { value: 'feat', name: 'feat: A new feature' },
- { value: 'fix', name: 'fix: A bug fix' },
- { value: 'docs', name: 'docs: Documentation only changes' },
- {
- value: 'style',
- name:
- 'style: Changes that do not affect the meaning of the code\n (white-space, formatting, missing semi-colons, etc)',
- },
- {
- value: 'refactor',
- name: 'refactor: A code change that neither fixes a bug nor adds a feature',
- },
- {
- value: 'perf',
- name: 'perf: A code change that improves performance',
- },
- { value: 'test', name: 'test: Adding missing tests' },
- {
- value: 'chore',
- name:
- 'chore: Changes to the build process or auxiliary tools\n and libraries such as documentation generation',
- },
- { value: 'revert', name: 'revert: Revert to a commit' },
- { value: 'WIP', name: 'WIP: Work in progress' },
- ],
- scopes: [{ name: 'accounts' }, { name: 'admin' }, { name: 'exampleScope' }, { name: 'changeMe' }],
- allowTicketNumber: false,
- isTicketNumberRequired: false,
- ticketNumberPrefix: 'TICKET-',
- ticketNumberRegExp: '\\d{1,5}',
- // it needs to match the value for field type. Eg.: 'fix'
- /*
- scopeOverrides: {
- fix: [
- {name: 'merge'},
- {name: 'style'},
- {name: 'e2eTest'},
- {name: 'unitTest'}
- ]
- },
- */
- // override the messages, defaults are as follows
- messages: {
- type: "Select the type of change that you're committing:",
- scope: '\nDenote the SCOPE of this change (optional):',
- // used if allowCustomScopes is true
- customScope: 'Denote the SCOPE of this change:',
- subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
- body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
- breaking: 'List any BREAKING CHANGES (optional):\n',
- footer: 'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
- confirmCommit: 'Are you sure you want to proceed with the commit above?',
- },
- allowCustomScopes: true,
- allowBreakingChanges: ['feat', 'fix'],
- // skip any questions you want
- skipQuestions: ['body'],
- // limit subject length
- subjectLimit: 100,
- };
- types:描述修改的性質(zhì)是什么,是bugfix還是feat,在這里進(jìn)行定義。
- scopes:定義之后,我們就可以通過(guò)上下鍵去選擇 scope
- scopeOverrides:針對(duì)每一個(gè)type去定義scope
- allowBreakingChanges:如上設(shè)置為 ['feat', 'fix'],只有我們type選擇了 feat 或者是 fix,才會(huì)詢問(wèn)我們 breaking message.
- allowCustomScopes:設(shè)置為 true,在 scope 選擇的時(shí)候,會(huì)有 empty 和 custom 可以選擇,顧名思義,選擇 empty 表示 scope 缺省,如果選擇 custom,則可以自己輸入信息
- skipQuestions:指定跳過(guò)哪些步驟,例如跳過(guò)我們剛剛說(shuō)的詳細(xì)描述,設(shè)置其為 scope: ['body'],假設(shè)我們的項(xiàng)目也不會(huì)涉及到關(guān)聯(lián) issue,我們可以設(shè)置其為 scope: ['body', 'footer']
- subjectLimit:描述的長(zhǎng)度限制
這里我就不一一演示每個(gè)字段修改之后的情況了,根據(jù)字段的說(shuō)明,建議如果想自定義提交規(guī)則,在本地進(jìn)行修改驗(yàn)證,公司內(nèi)部的代碼庫(kù)不需要管理 issue,另外,我不喜歡寫長(zhǎng)描述,所以我把 body 和 footer 給 skip 掉了。
cz-customizable 會(huì)首先在項(xiàng)目根目錄下尋找: .cz-config.js 或 .config/cz-config.js,如果找不到,會(huì)去主目錄尋找。我們也可以在 package.json 中手動(dòng)去指定配置文件的路徑。
- "config": {
- "commitizen": {
- "path": "node_modules/cz-customizable"
- },
- "cz-customizable": {
- "config": "config/path/to/my/config.js"
- }
- }
現(xiàn)在,我們已經(jīng)規(guī)范了 commit 信息,但是沒(méi)有對(duì)提交的代碼進(jìn)行規(guī)范,在一個(gè)代碼庫(kù)中,經(jīng)常出現(xiàn)2個(gè)空格/4個(gè)空格混用,有些地方寫 ;,有些不寫 ;,風(fēng)格不統(tǒng)一。例如,我們希望提交到git庫(kù)的代碼,都能夠通過(guò) eslint 檢查或者是通過(guò)測(cè)試。我們可以借助于 pre-commit 這個(gè)鉤子來(lái)做這些事情。
2. 代碼提交前檢查
安裝依賴:
- npm install lint-staged -D
使用 pre-commit 的 hook
- "husky": {
- "hooks": {
- "pre-commit": "lint-staged"
- }
- },
- "lint-staged": {
- "**/*.js": [
- "prettier --write",
- "eslint"
- ]
- }
這樣配置之后,每次提交的時(shí)候,都會(huì)對(duì)要提交的文件(并不是對(duì)整個(gè)項(xiàng)目)進(jìn)行 prettier 格式化和 eslint 檢查,都通過(guò)之后,才能 commit 成功。
(1) eslint 和 prettier 配置
我的項(xiàng)目是 react 項(xiàng)目,下面是我進(jìn)行的配置。
安裝 eslint 和 prettier 相關(guān)依賴:
- npm install eslint eslint-config-prettier eslint-plugin-promise eslint-plugin-react eslint-plugin-react-hooks prettier babel-eslint -D
新建 .prettierrc.js
當(dāng)然啦,你也可以在 package.json 的 prettier 字段中配置,這里我配置成了獨(dú)立的文件,以便后期維護(hù)。
- module.exports = {
- printWidth: 100, //長(zhǎng)度超過(guò)100斷行
- singleQuote: true,//使用單引號(hào)
- };
如果你有一些文件不需要 prettier 進(jìn)行格式化,那么可以新建一個(gè) .prettierignore 文件,如下:
- dist
- node_modules
- public
新建 .eslintrc.js 文件
以下是我的配置:
- module.exports = {
- settings: {
- react: {
- pragma: 'React',
- version: 'detect'
- }
- },
- // babel parser to support ES6/7 features
- parser: 'babel-eslint',
- parserOptions: {
- ecmaVersion: 7,
- ecmaFeatures: {
- experimentalObjectRestSpread: true,
- jsx: true
- },
- sourceType: 'module'
- },
- extends: [
- 'prettier',
- 'prettier/react'
- ],
- plugins: [
- 'promise',
- 'react',
- 'react-hooks'
- ],
- env: {
- browser: true,
- es6: true,
- node: true
- },
- rules: {
- 'no-compare-neg-zero': 2, //禁止與 -0 進(jìn)行比較
- 'no-cond-assign': 2, //禁止條件表達(dá)式中出現(xiàn)賦值操作符
- 'no-console': 1, //禁用 console
- 'no-constant-condition': 1, //禁止在條件中使用常量表達(dá)式
- 'no-control-regex': 1, //禁止在正則表達(dá)式中使用控制字符
- 'no-debugger': 2, //禁用 debugger
- 'no-dupe-args': 2, //禁止 function 定義中出現(xiàn)重名參數(shù)
- 'no-dupe-keys': 2, //禁止對(duì)象字面量中出現(xiàn)重復(fù)的 key
- 'no-duplicate-case': 2, //禁止出現(xiàn)重復(fù)的 case 標(biāo)簽
- 'no-const-assign': 1, //禁止修改const聲明的變量
- 'no-empty': 1, //禁止出現(xiàn)空語(yǔ)句塊
- 'no-empty-character-class': 2, //禁止在正則表達(dá)式中使用空字符集
- 'no-ex-assign': 2, //禁止對(duì) catch 子句的異常參數(shù)重新賦值
- 'no-extra-boolean-cast': 1, //禁止不必要的布爾轉(zhuǎn)換
- 'no-extra-semi': 1, //禁止不必要的分號(hào)
- 'no-func-assign': 2, //禁止對(duì) function 聲明重新賦值
- 'no-inner-declarations': 0, //禁止在嵌套的塊中出現(xiàn)變量聲明或 function 聲明,ES6中無(wú)需禁止
- 'no-invalid-regexp': 2, //禁止 RegExp 構(gòu)造函數(shù)中存在無(wú)效的正則表達(dá)式字符串
- 'no-irregular-whitespace': 1, //禁止在字符串和注釋之外不規(guī)則的空白
- 'no-obj-calls': 2, //禁止把全局對(duì)象作為函數(shù)調(diào)用,比如Math() JSON()
- 'no-regex-spaces': 1, //禁止正則表達(dá)式字面量中出現(xiàn)多個(gè)空格
- 'no-sparse-arrays': 1, //禁用稀疏數(shù)組
- 'no-unexpected-multiline': 1, //禁止出現(xiàn)令人困惑的多行表達(dá)式
- 'no-unreachable': 1, //禁止在return、throw、continue 和 break 語(yǔ)句之后出現(xiàn)不可達(dá)代碼
- 'no-unsafe-finally': 2, //禁止在 finally 語(yǔ)句塊中出現(xiàn)控制流語(yǔ)句
- 'no-unsafe-negation': 1, //禁止對(duì)關(guān)系運(yùn)算符的左操作數(shù)使用否定操作符
- 'use-isnan': 2, //要求使用 isNaN() 檢查 NaN,如 isNaN(foo),而非foo == NaN
- 'valid-typeof': 2, //強(qiáng)制 typeof 表達(dá)式與有效的字符串(如: 'undefined', 'object', 'boolean', 'number', 'string', 'function','symbol')進(jìn)行比較
- 'no-case-declarations': 1, //不允許在 case 子句中使用詞法聲明
- 'no-empty-pattern': 2, //禁止使用空解構(gòu)模式
- 'no-fallthrough': 2, //禁止 case 語(yǔ)句落空
- 'no-global-assign': 2, //禁止對(duì)原生對(duì)象或只讀的全局對(duì)象進(jìn)行賦值
- 'no-octal': 1, //禁用八進(jìn)制字面量
- 'no-redeclare': 1, //禁止多次聲明同一變量
- 'no-self-assign': 1, //禁止自我賦值
- 'no-unused-labels': 1, //禁用出現(xiàn)未使用過(guò)的標(biāo)
- 'no-useless-escape': 1, //禁用不必要的轉(zhuǎn)義字符
- 'no-delete-var': 2, //禁止刪除變量
- 'no-undef': 2, //禁用使用未聲明的變量,除非它們?cè)?nbsp;/*global */ 注釋中被提到
- 'no-unused-vars': 1, //禁止出現(xiàn)未使用過(guò)的變量
- 'constructor-super': 2, //要求在構(gòu)造函數(shù)中有 super() 的調(diào)用
- 'no-class-assign': 2, //禁止給類賦值
- 'no-dupe-class-members': 2, //禁止類成員中出現(xiàn)重復(fù)的名稱
- 'no-new-symbol': 2, //禁止 Symbol 和 new 操作符一起使用
- 'no-this-before-super': 2, //禁止在構(gòu)造函數(shù)中,在調(diào)用 super() 之前使用 this 或 super
- 'require-yield': 2, //要求 generator 函數(shù)內(nèi)有 yield
- 'no-mixed-spaces-and-tabs': 1, //要求不適用space,tab混用
- 'react/forbid-prop-types': [1, { forbid: ['any'] }], //禁止某些propTypes
- 'react/prop-types': 1, //沒(méi)用對(duì)props類型進(jìn)行校驗(yàn)
- 'react/jsx-closing-bracket-location': 1, //在JSX中驗(yàn)證右括號(hào)位置
- 'react/jsx-curly-spacing': [1, { when: 'never', children: true }], //在JSX屬性和表達(dá)式中加強(qiáng)或禁止大括號(hào)內(nèi)的空格。
- 'react/jsx-key': 2, //在數(shù)組或迭代器中驗(yàn)證JSX具有key屬性
- 'react/jsx-max-props-per-line': [1, { maximum: 1 }], // 限制JSX中單行上的props的最大數(shù)量
- 'react/jsx-no-duplicate-props': 2, //防止在JSX中重復(fù)的props
- 'react/jsx-no-undef': 1, //在JSX中禁止未聲明的變量
- 'react/no-string-refs': 1, //Using string literals in ref attributes is deprecated
- 'react/jsx-uses-react': 1, //防止反應(yīng)被錯(cuò)誤地標(biāo)記為未使用
- 'react/jsx-uses-vars': 1, //防止在JSX中使用的變量被錯(cuò)誤地標(biāo)記為未使用
- 'react/no-danger': 1, //防止使用危險(xiǎn)的JSX屬性
- 'react/no-did-update-set-state': 2, //防止在componentDidUpdate中使用setState
- 'react/no-did-mount-set-state': 0, //防止在componentDidUpdate中使用setState
- 'react/no-direct-mutation-state': 2, //防止this.state賦值
- 'react/no-unknown-property': 2, //防止使用未知的DOM屬性
- 'react/prefer-es6-class': 1, //為React組件強(qiáng)制執(zhí)行ES5或ES6類
- 'react/react-in-jsx-scope': 0, //使用JSX時(shí),必須要引入React
- 'react/sort-comp': 0, //強(qiáng)制組件方法順序
- 'react/sort-prop-types': 0, //強(qiáng)制組件屬性順序
- 'react/jsx-sort-props': 1,
- 'react/no-deprecated': 1, //不使用棄用的方法
- 'react/jsx-equals-spacing': 1, //在JSX屬性中強(qiáng)制或禁止等號(hào)周圍的空格
- 'react/wrap-multilines': 0,
- 'comma-dangle': 1, //對(duì)象字面量項(xiàng)尾不能有逗號(hào)
- 'react/no-multi-comp': 0, //防止每個(gè)文件有多個(gè)組件定義
- 'flowtype/generic-spacing': 0, //泛型對(duì)象的尖括號(hào)中類型前后的空格規(guī)范
- 'flowtype/space-after-type-colon': 0, //類型注解分號(hào)后的空格規(guī)范
- // react-hooks
- 'react-hooks/rules-of-hooks': 'error',
- 'react-hooks/exhaustive-deps': 'warn'
- }
- };
現(xiàn)在,再也不能隨心所欲往你的代碼庫(kù)提交文件啦,不過(guò) eslint 和 prettier 的規(guī)則要和團(tuán)隊(duì)的成員協(xié)商制定哈~
本文標(biāo)題:花十分鐘的時(shí)間武裝你的代碼庫(kù)
文章地址:http://www.dlmjj.cn/article/dhpcpdh.html


咨詢
建站咨詢
