花十分鐘的時間武裝你的代碼庫

當咱們的代碼庫有不少人維護時,常常會出現代碼風格不一致或者代碼質量不過關,提交信息雜亂的狀況,固然啦,即便是一我的的代碼庫,有的時候,本身寫代碼時不太注意細節,也會出現風格不一致的狀況。前端

本文正是爲了解決這個問題而生,閱讀本篇文章並不須要很長時間,若是你的代碼庫尚未進行這些配置,正是你大展身手的好時機,武裝一下你的代碼庫。node

1. 規範 commit 信息

首先,看下 angular 的代碼庫的 commit 記錄,如圖:react

咱們能夠利用 commitizenhusky 來規範代碼庫的 commit
git

安裝如下依賴:
npm install @commitlint/cli @commitlint/config-conventional husky  -D

若是你尚未安裝過 commitizen,那麼先全局安裝:es6

npm install commitizen -g
在 package.json 中增長 husky 字段。
{
    "husky": {
        "hooks": {
            "commit-msg""commitlint -E HUSKY_GIT_PARAMS"
        }
    },
}

huskygit hook 工具,使用 husky,咱們能夠方便的在 package.json 中配置 git hook 腳本,例如: pre-commitpre-pushcommit-msg 等的。github

建立 commitlint.config.js 文件
module.exports = {
    extends: ["@commitlint/config-conventional"],
};

此刻開始,請使用 git cz 來替代 git commit 提交信息,咱們來看看,假設咱們隨便寫一個 git commit -m 'fixbug' 會提示什麼?web

使用 git cz 來進行填寫 commit 的內容。正則表達式

git cztype 說明:npm

雖然,咱們如今已經能夠規範提交信息了,可是咱們可能不喜歡默認的交互,例如,一個精簡的描述就能夠了,不但願再提示我去寫詳細的描述,那麼就可使用 cz-customizable 來進行定製。json

自定義提交說明

安裝 cz-customizable
npm install cz-customizable -D

cz-customizable 是可自定義的 Commitizen 插件,可幫助實現一致的 commit message

cz-customizable 適合大型團隊去自定義 scope,和 commit type

新建 .cz-config.js

在項目根目錄下建立 .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' }],

  allowTicketNumberfalse,
  isTicketNumberRequiredfalse,
  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?',
  },

  allowCustomScopestrue,
  allowBreakingChanges: ['feat''fix'],
  // skip any questions you want
  skipQuestions: ['body'],

  // limit subject length
  subjectLimit: 100,
};
  • types: 描述修改的性質是什麼,是bugfix仍是feat,在這裏進行定義。

  • scopes: 定義以後,咱們就能夠經過上下鍵去選擇 scope

  • scopeOverrides: 針對每個type去定義scope

  • allowBreakingChanges: 如上設置爲 ['feat', 'fix'],只有咱們type選擇了 feat 或者是 fix,纔會詢問咱們 breaking message.

  • allowCustomScopes: 設置爲 true,在 scope 選擇的時候,會有 emptycustom 能夠選擇,顧名思義,選擇 empty 表示 scope 缺省,若是選擇 custom,則能夠本身輸入信息

  • skipQuestions: 指定跳過哪些步驟,例如跳過咱們剛剛說的詳細描述,設置其爲 scope: ['body'],假設咱們的項目也不會涉及到關聯 issue,咱們能夠設置其爲 scope: ['body', 'footer']

  • subjectLimit: 描述的長度限制

這裏我就不一一演示每一個字段修改以後的狀況了,根據字段的說明,建議若是想自定義提交規則,在本地進行修改驗證,公司內部的代碼庫不須要管理 issue,另外,我不喜歡寫長描述,因此我把 bodyfooterskip 掉了。

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"
    }
}

如今,咱們已經規範了 commit 信息,可是沒有對提交的代碼進行規範,在一個代碼庫中,常常出現2個空格/4個空格混用,有些地方寫 ;,有些不寫 ;,風格不統一。例如,咱們但願提交到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"
    ]
}

這樣配置以後,每次提交的時候,都會對要提交的文件(並非對整個項目)進行 prettier 格式化和 eslint 檢查,都經過以後,才能 commit 成功。

eslint 和 prettier 配置

個人項目是 react 項目,下面是我進行的配置。

安裝 eslintprettier 相關依賴:

npm install eslint eslint-config-prettier eslint-plugin-promise eslint-plugin-react eslint-plugin-react-hooks prettier babel-eslint -D

新建 .prettierrc.js

固然啦,你也能夠在 package.jsonprettier 字段中配置,這裏我配置成了獨立的文件,以便後期維護。

module.exports = {
  printWidth100//長度超過100斷行
  singleQuote: true,//使用單引號
};

