1

目的

工程配置主要是为了能够在团队开发中统一代码规范,避免因为代码风格不统一或其它不一致的问题导致的整合冲突

  • 编辑器风格(EditorConfig、prettier)
  • 代码规范和校验(eslint、stylint)
  • git提交规范(commitlint)

参考文章:我是这样搭建Typescript+React项目环境的

vscode 必备插件

package.json

初始化package.json:

npm init -y

.gitignore

ctrl+shift+p 召唤命令面板,输入 Add gitignore 命令,新建 .gitignore

或者直接新建:

touch .gitignore

.npmrc

统一npm依赖源

# 创建 .npmrc 文件
touch .npmrc
# 在该文件内输入配置
registry=https://registry.npm.taobao.org/

因为项目中会用到reacttypescript,所以先装上这两个依赖包:

npm install typescript -D
npm install react react-dom -S

README.md

新建 README 文件

touch README.md

EditorConfig

.editorconfig是跨编辑器维护一致编码风格的配置文件

vscode安装插件EditorConfig,根目录新建文件.editorconfig:

touch .editorconfig

输入以下配置:

root = true

[*]
indent_style = tab
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf

[*.md]
trim_trailing_whitespace = false
  • indent_style 缩进风格,可选配置有 tab 和 space
  • indent_size 缩进大小
  • charset 编码格式
  • trim_trailing_whitespace 去除多余的空格
  • insert_final_newline 在尾部插入一行
  • end_of_line 换行符

更多配置可以查看EditorConfig

Prettier

Prettier统一项目风格

prettier 依赖包

npm install prettier -D

根目录新建文件.prettierrc:

touch .prettierrc

输入以下配置:

{
  "trailingComma": "none",
  "tabWidth": 2,
  "semi": true,
  "endOfLine": "lf",
  "printWidth": 120,
  "bracketSpacing": true,
  "arrowParens": "always"
}
  • trailingComma 对象的最后一个属性末尾添加,
  • tabWidth 缩进大小
  • semi 末尾是否添加分号
  • singleQuote 是否单引号
  • jsxSingleQuote jsx 语法是否单引号
  • endOfLine 与 .editorconfig 保持一致设置
  • printWidth 单行代码最长字符长度,超过之后会自动格式化换行
  • bracketSpacing 花括号里面有空格 {a:1} => { a: 1}
  • arrowParens 箭头函数的参数括号包裹 (a)=>{}

更多配置请查看Prettier Playground

prettier 插件

vscode 安装扩展 Prettier - Code formatter

根目录下新建文件夹.vscode,再此文件夹下新建settings.json:

mkdir .vscode
touch .vscode/settings.json
该文件的配置优先于 vscode 全局的 settings.json,不过要在工作区 workspace 的根目录下才会生效。

settings.json配置:

