前端规范化开发实践

1,294 阅读3分钟

本文以 React Native 项目为示例介绍了前端规范化开发涉及的工具及知识,但是所涉及内容具有通用性,建议读者点赞收藏(^▽^)。

gitconfig

# 初始化设置
$ git config --global user.name 'your_name'
$ git config --global user.email 'your_email@aliyun.com'
# 提高命令输出的可读性
$ git config --global color.ui auto
# git 记住用户名和密码
$ git config --global credential.helper store
# core.autocrlf
$ git config --global core.autocrlf input

以上配置内容可以在 ~/.gitconfig 文件中找到。

npm scripts

package.json 文件的 scripts 字段是定义可执行脚本用的,可以利用它来实现简单的工作流。如果不是大型的项目,不建议使用 gulp,npm scripts 一样可以完成工作流设计的任务。下面是 React Native 项目默认的 scripts,如今我们可以把使用和扩展 scripts 看做是前端基本功。

{
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "format": "prettier --write src/**/*/*.{js,jsx,ts,tsx}",
    "lint": "eslint src --ext .js,.jsx,.ts,.tsx --fix"
  }
}

使用 EditorConfig 实现跨编辑器代码风格统一

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[*.gradle]
indent_size = 4

[BUCK]
indent_size = 4

使用ESLint规范代码

安装依赖

$ yarn add -D eslint typescript eslint-config-airbnb-typescript
# 支持 react
$ yarn add -D eslint-plugin-import@^2.22.0 \
            eslint-plugin-jsx-a11y@^6.3.1 \
            eslint-plugin-react@^7.20.3 \
            eslint-plugin-react-hooks@^4.0.8 \
            @typescript-eslint/eslint-plugin@^4.4.1
# 支持 react-native
$ yarn add -D eslint-plugin-react-native
# 支持 jest
$ yarn add -D eslint-plugin-jest babel-jest @babel/core metro-react-native-babel-preset
# 支持 prettier
$ yarn add -D prettier eslint-plugin-prettier eslint-config-prettier

package.json

{
   "eslintConfig": {
    "extends": [
      "airbnb-typescript",
      "plugin:jest/recommended",
      "plugin:react-native/all",
      "plugin:@typescript-eslint/recommended",
      "plugin:prettier/recommended",
      "prettier",
      "prettier/react",
      "prettier/@typescript-eslint"
    ],
    "parserOptions": {
      "project": "./tsconfig.json",
    },
    "env": {
      "react-native/react-native": true
      "jest/globals": true,
    }
  }
}

.prettierrc.js

module.exports = {
  printWidth: 150, // 一行的字符数,如果超过会进行换行,默认为80
  tabWidth: 2, // tab缩进大小,默认为2
  useTabs: false, // 使用tab缩进,默认false
  semi: false, // 使用分号, 默认true
  /**
   * 行尾逗号,默认none,可选 none|es5|all
   * es5 包括es5中的数组、对象
   * all 包括函数对象等所有可选
   */
  trailingComma: 'es5',
  singleQuote: true, // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
  /**
   * 对象中的空格 默认true
   * true: { foo: bar }
   * false: {foo: bar}
   */
  bracketSpacing: true,
  /**
   * JSX标签闭合位置 默认false
   * false:
   * <div
   *  className=""
   *  style={{}}
   * >
   * true:
   * <div
   *  className=""
   * style={{}} >
   */
  jsxBracketSameLine: false,
  /**
   * 箭头函数参数括号 默认avoid 可选 avoid| always
   * avoid 能省略括号的时候就省略 例如x => x
   * always 总是有括号
   */
  arrowParens: 'avoid',
  vueIndentScriptAndStyle: false, // vue 文件 script 和 style 标签缩进,默认false
  endOfLine: 'lf', // 强制使用 unix 风格的换行符
}

插件介绍

  • eslint-config-airbnb-typescript: 该软件包提供 Airbnb 的 .eslintrc 作为可扩展的共享配置
  • eslint-plugin-react-native: 针对 ESLint 的 React Native 特定 linting 规则
  • eslint-plugin-prettier: 以 ESLint 插件的形式运行 prettier
  • eslint-config-prettier: 关闭所有不必要或可能与 prettier 的规则冲突的 ESLint 规则。一定要放到最后。

vscode eslint plugin config

"editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
},
"eslint.lintTask.enable": true,
"eslint.packageManager": "yarn",
"eslint.alwaysShowStatus": true,
"eslint.validate": [
  "javascript",
  "javascriptreact",
  "typescript",
  "typescriptreact",
  "vue",
  "html"
]

用 husky 和 lint-staged 构建超溜的代码检查工作流

$ yarn add -D husky
{
  "husky": {
    "hooks": {
      "pre-commit": "tsc --noEmit && lint-staged"
    }
  },
  "lint-staged": {
    "**/*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "git add ."
    ],
    "**/*.{md,json}": [
      "prettier --write",
      "git add ."
    ]
  }
}

Conventional Commits 约定式提交规范

Conventional Commits 是一种用于给提交信息增加人机可读含义的规范。约定式提交规范是一种基于消息的轻量级约定。它提供了一组用于创建清晰的提交历史的简单规则;这使得编写基于规范的自动化工具变得更容易。这个约定与 SemVer 相吻合,在提交信息中描述新特性、bug 修复和破坏性变更。

提交说明的结构如下所示:

<类型>([可选的作用域]): <描述>

[可选的正文]

[可选的脚注]

