前端基建之(一)代码风格和提交规范配置

Posted by 汪洋龙 on Tuesday, December 13, 2022

前端基建之(一)代码风格和提交规范配置

1. 初始化项目

npx create-react-app demo-framework --template typescript

2. 配置 Eslint

2.1 vscode 安装 eslint

2.2 安装依赖

npm i eslint -D

2.3 初始化 eslint

npx eslint --init

You can also run this command directly using 'npm init @eslint/config'.
npx: installed 41 in 3.304s
✔ 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? · JavaScript
The config that you've selected requires the following dependencies:

eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now? · No ✔ / Yes
A config file was generated, but the config file itself may not follow your linting rules.
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
  ],
  overrides: [],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
  },
  plugins: ["react", "@typescript-eslint"],
  rules: {},
};

2.4 社区规范

三种社区主流规范

  • Airbnb
  • Standard
  • Google

Star History Chart

2.5 配置 airbnb 规范

  1. 安装 eslint-config-airbnb
npm i eslint-config-airbnb -D
  1. .eslintrc.js 配置规则
//  .eslintrc.js
{
    ...
    "extends": [
        "airbnb",
        ...
    ]
    ...
}
  1. package.json 配置 script
...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "lint": "eslint src --ext .ts,.jsx,.tsx --fix --quiet"
  },
...
  1. 修复运行错误
  • error Unable to resolve path to module './App' import/no-unresolved
npm i eslint-import-resolver-typescript -D
// .eslintrc
...
  rules: {},
  settings: {
    "import/resolver": {
      typescript: {
        directory: "./tsconfig.json",
      },
    },
  },
...
  • error Missing file extension for "./App" import/extensions
// .eslintrc
...
  rules: {
    "react/jsx-filename-extension": [
      2,
      {
        extensions: [".js", ".jsx", ".ts", ".tsx"],
      },
    ],
  },
...
  • error JSX not allowed in files with extension '.tsx' react/jsx-filename-extension
// .eslintrc
  rules: {
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        js: "never",
        jsx: "never",
        ts: "never",
        tsx: "never",
      },
    ],
  },
  • error Do not use a triple slash reference for react, use import style instead @typescript-eslint/triple-slash-reference
// .eslintrc
  rules: {
    "@typescript-eslint/triple-slash-reference": "warn",
  }
  • 'React' must be in scope when using JSX react/react-in-jsx-scope
// .eslintrc
  rules: {
    "react/react-in-jsx-scope": "off",
  }

3. prettier

Prettier 官网

3.1 跟 Linters 区别

Prettier vs. Linters

In other words, use Prettier for formatting and linters for catching bugs!

3.2 vscode 安装 prettier

  1. VsCode 安装 Prettier - Code formatter

  2. 设置自动保存

设置自动保存

  1. 编辑器的 settings.json 的配置项

点击上图 👆 中的 Edit in settings.json 设置

{
  ...
   "editor.defaultFormatter": "esbenp.prettier-vscode",
   ...
}

3.3. 规则设定

标签名含义属性默认值
Print Width行宽度printWidth80
Tab WidthTab 宽度tabWidth2
Tabs是否使用 TabuseTabsfalse
Semicolons是否句末开启分号semitrue
Quotes是否启用单引号singleQuotefalse
Quote PropsquotePropsas-needed
JSX QuotesJSX 是否用单引号jsxSingleQuotefalse
Trailing Commas尾部逗号trailingCommaes5
Bracket Spacing括号空格bracketSpacingtrue
Bracket Line括号换行bracketSameLinefalse
Arrow Function Parentheses剪头函数括号arrowParensalways
Range格式化范围rangeStart rangeEnd
Parser指定解析器parser
File Pathfilepath``
Require PragmarequirePragmafalse
Insert PragmainsertPragmafalse
Prose WrapproseWrappreserve
HTML Whitespace SensitivityhtmlWhitespaceSensitivitycss
Vue files script and style tags indentationvueIndentScriptAndStylefalse
End of LineendOfLinelf
Embedded Language FormattingembeddedLanguageFormattingauto
Single Attribute Per LinesingleAttributePerLinefalse

3.4 案例

"use strict";

const { esNextPaths } = require("./scripts/shared/pathsByLanguageVersion");

module.exports = {
  bracketSpacing: false,
  singleQuote: true,
  jsxBracketSameLine: true,
  trailingComma: "es5",
  printWidth: 80,
  parser: "babel",

  overrides: [
    {
      files: esNextPaths,
      options: {
        trailingComma: "all",
      },
    },
  ],
};
{
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "proseWrap": "never",
  "overrides": [
    {
      "files": ".prettierrc",
      "options": {
        "parser": "json"
      }
    }
  ]
}
{
  "printWidth": 100,
  "tabWidth": 2,
  "tabs": false,
  "singleQuote": true,
  "semicolon": true,
  "quoteProps": "preserve",
  "bracketSpacing": false
}
semi: false
singleQuote: true
printWidth: 80
trailingComma: 'none'
arrowParens: 'avoid'

