When our code base is maintained by many people, it is often the case that the code style is inconsistent or the code quality is not good, and the submission information is disordered. Of course, even the code base of one person can sometimes be inconsistent when they write their own code without paying much attention to details.

This article is designed to solve this problem. It doesn’t take long to read this article. Take a few minutes to read it.

1. Specify commit information

First, take a look at the Angular code base commit record, as shown below:

We can use Commitizen and Husky to standardize the commit of the code base.

Install the following dependencies:
npm install @commitlint/cli @commitlint/config-conventional husky  -D
Copy the code

If you haven’t already installed Commitizen, install it globally first:

npm install commitizen -g
Copy the code
Add a husky field to package.json.
{
    "husky": {
        "hooks": {
            "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"}}},Copy the code

Husky is a Git hook tool. Using Husky, you can easily configure git hook scripts in package.json, such as pre-commit, pre-push, commit-msg, etc.

Create the commitlint.config.js file
module.exports = {
    extends: ["@commitlint/config-conventional"]};Copy the code

Git commit -m ‘fixbug’ : git commit -m ‘fixbug’ : git commit -m

Use git Cz to fill in the commit content.

Git cz git cz

Although we can now normalize the submission information, we may not like the default interaction, for example, if a simplified description is ok and I don’t want to be prompted to write a detailed description, then WE can use CZ-Customizable.

Customize submission instructions

Install the cz – customizable
npm install cz-customizable -D
Copy the code

Cz-customizable is a customizable Commitizen plug-in that helps achieve a consistent COMMIT message.

Cz-customizable is suitable for large teams to customize scope, and COMMIT Type.

New. Cz – config. Js

Create the.cz-config.js file in the project root directory:

The official configuration information is available at github.com/leoforfree/…

//.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};Copy the code
  • Types: Describes what the modification is, bugfix or feat, defined here.
  • Scopes: After the scopes are defined, we can select them by pressing up and downscope
  • ScopeOverrides: defines scope for each type
  • AllowBreakingChanges: Set to['feat', 'fix'], only we type choosefeatOr is itfix“Will ask us about the breaking message.
  • AllowCustomScopes: Set to true and run at scope when selectedemptycustomYou can choose, as the name suggests, to chooseemptysaidscopeBy default, if selectedcustom, you can input information by yourself
  • SkipQuestions: Specify which steps to skip, for example skip the detailed description we just talked about, set it toscope: ['body'], assuming that our project will not involve the associated issue, we can set it toscope: ['body', 'footer']
  • SubjectLimit: Specifies the length of the description

Here I will not demonstrate the situation after each field modification. According to the field description, it is suggested that if you want to customize the submission rule, you can verify the modification locally, and the internal code base of the company does not need to manage the issue. In addition, I do not like to write long descriptions, so I skip the body and footer.

Cz-customizable will first look in the project root directory:.cz-config.js or.config/cz-config.js. If it cannot find it, it will look in the home directory. We can also specify the configuration file path manually in package.json.

"config": {
    "commitizen": { 
        "path": "node_modules/cz-customizable"
    },
    "cz-customizable": {
        "config": "config/path/to/my/config.js"}}Copy the code

Now that we’ve normalized the commit information, but not the committed code, we often have 2 Spaces /4 Spaces mixed up in a code base, and some places write; , some don’t; , the style is not unified. For example, we want to submit code to git libraries that can be checked by ESLint or tested. We can use the pre-commit hook to do this.

2. Check the code before submission

Install dependencies
npm install lint-staged -D
Copy the code
Use pre-commit hooks
"husky": {
    "hooks": {
        "pre-commit": "lint-staged"}},"lint-staged": {
    "**/*.js": [
        "prettier --write"."eslint"]}Copy the code

Prettier formatting and ESLint checking occur every commit before the file (not the whole project) prettier formatting and ESLint checking are done.

Eslint and prettier configurations

My react project is the react project. Here is how I configured it.

Installing esLint and Prettier dependency:

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

New. Prettierrc. Js

Of course, you can also prettier the package.json field, which I configured as a separate file for later maintenance.

module.exports = {
  printWidth: 100.// The length exceeds 100 lines
  singleQuote: true.// Use single quotes
};
Copy the code

If you do not need prettier to format a file, create a new. Prettier ignore file like this:

dist
node_modules
public
Copy the code

Create the.eslintrc.js file

