花十分鐘的時間武裝你的代碼庫
當(dāng)我們的代碼庫有很多人維護(hù)時,經(jīng)常會出現(xiàn)代碼風(fēng)格不一致或者代碼質(zhì)量不過關(guān),提交信息雜亂的情況,當(dāng)然啦,即使是一個人的代碼庫,有的時候,自己寫代碼時不太注意細(xì)節(jié),也會出現(xiàn)風(fēng)格不一致的情況。
本文正是為了解決這個問題而生,閱讀本篇文章并不需要很長時間,如果你的代碼庫還沒有進(jìn)行這些配置,正是你大展身手的好時機(jī),武裝一下你的代碼庫。
1. 規(guī)范 commit 信息
首先,看下 angular 的代碼庫的 commit 記錄,如圖:

我們可以利用 commitizen 和 husky 來規(guī)范代碼庫的 commit。
安裝以下依賴:
npm?install?@commitlint/cli?@commitlint/config-conventional?husky??-D
如果你還沒有安裝過 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 等的。
創(chuàng)建 commitlint.config.js 文件
module.exports?=?{
????extends:?["@commitlint/config-conventional"],
};
此刻開始,請使用 git cz 來替代 git commit 提交信息,我們來看看,假設(shè)我們隨便寫一個 git commit -m 'fixbug' 會提示什么?

使用 git cz 來進(jìn)行填寫 commit 的內(nèi)容。

git cz 的 type 說明:

雖然,我們現(xiàn)在已經(jīng)可以規(guī)范提交信息了,但是我們可能不喜歡默認(rèn)的交互,例如,一個精簡的描述就可以了,不希望再提示我去寫詳細(xì)的描述,那么就可以使用 cz-customizable 來進(jìn)行定制。
自定義提交說明
安裝 cz-customizable
npm?install?cz-customizable?-D
cz-customizable 是可自定義的 Commitizen 插件,可幫助實現(xiàn)一致的 commit message。
cz-customizable 適合大型團(tuán)隊去自定義 scope,和 commit type。
新建 .cz-config.js
在項目根目錄下創(chuàng)建 .cz-config.js 文件:
官方提供了一份配置信息,可以去這個地址查看: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: 定義之后,我們就可以通過上下鍵去選擇
scopescopeOverrides: 針對每一個type去定義scope
allowBreakingChanges: 如上設(shè)置為
['feat', 'fix'],只有我們type選擇了feat或者是fix,才會詢問我們 breaking message.allowCustomScopes: 設(shè)置為 true,在 scope 選擇的時候,會有
empty和custom可以選擇,顧名思義,選擇empty表示scope缺省,如果選擇custom,則可以自己輸入信息skipQuestions: 指定跳過哪些步驟,例如跳過我們剛剛說的詳細(xì)描述,設(shè)置其為
scope: ['body'],假設(shè)我們的項目也不會涉及到關(guān)聯(lián) issue,我們可以設(shè)置其為scope: ['body', 'footer']subjectLimit: 描述的長度限制
這里我就不一一演示每個字段修改之后的情況了,根據(jù)字段的說明,建議如果想自定義提交規(guī)則,在本地進(jìn)行修改驗證,公司內(nèi)部的代碼庫不需要管理 issue,另外,我不喜歡寫長描述,所以我把 body 和 footer 給 skip 掉了。
cz-customizable 會首先在項目根目錄下尋找: .cz-config.js 或 .config/cz-config.js,如果找不到,會去主目錄尋找。我們也可以在 package.json 中手動去指定配置文件的路徑。
"config":?{
????"commitizen":?{?
????????"path":?"node_modules/cz-customizable"
????},
????"cz-customizable":?{
????????"config":?"config/path/to/my/config.js"
????}
}
現(xiàn)在,我們已經(jīng)規(guī)范了 commit 信息,但是沒有對提交的代碼進(jìn)行規(guī)范,在一個代碼庫中,經(jīng)常出現(xiàn)2個空格/4個空格混用,有些地方寫 ;,有些不寫 ;,風(fēng)格不統(tǒng)一。例如,我們希望提交到git庫的代碼,都能夠通過 eslint 檢查或者是通過測試。我們可以借助于 pre-commit 這個鉤子來做這些事情。
2. 代碼提交前檢查
安裝依賴
npm?install?lint-staged?-D
使用 pre-commit 的 hook
"husky":?{
????"hooks":?{
????????"pre-commit":?"lint-staged"
????}
},
"lint-staged":?{
????"**/*.js":?[
????????"prettier?--write",?
????????"eslint"
????]
}
這樣配置之后,每次提交的時候,都會對要提交的文件(并不是對整個項目)進(jìn)行 prettier 格式化和 eslint 檢查,都通過之后,才能 commit 成功。
eslint 和 prettier 配置
我的項目是 react 項目,下面是我進(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 字段中配置,這里我配置成了獨立的文件,以便后期維護(hù)。
module.exports?=?{
??printWidth:?100,?//長度超過100斷行
??singleQuote:?true,//使用單引號
};
如果你有一些文件不需要 prettier 進(jìn)行格式化,那么可以新建一個 .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,?//禁止對象字面量中出現(xiàn)重復(fù)的?key
????'no-duplicate-case':?2,?//禁止出現(xiàn)重復(fù)的?case?標(biāo)簽
????'no-const-assign':?1,?//禁止修改const聲明的變量
????'no-empty':?1,?//禁止出現(xiàn)空語句塊
????'no-empty-character-class':?2,?//禁止在正則表達(dá)式中使用空字符集
????'no-ex-assign':?2,?//禁止對?catch?子句的異常參數(shù)重新賦值
????'no-extra-boolean-cast':?1,?//禁止不必要的布爾轉(zhuǎn)換
????'no-extra-semi':?1,?//禁止不必要的分號
????'no-func-assign':?2,?//禁止對?function?聲明重新賦值
????'no-inner-declarations':?0,?//禁止在嵌套的塊中出現(xiàn)變量聲明或?function?聲明,ES6中無需禁止
????'no-invalid-regexp':?2,?//禁止?RegExp?構(gòu)造函數(shù)中存在無效的正則表達(dá)式字符串
????'no-irregular-whitespace':?1,?//禁止在字符串和注釋之外不規(guī)則的空白
????'no-obj-calls':?2,?//禁止把全局對象作為函數(shù)調(diào)用,比如Math()?JSON()
????'no-regex-spaces':?1,?//禁止正則表達(dá)式字面量中出現(xiàn)多個空格
????'no-sparse-arrays':?1,?//禁用稀疏數(shù)組
????'no-unexpected-multiline':?1,?//禁止出現(xiàn)令人困惑的多行表達(dá)式
????'no-unreachable':?1,?//禁止在return、throw、continue?和?break?語句之后出現(xiàn)不可達(dá)代碼
????'no-unsafe-finally':?2,?//禁止在?finally?語句塊中出現(xiàn)控制流語句
????'no-unsafe-negation':?1,?//禁止對關(guā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?語句落空
????'no-global-assign':?2,?//禁止對原生對象或只讀的全局對象進(jìn)行賦值
????'no-octal':?1,?//禁用八進(jìn)制字面量
????'no-redeclare':?1,?//禁止多次聲明同一變量
????'no-self-assign':?1,?//禁止自我賦值
????'no-unused-labels':?1,?//禁用出現(xiàn)未使用過的標(biāo)
????'no-useless-escape':?1,?//禁用不必要的轉(zhuǎn)義字符
????'no-delete-var':?2,?//禁止刪除變量
????'no-undef':?2,?//禁用使用未聲明的變量,除非它們在?/*global?*/?注釋中被提到
????'no-unused-vars':?1,?//禁止出現(xiàn)未使用過的變量
????'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,?//沒用對props類型進(jìn)行校驗
????'react/jsx-closing-bracket-location':?1,?//在JSX中驗證右括號位置
????'react/jsx-curly-spacing':?[1,?{?when:?'never',?children:?true?}],?//在JSX屬性和表達(dá)式中加強(qiáng)或禁止大括號內(nèi)的空格。
????'react/jsx-key':?2,?//在數(shù)組或迭代器中驗證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)被錯誤地標(biāo)記為未使用
????'react/jsx-uses-vars':?1,?//防止在JSX中使用的變量被錯誤地標(biāo)記為未使用
????'react/no-danger':?1,?//防止使用危險的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時,必須要引入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)制或禁止等號周圍的空格
????'react/wrap-multilines':?0,
????'comma-dangle':?1,?//對象字面量項尾不能有逗號
????'react/no-multi-comp':?0,?//防止每個文件有多個組件定義
????'flowtype/generic-spacing':?0,?//泛型對象的尖括號中類型前后的空格規(guī)范
????'flowtype/space-after-type-colon':?0,?//類型注解分號后的空格規(guī)范
????//?react-hooks
????'react-hooks/rules-of-hooks':?'error',
????'react-hooks/exhaustive-deps':?'warn'
??}
};
現(xiàn)在,再也不能隨心所欲往你的代碼庫提交文件啦,不過 eslint 和 prettier 的規(guī)則要和團(tuán)隊的成員協(xié)商制定哈~
參考資料:
https://juejin.im/post/6844903831893966856
react-native-web 代碼庫配置