3.5 配置 prettier

  1. 安装
npm i prettier -D
  1. 根目录创建 .prettierrc
{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true
}
  1. package.json 新增命令
...
"scripts": {
    ...
    "prettier": "prettier --write **/*.{js,jsx,ts,tsx,json}"
    ...
}
...

3.6 解决和 eslint 的冲突

因为 eslint 也可以做风格检查,所以会跟 prettier 冲突

例如:在 prettier 中设置 "semi": false,在 eslintrc 中设置 semi: 2。保存文件会取消分号,但是 npm run lint 之后又会新增分号。

  1. prettier 集成到 eslint
npm i eslint-config-prettier -D # 关闭可能与prettier冲突的规则
npm i eslint-plugin-prettier -D # 使用prettier代替eslint格式化
  1. 设置 prettier 为默认格式化并设置保存时生效

.eslintrc 中配置 prettier

...
  extends: [
    'airbnb',
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'
  ],
  ...

4. 配置 StyleLint

4.1 vscode 安装 Stylelint 插件

4.2 安装依赖

npm install --save-dev stylelint stylelint-config-standard

4.3 根目录创建 .stylelintrc

// .stylelintrc
{
  "extends": "stylelint-config-standard"
}

4.4 解决与 prettier 配置的冲突

npm install --save-dev stylelint-config-prettier

4.5 修改 stylelintrc

// .stylelintrc
{
  "extends": ["stylelint-config-standard", "stylelint-config-prettier"]
}

4.6 在 git commit 阶段检测

...
 "scripts": {
    ...
    "lint:style": "stylelint src/**/*.less",
    ...
 },
...

5. 配置别名

5.1 @craco/craco

安装

npm i -D @craco/craco

根目录新建 craco.config.js

const path = require("path");

const pathResolve = (pathUrl) => path.join(__dirname, pathUrl);

module.exports = {
  webpack: {
    alias: {
      "@": pathResolve("src"),
      "@assets": pathResolve("src/assets"),
      "@components": pathResolve("src/components"),
      "@utils": pathResolve("src/utils"),
    },
  },
};

修改 tsconfig.json 配置文件

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@utils/*": ["utils/*"]
    }
  }
  //   ...
}

修改 package.json

...
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject"
  },
...

5.2 webpack

暴露 webpack 配置

npm run eject

修改 config/webpack/webpack.config.js

...
    alias: {
    // Support React Native Web
    // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
    "react-native": "react-native-web",
    // Allows for better profiling with ReactDevTools
    ...(isEnvProductionProfile && {
        "react-dom$": "react-dom/profiling",
        "scheduler/tracing": "scheduler/tracing-profiling",
    }),
    ...(modules.webpackAliases || {}),
    "@utils": path.resolve(__dirname, "../src/utils"),
    },
...

修改 tsconfig.json 配置文件

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@utils/*": ["utils/*"]
    }
  }
  //   ...
}

6. Husky

git hooks 自动化校验

6.1 安装 husky

npm i husky -D

6.2 初始化 husky

npx husky install

6.3 启用 husky

我们需要在每次执行 npm install 时自动启用 husky

修改 package.json

  "scripts": {
    "prepare": "husky install"
  },

6.4 添加 lint 钩子

npx husky add .husky/pre-commit "npm run lint"

6.5 添加 lint-staged

用来对 暂存区 的文件进行检测,用不全量检查

npm install --save-dev lint-staged

修改 .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# npm run lint
npx lint-staged

修改 package.json

...
  "scripts": {
    ...
  },
  "lint-staged": {
    "**/*.{jsx,ts,tsx}": "npm run lint"
  },
  //  "lint-staged": {
  //   "**/*": "prettier --write --ignore-unknown", //格式化
  //   "src/**.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx", //对js文件检测
  //   "**/*.{less,css}": "stylelint --fix", //对css文件进行检测
  //   "**/*.{jsx,ts,tsx}": "npm run lint",
  //   "**/*.{less,css}": "npm run lint:style"
  // },
...

7. Commitlint

约定 commit 信息

7.1 安装

npm i @commitlint/cli @commitlint/config-conventional -D

7.2. 创建 .commitlintrc,写入配置

{
  "extends": ["@commitlint/config-conventional"]
}

7.3. 集成 husky

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
  • feat: 新功能
  • fix: 修补 BUG
  • docs: 修改文档,eg:README,CHANGELOG,CONTRIBUTE 等
  • style: 不改变代码逻辑(仅仅修改空格、格式缩进、逗号等)
  • refactor: 重构(既不修复错误也不添加功能)
  • perf:优化相关,比如提升性能、体验
  • test:增加测试,包括单元测试、集成测试等
  • build:构建系统或外部依赖项的更改
  • ci:自动化流程配置或脚本修改
  • chore:非 src 和 test 的修改,发布版本等
  • revert:恢复先前的提交

8. Semantic Release