Here is my configuration:

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.// Disallow comparisons with -0
    'no-cond-assign': 2.// Disallow assignment operators in conditional expressions
    'no-console': 1./ / disable the console
    'no-constant-condition': 1.// Disallow constant expressions in conditions
    'no-control-regex': 1.// Disallow control characters in regular expressions
    'no-debugger': 2./ / disable the debugger
    'no-dupe-args': 2.// Disallow duplicate arguments in function definitions
    'no-dupe-keys': 2.Disallow duplicate keys in object literals
    'no-duplicate-case': 2.// Disallow duplicate case tags
    'no-const-assign': 1.// Disallow modifying variables declared by const
    'no-empty': 1.// Disallow empty statement blocks
    'no-empty-character-class': 2.// Disallow null character sets in regular expressions
    'no-ex-assign': 2.// Disallows reassignment of exception parameters in the catch clause
    'no-extra-boolean-cast': 1.// Disable unnecessary Boolean conversions
    'no-extra-semi': 1.// Disallow unnecessary semicolons
    'no-func-assign': 2.// Disallow reassignment of function declarations
    'no-inner-declarations': 0.// Disallow variable declarations or function declarations in nested blocks, no need in ES6
    'no-invalid-regexp': 2.// Disallow invalid regular expression strings in the RegExp constructor
    'no-irregular-whitespace': 1.// Disallow irregular whitespace outside strings and comments
    'no-obj-calls': 2.// Disallow global objects as function calls, such as Math() JSON()
    'no-regex-spaces': 1.Disallow multiple Spaces in regular expression literals
    'no-sparse-arrays': 1.// Disable sparse arrays
    'no-unexpected-multiline': 1.// Disallow confusing multi-line expressions
    'no-unreachable': 1.// Disallows unreachable code after return, throw, continue, and break statements
    'no-unsafe-finally': 2.// Disallow control flow statements in finally blocks
    'no-unsafe-negation': 1.// Disallow the negation operator on the left-hand operand of relational operators
    'use-isnan': 2.// Require the use of isNaN() to check NaN, such as isNaN(foo) instead of foo == NaN
    'valid-typeof': 2.// Forces typeof expressions to be compared with valid strings such as 'undefined', 'object', 'Boolean ',' number', 'string', 'function','symbol')
    'no-case-declarations': 1.// Lexical declarations are not allowed in case clauses
    'no-empty-pattern': 2.// Disallow empty destruct mode
    'no-fallthrough': 2.// Disallow case statements from falling through
    'no-global-assign': 2.// Disallow assignment to native or read-only global objects
    'no-octal': 1.// Disable octal literals
    'no-redeclare': 1.// Do not declare the same variable more than once
    'no-self-assign': 1.// Disallow self-assignment
    'no-unused-labels': 1.// Disable unused tokens
    'no-useless-escape': 1.// Disable unnecessary escape characters
    'no-delete-var': 2.// Disable variable deletion
    'no-undef': 2.// Disable the use of undeclared variables unless they are mentioned in the /*global */ comment
    'no-unused-vars': 1.// Disallow unused variables
    'constructor-super': 2.// Requires a call to super() in the constructor
    'no-class-assign': 2.// Disallow class assignment
    'no-dupe-class-members': 2.// Disallow duplicate names in class members
    'no-new-symbol': 2.// Disallow the Symbol and new operators
    'no-this-before-super': 2.// Disallow this or super before calling super() in constructors
    'require-yield': 2.// Require that generator functions contain yield
    'no-mixed-spaces-and-tabs': 1.// Request does not apply to space, TAB
    'react/forbid-prop-types': [1, { forbid: ['any']}],// Disable certain propTypes
    'react/prop-types': 1.// The props type was not verified
    'react/jsx-closing-bracket-location': 1.// Verify the close parenthesis position in JSX
    'react/jsx-curly-spacing': [1, { when: 'never'.children: true}].// Enforce or disallow Spaces in braces in JSX attributes and expressions.
    'react/jsx-key': 2.// Verify that JSX has the key attribute in an array or iterator
    'react/jsx-max-props-per-line': [1, { maximum: 1}].// Limit the maximum number of props on a single line in JSX
    'react/jsx-no-duplicate-props': 2.// Prevent duplicate props in JSX
    'react/jsx-no-undef': 1.// Disallow undeclared variables in JSX
    'react/no-string-refs': 1.//Using string literals in ref attributes is deprecated
    'react/jsx-uses-react': 1.// Prevent reactions from being incorrectly marked as unused
    'react/jsx-uses-vars': 1.// Prevent variables used in JSX from being incorrectly marked as unused
    'react/no-danger': 1.// Prevent the use of dangerous JSX attributes
    'react/no-did-update-set-state': 2.Prevent setState from being used in componentDidUpdate
    'react/no-did-mount-set-state': 0.Prevent setState from being used in componentDidUpdate
    'react/no-direct-mutation-state': 2.// Prevent this.state from being assigned
    'react/no-unknown-property': 2.// Prevent using unknown DOM attributes
    'react/prefer-es6-class': 1.// Enforce ES5 or ES6 classes for the React component
    'react/react-in-jsx-scope': 0.// When using JSX, React must be introduced
    'react/sort-comp': 0.// Enforce component method order
    'react/sort-prop-types': 0.// Enforce component property order
    'react/jsx-sort-props': 1.'react/no-deprecated': 1.// Do not use deprecated methods
    'react/jsx-equals-spacing': 1.Enforces or disallows Spaces around equals signs in JSX attributes
    'react/wrap-multilines': 0.'comma-dangle': 1.Object literals cannot end with commas
    'react/no-multi-comp': 0.// Prevent multiple component definitions per file
    'flowtype/generic-spacing': 0.// The whitespace specification before and after the type in Angle brackets on a generic object
    'flowtype/space-after-type-colon': 0.Type annotation space specification after semicolon
    // react-hooks
    'react-hooks/rules-of-hooks': 'error'.'react-hooks/exhaustive-deps': 'warn'}};Copy the code

No longer can you just commit files to your code base, but rules for EsLint and Prettier must be worked out in consultation with members of the team

References:

  1. Juejin. Cn/post / 684490…
  2. React-native Web code base configuration

Pay attention to the public number, join the technical exchange group