{
  // 指定哪些文件不参与搜索
  "search.exclude": {
    "**/node_modules": true,
    "dist": true,
    "build": true,
    "yarn.lock": true,
    "package-lock.json": true
  },
  "editor.formatOnSave": true,
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

ESLint

安装 eslint

npm install eslint -D

安装成功后,执行以下命令:

npx eslint --init

//termail
1、How would you like to use ESLint?
= To check syntax, find problems, and enforce code style
2、What type of modules does your project use?
= JavaScript modules (import/export)
3、Which framework does your project use?
= React
4、Does your project use TypeScript?
= Typescript
5、Where does your code run?
= Browser & Node
6、How would you like to define a style for your project?
= Use a popular style guide
7、Which style guide do you want to follow?
= Airbnb
8、What format do you want your config file to be in?
= JavaScript
9、Would you like to install them now with npm?
= Yes

对生成的.eslintrc.js文件,还要做以下修改:

  • 根据 eslint-config-airbnb 官方说明,如果要开启 React Hooks 的检查,需要在 extends 中添加一项 'airbnb/hooks'
  • 根据 @typescript-eslint/eslint-plugin 官方说明,在 extends 中添加 'plugin:@typescript-eslint/recommended' 可开启针对 ts 语法推荐的规则定义。
  • 需要添加一条很重要的 rule ,不然在typescript中通过import导入会报错

添加以下规则到 rules

rules: {
  'import/extensions': [
    ERROR,
    'ignorePackages',
    {
      ts: 'never',
      tsx: 'never',
      json: 'never',
      js: 'never',
    },
  ],
}

添加settings配置:

settings: {
    'import/resolver': {
        node: {
            extensions: ['.tsx', '.ts', '.js', '.json'],
        },
    },
},

ESLint 和 Prettier 的冲突

配置完会发现,vscode一直在标红,因为eslint的配置规则跟prettier冲突了

安装 eslint-config-prettier:

npm install eslint-config-prettier -D

添加以下配置到 .eslintrc.jsextends 中:

{
  extends: [
    // other configs ...
    'prettier',
    'prettier/@typescript-eslint',
    'prettier/react',
    'prettier/unicorn',
  ]
}

eslint 扩展插件

  • eslint-plugin-promise 让你把 Promise 语法写成最佳实践
  • eslint-plugin-unicorn 提供了更多有用的配置项
npm install eslint-plugin-promise eslint-plugin-unicorn -D

修改.eslintrc.js文件如下:

const OFF = 0;
const WARN = 1;
const ERROR = 2;

module.exports = {
    env: {
        browser: true,
        es2020: true,
        node: true
    },
    extends: [
        'airbnb',
        'airbnb/hooks',
        'plugin:react/recommended',
        'plugin:unicorn/recommended',
        'plugin:promise/recommended',
        'plugin:@typescript-eslint/recommended',
        'prettier',
        'prettier/@typescript-eslint',
        'prettier/react',
        'prettier/unicorn'
    ],
    parser: '@typescript-eslint/parser',
    parserOptions: {
        ecmaFeatures: {
            jsx: true
        },
        ecmaVersion: 11,
        sourceType: 'module'
    },
    plugins: ['react', 'unicorn', 'promise', '@typescript-eslint'],
    settings: {
        'import/resolver': {
            node: {
                extensions: ['.tsx', '.ts', '.js', '.json']
            },
            typescript: {}
        }
    },
    rules: {
        'import/extensions': [
            ERROR,
            'ignorePackages',
            {
                ts: 'never',
                tsx: 'never',
                js: 'never'
            }
        ],
        'import/no-extraneous-dependencies': [ERROR, { devDependencies: true }],
        'import/prefer-default-export': OFF,
        'import/no-unresolved': ERROR,

        'unicorn/better-regex': ERROR,
        'unicorn/prevent-abbreviations': OFF,
        'unicorn/filename-case': [
            ERROR,
            {
                cases: {
                    // 中划线
                    kebabCase: true,
                    // 小驼峰
                    camelCase: true,
                    // 下划线
                    snakeCase: false,
                    // 大驼峰
                    pascalCase: true
                }
            }
        ],
        'unicorn/no-array-instanceof': WARN,
        'unicorn/no-for-loop': WARN, // 使用 for of 和 .entries 代替传统的 for 循环
        'unicorn/prefer-add-event-listener': [
            ERROR,
            {
                excludedPackages: ['koa', 'sax']
            }
        ],
        'unicorn/prefer-query-selector': ERROR,
        'unicorn/no-null': OFF,
        'unicorn/import-style': OFF,

        '@typescript-eslint/no-useless-constructor': ERROR,
        '@typescript-eslint/no-empty-function': WARN,
        '@typescript-eslint/no-var-requires': OFF,
        '@typescript-eslint/explicit-function-return-type': OFF,
        '@typescript-eslint/explicit-module-boundary-types': OFF,
        '@typescript-eslint/no-explicit-any': OFF,
        '@typescript-eslint/no-unused-vars': [OFF],

        'react/jsx-filename-extension': [ERROR, { extensions: ['.tsx', 'ts', '.jsx', 'js'] }],
        'react/jsx-indent-props': [ERROR, 'tab'],
        'react/jsx-indent': [ERROR, 'tab'],
        'react/jsx-one-expression-per-line': OFF,
        'react/destructuring-assignment': OFF,
        'react/state-in-constructor': OFF,
        'react/jsx-props-no-spreading': OFF,
        'react/prefer-stateless-function': OFF,

        'jsx-a11y/click-events-have-key-events': OFF,
        'jsx-a11y/no-noninteractive-element-interactions': OFF,

        'lines-between-class-members': [ERROR, 'always'],
        indent: [ERROR, 'tab', { SwitchCase: 1 }],
        'linebreak-style': [ERROR, 'unix'],
        semi: [ERROR, 'always'],
        'no-unused-expressions': WARN,
        'no-plusplus': OFF,
        'no-console': OFF,
        'no-unused-vars': OFF,
        'no-use-before-define': OFF,
        'class-methods-use-this': ERROR,
        'global-require': OFF
    }
};

eslint vscode 配置

ESLint 插件可以提供编辑器自动修复功能

安装完成添加配置到 .vscode/settings.json

  "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
  "typescript.tsdk": "./node_modules/typescript/lib", // 代替 vscode 的 ts 语法智能提示
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
  },

.eslintignore 和 .prettierignore

新建 .eslintignore.prettierignore:

touch .eslintignore .prettierignore

输入以下内容:

/node_modules
/build
/dist

StyleLint

接下来统一样式风格,安装两个的依赖包包:

npm install stylelint stylelint-config-standard -D

项目根目录新建 .stylelintrc.js 文件:

touch .stylelintrc.js

输入以下内容:

module.exports = {
  extends: ['stylelint-config-standard'],
  rules: {
    'comment-empty-line-before': null,
    'declaration-empty-line-before': null,
    'function-name-case': 'lower',
    'no-descending-specificity': null,
    'no-invalid-double-slash-comments': null,
    'rule-empty-line-before': 'always',
  },
  ignoreFiles: ['node_modules/**/*', 'build/**/*'],
}
  • extends 预设规则扩展
  • rules 具体的规则
  • ignoreFiles 忽略配置字段