类型

  • build:: 影响构建系统或外部依赖关系的更改(示例范围:gulp、broccoli、NPM)。
  • chore:: 其他不修改srctest文件。
  • ci:: 更改持续集成文件和脚本(示例范围:Travis、Circle、BrowserStack、SauceLabs)。
  • docs:: 只是更改文档。
  • feat:: 类型为 feat 的提交表示在代码库中新增了一个功能(这和语义化版本中的 MINOR 相对应)。
  • fix::类型为 fix 的 提交表示在代码库中修复了一个 bug (这和语义化版本中的 PATCH 相对应)。
  • improvement:: 用于对当前实现进行改进而没有添加新功能或修复错误的提交。
  • perf:: 改进性能的代码更改。
  • refactor:: 代码重构,既不修复错误也不添加功能。
  • revert:: commit 回退。
  • style:: 不影响代码含义的变化(空白、格式化、缺少分号等)。
  • test:: 添加确实测试或更正现有的测试。

范围

可以为提交类型添加一个围在圆括号内的作用域,以为其提供额外的上下文信息。例如 feat(parser): adds ability to parse arrays.

BREAKING CHANGE

在可选的正文或脚注的起始位置带有 BREAKING CHANGE: 的提交,表示引入了破坏性 API 变更(这和语义化版本中的 MAJOR 相对应)。 破坏性变更可以是任意 类型 提交的一部分。

示例

包含了描述以及正文内有破坏性变更的提交说明

feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

包含了可选的 ! 字符以提醒注意破坏性变更的提交说明

chore!: drop Node 6 from testing matrix

BREAKING CHANGE: dropping Node 6 which hits end of life in April

不包含正文的提交说明

docs: correct spelling of CHANGELOG

包含作用域的提交说明

feat(lang): add polish language

为 fix 编写的提交说明,包含(可选的) issue 编号

fix: correct minor typos in code

see the issue for details on the typos fixed

closes issue #12

约定式提交规范

  1. 每个提交都必须使用类型字段前缀,它由一个名词组成,诸如featfix,其后接一个可选的作用域字段,以及一个必要的冒号(英文半角)和空格。
  2. 当一个提交为应用或类库实现了新特性时,必须使用feat类型。
  3. 当一个提交为应用修复 bug 时,必须使用fix类型。
  4. 作用域字段可以跟随在类型字段后面。作用有必须是一个描述某部分代码的名词,并用圆括号包围,例如:fix(parser):
  5. 描述字段必须紧接在类型/作用域前缀的空格之后。描述指的是对代码变更的简短总结,例如:fix:array parsing issue when multiplejspaces were contained in string
  6. 在简短描述之后,可以编写更长的提交正文,为代码变更提供额外的上下文信息。正文必须起始于描述字段结束的一个空行后。
  7. 在正文结束的一个空行之后,可以编写一行或或多行脚注。脚注必须包含关于提交的元信息,例如:关联的合并请求、Reviewer、破坏性变更、每条元信息一行。
  8. 破坏性变更必须标示在正文区域最开始处,或脚注区域中某一行的开始。一个破坏性变更必须包含大写的文本BREAKING CHANGE,后面紧跟冒号和空格。
  9. BREAKING CHANGE:之后必须提供描述,以描述对 API 的变更。例如:BREAKING CHANGE: environment variables now take precedence over config files
  10. 在提交说明中,可以使用featfix之外的类型。
  11. 工具的实现必须不区分大小写地解析构成约定式提交的信息单元,只有BREAKING CHANGE 必须是大写的。
  12. 可以在类型/作用域前缀之后,:之前,附加!字符,以进一步提醒注意破坏性变更。当有!前缀时,正文或脚注内必须包含BREAKING CHANGE: description

为什么使用约定式提交

  • 自动化生产 CHANGELOG。
  • 基于提交的类型,自动决定语义化的版本变更。
  • 向同事、公众与其他利益关系者传达变化的性质。
  • 触发构建和部署流程。
  • 让人们探索一个更加结构化的提交历史,以便降低对你的项目作出贡献的难度。

commitlint

commitlint检查您的提交消息是否符合conventional commit format

$ yarn add -D @commitlint/cli @commitlint/config-conventional @commitlint/prompt-cli
$ yarn add -D husky lint-staged
// package.json
{
  "scripts": {
    "commit": "commit"
  },
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }
}

standard-version

standard-version 是一款遵循语义化版本( semver)commit message 标准规范 的版本和 changlog 自动化工具。通常情况线下,我们会在 master 分支进行如下的版本发布操作:

  1. git pull origin master
  2. 根据 package.json 中的 version 更新版本号,更新 CHANGELOG
  3. git add .
  4. git commit
  5. git tag 打版本操作
  6. git push --follow-tags origin master && npm publish:push 版本 tag 和 master 分支到仓库并发布

其中 2,3,4,5 是 standard-version 工具会自动完成的工作,配合本地的 shell 脚本,则可以自动完成一系列版本发布的工作了。

安装 & 使用

$ yarn add -D standard-version
// package.json
{
  "scripts": {
    "release": "standard-version"
  }
}
  • First Release:yarn release --first-release
  • Cutting Release:yarn release
  • Release as a Pre-Release:yarn release --prerelease or yarn release --prerelease alpha
  • Release as a Target Type Imperatively (npm version-like):yarn release --release-as minor or yarn release --release-as 1.1.0,可以合并 --prerelease以此方便发布实验性特性
  • Prevent Git Hooks:yarn release --no-verify

资源参考