若是你有一些文件不須要 prettier 進行格式化,那麼能夠新建一個 .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: {
    ecmaVersion7,
    ecmaFeatures: {
      experimentalObjectRestSpreadtrue,
      jsxtrue
    },
    sourceType'module'
  },
  extends: [
    'prettier'
    'prettier/react'
  ],
  plugins: [
    'promise'
    'react'
    'react-hooks'
  ],
  env: {
    browsertrue,
    es6true,
    nodetrue
  },
  rules: {
    'no-compare-neg-zero'2//禁止與 -0 進行比較
    'no-cond-assign'2//禁止條件表達式中出現賦值操做符
    'no-console'1//禁用 console
    'no-constant-condition'1//禁止在條件中使用常量表達式
    'no-control-regex'1//禁止在正則表達式中使用控制字符
    'no-debugger'2//禁用 debugger
    'no-dupe-args'2//禁止 function 定義中出現重名參數
    'no-dupe-keys'2//禁止對象字面量中出現重複的 key
    'no-duplicate-case'2//禁止出現重複的 case 標籤
    'no-const-assign'1//禁止修改const聲明的變量
    'no-empty'1//禁止出現空語句塊
    'no-empty-character-class'2//禁止在正則表達式中使用空字符集
    'no-ex-assign'2//禁止對 catch 子句的異常參數從新賦值
    'no-extra-boolean-cast'1//禁止沒必要要的布爾轉換
    'no-extra-semi'1//禁止沒必要要的分號
    'no-func-assign'2//禁止對 function 聲明從新賦值
    'no-inner-declarations'0//禁止在嵌套的塊中出現變量聲明或 function 聲明,ES6中無需禁止
    'no-invalid-regexp'2//禁止 RegExp 構造函數中存在無效的正則表達式字符串
    'no-irregular-whitespace'1//禁止在字符串和註釋以外不規則的空白
    'no-obj-calls'2//禁止把全局對象做爲函數調用,好比Math() JSON()
    'no-regex-spaces'1//禁止正則表達式字面量中出現多個空格
    'no-sparse-arrays'1//禁用稀疏數組
    'no-unexpected-multiline'1//禁止出現使人困惑的多行表達式
    'no-unreachable'1//禁止在return、throw、continue 和 break 語句以後出現不可達代碼
    'no-unsafe-finally'2//禁止在 finally 語句塊中出現控制流語句
    'no-unsafe-negation'1//禁止對關係運算符的左操做數使用否認操做符
    'use-isnan'2//要求使用 isNaN() 檢查 NaN,如 isNaN(foo),而非foo == NaN
    'valid-typeof'2//強制 typeof 表達式與有效的字符串(如: 'undefined', 'object', 'boolean', 'number', 'string', 'function','symbol')進行比較
    'no-case-declarations'1//不容許在 case 子句中使用詞法聲明
    'no-empty-pattern'2//禁止使用空解構模式
    'no-fallthrough'2//禁止 case 語句落空
    'no-global-assign'2//禁止對原生對象或只讀的全局對象進行賦值
    'no-octal'1//禁用八進制字面量
    'no-redeclare'1//禁止屢次聲明同一變量
    'no-self-assign'1//禁止自我賦值
    'no-unused-labels'1//禁用出現未使用過的標
    'no-useless-escape'1//禁用沒必要要的轉義字符
    'no-delete-var'2//禁止刪除變量
    'no-undef'2//禁用使用未聲明的變量,除非它們在 /*global */ 註釋中被提到
    'no-unused-vars'1//禁止出現未使用過的變量
    'constructor-super'2//要求在構造函數中有 super() 的調用
    'no-class-assign'2//禁止給類賦值
    'no-dupe-class-members'2//禁止類成員中出現重複的名稱
    'no-new-symbol'2//禁止 Symbol 和 new 操做符一塊兒使用
    'no-this-before-super'2//禁止在構造函數中,在調用 super() 以前使用 this 或 super
    'require-yield'2//要求 generator 函數內有 yield
    'no-mixed-spaces-and-tabs'1//要求不適用space,tab混用
    'react/forbid-prop-types': [1, { forbid: ['any'] }], //禁止某些propTypes
    'react/prop-types'1//沒用對props類型進行校驗
    'react/jsx-closing-bracket-location'1//在JSX中驗證右括號位置
    'react/jsx-curly-spacing': [1, { when'never'childrentrue }], //在JSX屬性和表達式中增強或禁止大括號內的空格。
    'react/jsx-key'2//在數組或迭代器中驗證JSX具備key屬性
    'react/jsx-max-props-per-line': [1, { maximum1 }], // 限制JSX中單行上的props的最大數量
    'react/jsx-no-duplicate-props'2//防止在JSX中重複的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//防止反應被錯誤地標記爲未使用
    'react/jsx-uses-vars'1//防止在JSX中使用的變量被錯誤地標記爲未使用
    '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組件強制執行ES5或ES6類
    'react/react-in-jsx-scope'0//使用JSX時,必需要引入React
    'react/sort-comp'0//強制組件方法順序
    'react/sort-prop-types'0//強制組件屬性順序
    'react/jsx-sort-props'1,
    'react/no-deprecated'1//不使用棄用的方法
    'react/jsx-equals-spacing'1//在JSX屬性中強制或禁止等號周圍的空格
    'react/wrap-multilines'0,
    'comma-dangle'1//對象字面量項尾不能有逗號
    'react/no-multi-comp'0//防止每一個文件有多個組件定義
    'flowtype/generic-spacing'0//泛型對象的尖括號中類型先後的空格規範
    'flowtype/space-after-type-colon'0//類型註解分號後的空格規範
    // react-hooks
    'react-hooks/rules-of-hooks''error',
    'react-hooks/exhaustive-deps''warn'
  }
};

如今,不再能爲所欲爲往你的代碼庫提交文件啦,不過 eslintprettier 的規則要和團隊的成員協商制定哈~

參考資料:

  1. https://juejin.im/post/6844903831893966856

  2. react-native-web 代碼庫配置

學習交流

  • 關注公衆號【前端宇宙】,每日獲取好文推薦
  • 添加微信,入羣交流

「在看和轉發」 就是最大的支持


本文分享自微信公衆號 - 前端宇宙(gh_8184da923ced)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索