vscode同步配套插件 stylelint

.vscode/settings.json中新增以下代码:

{
    // 使用 stylelint 自身的校验即可
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false,

  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  },
}

stylelint extends 和 stylelint plugins

npm install stylelint-order stylelint-config-rational-order stylelint-declaration-block-no-ignored-properties -D

修改配置文件如下:

module.exports = {
  extends: ['stylelint-config-standard', 'stylelint-config-rational-order'],
  plugins: ['stylelint-order', 'stylelint-declaration-block-no-ignored-properties'],
  rules: {
    'plugin/declaration-block-no-ignored-properties': true,
    'comment-empty-line-before': null,
    'declaration-empty-line-before': null,
    'function-name-case': 'lower',
    'no-descending-specificity': null,
    'no-invalid-double-slash-comments': null,
    'rule-empty-line-before': 'always'
  },
 ignoreFiles: ['node_modules/**/*', 'build/**/*', 'dist/**/*']
};

解决 Stylelint 和 Prettier 的冲突

安装 stylelint-config-prettier:

npm install stylelint-config-prettier -D

添加以下配置到 .stylelintrc.js 的 extends 中:

{
    extends: [
    // other configs ...
    'stylelint-config-prettier'
  ]
}

lint 命令

我们在 package.json 的 scripts 中增加以下三个配置:

 "scripts": {
    "lint": "npm run lint-eslint && npm run lint-stylelint",
    "lint-eslint": "eslint -c .eslintrc.js --ext .ts,.tsx,.js src",
    "lint-stylelint": "stylelint --config .stylelintrc.js src/**/*.{less,css,scss}"
  },

lint-staged

只针对 git 缓存区最新改动过的文件进行 格式化 和 lint 规则校验

husky

husky可以提供一些钩子,比如执行 git commit 之前的钩子 pre-commit ,借助这个钩子我们就能执行 lint-staged 所提供的代码文件格式化及 lint 规则校验。

如果项目开始前没有初始化的.git文件,要先初始化git,否则husky会安装失败:

git init

安装 lint-stagedhusky :

npm install husky lint-staged -D

package.json 中添加以下代码:

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
    }
  },
  "lint-staged": {
    "*.{ts,tsx,js}": [
      "eslint --config .eslintrc.js"
    ],
    "*.{css,less,scss}": [
      "stylelint --config .stylelintrc.js"
    ],
    "*.{ts,tsx,js,json,html,yml,css,less,scss,md}": [
      "prettier --write"
    ]
  },
}

commitlint + changelog

在多人协作的项目中,如果 git 的提交说明精准,在后期协作以及 bug 处理时会变得有据可查,项目的开发可以根据规范的提交说明快速生成开发日志,从而方便开发者或用户追踪项目的开发信息和功能特性。
建议阅读 Commit message 和 Change log 编写指南(阮一峰)

commitlint 可以帮助我们在 git commit 时校验 message 格式是否符合规范,conventional-changelog 可以帮助我们快速生成 changelog

commitizen 可以在命令行中进行可视化的 git commit 操作,这里不作配置

安装 commitlint 相关依赖:

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

@commitlint/config-conventional 类似 eslint 配置文件中的 extends ,它是官方推荐的 angular 风格的 commitlint 配置,提供了少量的 lint 规则

根目录新建文件 .commitlintrc.js :

touch .commitlintrc.js

写入以下代码:

/**
 * build : 改变了build工具 如 webpack
 * ci : 持续集成新增
 * chore : 构建过程或辅助工具的变动
 * feat : 新功能
 * docs : 文档改变
 * fix : 修复bug
 * perf : 性能优化
 * refactor : 某个已有功能重构
 * revert : 撤销上一次的 commit
 * style : 代码格式改变
 * test : 增加测试
 * anno: 增加注释
 */

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      ['build', 'ci', 'chore', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'anno'],
    ],
  },
};

package.jsonhusky 配置,增加一个钩子:

{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint --config .commitlintrc.js -E HUSKY_GIT_PARAMS"
    }
  },
}

-E HUSKY_GIT_PARAMS 简单理解就是会拿到我们的 message ,然后 commitlint 再去进行 lint 校验。

安装依赖changelog

npm install conventional-changelog-cli -D

在 package.json 的 scripts 下增加一个命令:

{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
  },
}

之后就可以通过 npm run changelog 生成 angular 风格的 changelog ,需要注意的是,上面这条命令产生的 changelog 是基于上次 tag 版本之后的变更(featfix 等等)所产生

测试:

# 提交所有变化到缓存区
git add -A
# 把暂存区的所有修改提交到分支
git commit -m "chore: add commitlint to force commit style"

git push origin master

chenwl
117 声望5 粉丝

平坦的路面上曲折前行