前端工程化实践 - 代码规范 & 提交规范 & 构建流程 & Monorepo

  • 前言
  • 仓库策略
    • Multirepo
      • 什么是 Multirepo?
      • Multirepo 的优点
      • Multirepo 的缺点
    • Monorepo
      • 什么是 Monorepo?
      • Monorepo 的优点
      • Monorepo 的缺点和限制
  • 依赖管理
    • Yarn workspace - 高效管理工作区依赖
      • 简介
      • 如何使用
      • 所有依赖都需要提升到根仓库吗?
      • 基础命令
    • Lerna - 简化多包管理过程
      • Lerna 是什么?
      • Lerna 主要做什么?
      • Lerna 能解决了什么问题?
      • Lerna 的版本号管理策略
      • Lerna 的常用操作
      • 什么是 Glob?
        • Glob 的常用规则
    • Lerna + yarn workspace
  • 代码规范
    • ESLint - 确保代码格式规范且正确
      • ESLint 是什么?
      • ESLint 可以为项目带来哪些好处?
      • 如何使用 ESLint?
        • 安装
        • 初始化配置
        • 配置详解
        • 示例:启用 decorator
      • 如何触发 ESLint?
    • Prettier - 使用统一风格格式化代码
      • Prettier 是什么?
      • 如何使用 Prettier
        • 安装
        • 配置
      • 如何运行 Prettier?
      • 如何搭配 ESLint 使用?
  • 提交规范
    • Commitizen - 自动生成提交说明
      • 什么是约定式提交?
      • 约定式提交有什么要求?
        • 提交信息结构
        • 提交类型
        • 特殊脚注
      • 使用 Commitizen 生成提交说明
        • 安装 Commitizen
        • Commitizen 适配器
          • cz-conventional-changelog
          • cz-customizable
    • Commitlint - 校验提交信息
      • 安装和配置
      • 为什么提交信息中如果含有 Emoji,在提交时会提示检测不到 type, subject, body?
      • 为什么已经配置完成了,但 Commitlint 还是不生效?
    • Husky + Lint-staged - 提交前最后一道防火墙
      • 技术简介
      • 什么是 Git Hooks?
      • 如何使用 Husky?
      • 为什么需要 husky install?不可以直接在 .git/hooks 中直接添加 Hook 吗?
      • 格式化暂存区代码 - Lint-staged
        • 安装与配置
        • Git Hook 中的 $1 / HUSKY_GIT_PARAMS 是什么?
        • 在 Monorepo 中使用 Lint-staged
  • 任务流程
    • Lerna & NX
      • 配置 NX
        • taskRunnerOptions
        • Target Defaults
          • dependsOn
          • inputs & namedInputs
          • outputs
        • Project-Specific Configuration
  • React Native 项目改造
    • 项目结构
    • 提升依赖
    • 修改代码格式化配置
    • 修改 Metro 配置
    • 修改 npm 脚本
    • 适配 react-native-vector-icons

前言

本篇文章将从 仓库策略依赖管理代码规范提交规范任务流程 五个角度向读者介绍前端项目的一些工程化技术以及如何使你的 React Native 项目兼容 Monorepo 策略,同时你将了解到 lernayarn workspacehuskylint-stagedeslintprettiercommitlintcommitizenwebpack 等技术在项目中是如何工作的。

RN 示例项目:https://github.com/elton11220/MoogleCrafter

仓库策略

Multirepo

什么是 Multirepo?

在传统的单仓库管理模式中,所有的代码都被存储在一个大型代码仓库中。然而,在多仓库管理模式中,不同的代码库可以独立地进行版本控制和更改管理。这意味着每个代码库都可以拥有自己的开发流程和版本控制策略。

Multirepo 的优点

  • 更好的可扩展性
    多仓库管理使得团队可以更容易地扩展和修改项目的不同部分,而无需影响整个代码库。

  • 更好的可维护性
    在多仓库管理模式下,每个代码库都可以拥有自己的开发流程和版本控制策略,这使得团队可以更容易地维护项目的不同部分。

  • 更好的可测试性
    多仓库管理使得团队可以更容易地对项目的不同部分进行测试,而无需运行整个代码库。

Multirepo 的缺点

  • 管理复杂度增加
    多仓库管理模式需要更多的管理和协调工作,因为不同的代码库需要独立地进行版本控制和更改管理。

  • 集成问题
    在多仓库管理模式下,不同的代码库之间可能存在集成问题,这可能需要额外的努力来解决。

Monorepo

什么是 Monorepo?

Monorepo 是一种软件开发的方法,它将所有相关代码存储在一个单一的代码库中。这个代码库可以包含多个项目服务。使用 Monorepo 可以更轻松地管理代码和依赖项,减少重复代码,提高开发效率。

Monorepo 的优点

与单独的代码库相比,Monorepo 有许多潜在的优势:

  • 代码共享
    Monorepo 中,多个项目可以共享代码。这可以减少代码重复,提高代码质量,并使开发更加高效。开发人员可以更轻松地重用现有的代码,而无需复制和粘贴。

  • 更容易维护
    由于所有代码都在一个代码库中,因此更容易维护。开发人员可以更轻松地找到他们需要的代码,并且不需要在多个代码库之间切换。

  • 更容易协作
    Monorepo 使团队成员之间的协作更容易。由于所有代码都在一个代码库中,因此团队成员可以更轻松地共享代码并进行代码评审。这可以提高代码质量并促进知识共享。

  • 更容易管理依赖项
    Monorepo 中,多个项目可以共享同一组依赖项。这可以减少版本冲突,并使依赖项管理更加容易。开发人员可以更轻松地更新依赖项并确保所有项目都使用相同的版本。

Monorepo 的缺点和限制

  • 复杂性增加
    Monorepo 增加了代码库的复杂性,因为它需要管理多个项目和依赖项之间的交互。这会导致开发人员需要花费更多的时间来理解整个代码库以及如何在不同项目之间共享代码。

  • 构建时间增加
    Monorepo 中有多个项目,因此构建时间会变长,尤其是在代码库变得越来越大的情况下。这可能会导致开发流程变慢,因为开发人员需要等待更长时间来构建和测试他们的代码。

  • 依赖管理困难
    Monorepo 中,多个项目共享同一组依赖项。这可能会导致版本冲突和依赖项管理困难的问题。如果依赖项出现问题,可能需要花费更多的时间来解决它们。

  • 部署困难
    Monorepo 中,多个项目共享同一组代码。这可能会导致部署困难的问题,因为必须确保所有项目都能正确地部署并与其他项目一起工作。

  • 版本控制问题
    Monorepo 可能会导致版本控制问题,因为多个项目共享同一组代码。如果没有正确地管理版本控制,可能会导致代码库中的代码出现问题,从而影响开发流程和产品质量。

依赖管理

Yarn workspace - 高效管理工作区依赖

简介

yarn workspaceyarn 提供的一种管理 Monorepo 的方式。它允许将多个相关项目组织在一个代码库中,并且可以通过一个单独的 yarn.lock 文件来管理它们的依赖项。workspace 可以帮助简化 Monorepo 的管理,提高代码重用性和开发效率。

在一个 workspace 中,每个项目都是一个独立的子目录,并且可以有自己的 package.json 文件。这些子目录可以通过 yarn workspace 命令来管理,例如安装依赖、运行脚本等。

使用 yarn workspace 可以帮助开发人员更轻松地管理 Monorepo,减少代码重复,提高代码质量,并促进团队协作。

如何使用

  1. 在主仓库的 package.json 文件中添加 "private": true 属性。

这可以防止在发布代码时意外发布 workspace 中的项目。

  1. package.json 文件中添加一个 workspaces 属性,并将其设置为一个数组,其中包含 workspace 中的所有项目子目录的路径。例如:

    {"private": true,"workspaces": ["packages/*"]
    }
    
  2. 在每个项目子目录下,创建一个独立的 package.json 文件,并在其中定义项目的依赖项和脚本。

  3. 在代码库的根目录下运行 yarn install 命令,以安装所有 workspace 中的依赖项。yarn 会在根目录下生成一个单独的 yarn.lock 文件,用于管理 workspace 中所有项目的依赖项。

所有依赖都需要提升到根仓库吗?

当使用 yarn workspace 管理 Monorepo 时,如果多个项目之间共享依赖项,可能会出现版本冲突的问题。默认情况下,yarn 会将依赖项安装在 workspace 的根目录下,并将它们共享给所有项目,这可能会导致版本冲突和其他问题。

为了解决这个问题,可以使用 nohoist 配置选项,将指定的依赖项安装在每个项目的本地 node_modules 目录中,这样每个项目都有自己的依赖项,并且不会与其他项目发生冲突。

package.json 文件中,可以通过添加一个 nohoist 属性来配置 nohoist。例如:

{"private": true,"workspaces": {"packages": ["packages/*"],"nohoist": ["**/react","**/react-dom"],},
}

在上面的例子中,nohoist 配置指定了 reactreact-dom 两个依赖项不应该被提升到 workspace 的根目录下。这些依赖项将在每个项目的本地 node_modules 目录中安装和管理。

基础命令

使用 yarn workspace 命令来管理 workspace 中的项目,例如:

  • yarn workspace module-a add axios:向 module-a 项目添加 axios 依赖项。
  • yarn workspace module-a run build:在 module-a 项目中运行 build 脚本。
  • yarn add lint-staged -D -W: 在根仓库中添加 lint-staged 开发依赖。

-W: --ignore-workspace-root-check ,允许依赖被安装在workspace的根目录

Lerna - 简化多包管理过程

Lerna 是什么?

Lerna 是一个快速、现代的构建系统,用于管理和发布来自同一存储库的多个 JavaScript/TypeScript 包。它允许你将多个软件包存储在一个存储库中,并在这些软件包之间共享代码和依赖项。

Lerna 主要做什么?

Lerna 主要用于简化管理多个包的过程。它可以自动化许多常见的任务,例如:安装依赖项、构建、测试和发布。此外,Lerna 还提供了一些方便的命令,用于管理多个包之间的依赖关系。

Lerna 能解决了什么问题?

当你需要同时维护多个软件包时,使用 Lerna 可以显著提高开发效率。通过将所有软件包存储在一个存储库中,你可以更轻松地共享代码和依赖项,并更好地管理版本控制。此外,Lerna 还可以自动化许多常见的任务,从而减少了手动操作的时间和错误率。

Lerna 的版本号管理策略

Lerna 具有两种版本号管理策略:固定模式、独立模式。

① 固定模式(默认)
在固定模式下,所有 package 共享一个版本号。Lerna 会自动将所有 package 的版本号更新为相同的版本号。这种模式适用于想要将所有 package 一起发布的情况。

② 独立模式
在独立模式下,每个 package 都有自己的版本号。Lerna 会提示您为每个 package 输入新的版本号。这种模式适用于希望单独发布每个 package 的情况。每次发布时,你都会收到针对每个已更改包的提示,以指定它是补丁、次要、主要还是自定义更改。

设置方法:

  • Lerna 的配置文件中设置默认的版本号管理模式。

    {"version": "independent"
    }
    
  • 此外,可以在运行初始化 Lerna 时使用 --independent 标志来强制使用独立模式。
    lerna init --independent
    

Lerna 的常用操作

  1. lerna init:初始化一个新的 Lerna 项目。查看文档

    --independent 使用独立模式管理版本号
    --exact 默认情况下,lerna init 在添加或更新本地版本的 lerna 时将在 devDependencies 中添加 Lerna,使后续使用时保持相似的行为。

  2. lerna create <name>:创建一个新的 package。查看文档

    # lerna create <name> [location]# 执行 lerna init 后,默认的 lerna workspace 是 packages/*。在 packages 文件夹中创建 package1
    lerna create package1
    # 在 packages/pwd1 目录下,生成 package2 依赖包
    lerna create package2 packages/pwd1
    
  3. lerna add <package> [--scope <glob>] [--dev]:将一个包添加到 package 的依赖项中。查看文档

    # 如果添加本地包,lerna 会自动 link 到本地包
    lerna add package
    lerna add package --dev # 作为 devDependencies
    lerna add package --peer    # 作为 peerDependencies
    lerna add package[@version] --exact  # 安装准确版本的依赖lerna add module-1 --scope=module-2       # 将 module-1 添加为 module-2 的依赖
    lerna add package packages/abcd-*   # 给前缀为 abcd 的包,安装依赖
    

    --scope <glob> 在与给定的 Glob 匹配的目录中安装依赖

  4. lerna bootstrap:安装所有 package 的依赖项,并将它们链接在一起。查看文档

    默认情况下,Lerna 将尝试重用你选择的包管理器的 workspace 配置。你可以使用 packages 属性指定 Packages 的位置,它会告诉 Lerna 在哪里寻找 package.json 文件。

    // lerna.json
    {"packages": ["packages/*"]
    }
    

    同时,你可以通过 lerna.jsonuseWorkspaces 属性决定是否使用 yarn workspace 功能。如果 useWorkspaces: truelerna 将会继承 package.json -> workspaces 的配置。

    // lerna.json
    {"useWorkspaces": true,"npmClient": "yarn"
    }
    
  5. lerna run <script> [--scope <glob>]:在 package 中运行一个 npm script。查看文档

    # 这个操作会执行所有包的 build 脚本 (packages.json -> scripts -> build)
    # 没有 build 脚本的包将不会被执行
    lerna run build# 你也可以选择仅执行 module-1 中的 build 脚本
    lerna run build --scope=module-1
    
  6. lerna exec <command> [--scope <glob>]:在 package 中运行一个 shell 命令。查看文档

    lerna exec -- <command> [..args] # 在所有包中运行命令
    lerna exec -- rm -rf ./node_modules
    lerna exec -- protractor conf.js
    
  7. lerna changed:列出由上次发布以来发生更改的 package。查看文档

    lerna changed
    # package-1
    # package-2
    
  8. lerna version:更新 package 的版本号,并将它们提交到 Git。查看文档

    运行时,此命令执行以下操作:
    ① 检查 git 工作区是否干净,如果有未提交的修改,会提示用户先提交修改或者 stash 修改。
    ② 检查当前分支是否为 git 主分支(通常是 mastermain 分支),如果不是,会提示用户切换到主分支。
    ③ 提示用户输入新版本号,或者根据用户指定的版本升级方式(如 majorminorpatch 等)自动生成新版本号。
    ④ 对每个包进行版本升级和打标签,并将修改提交到 git 仓库。
    ⑤ 根据用户指定的 git remotetag 格式,将修改推送到远程 git 仓库。

  9. lerna publish:发布所有更新的 package。查看文档

    运行时,此命令执行以下操作:
    ① 检查 git 工作区是否干净,如果有未提交的修改,会提示用户先提交修改或者 stash 修改。
    ② 检查当前分支是否为 git 主分支(通常是 mastermain 分支),如果不是,会提示用户切换到主分支。
    ③ 提示用户输入新版本号,或者根据用户指定的版本升级方式(如 majorminorpatch 等)自动生成新版本号。(参考 lerna version
    ④ 对每个包进行版本升级和打标签,并将修改提交到 git 仓库。
    ⑤ 为每个包生成一个新的版本号,并将新版本号写入到各个包的 package.json 文件中。
    ⑥ 将每个包发布到指定的 npm registry 上,并将发布日志写入到各个包的 CHANGELOG.md 文件中。

    该命令默认只会发布被修改过的包,如果需要发布所有包,可以使用 --force-publish 选项。
    此外,lerna 不会发布那些被标记为私有的包("private":true)。这与 npm publish 的行为一致。

什么是 Glob?

glob 是一种通配符模式,用于匹配文件路径名。它通常用于文件处理操作,例如列出一个目录中所有符合特定模式的文件名。在 Unix类 Unix 操作系统中,glob 模式通常使用 shell 命令来执行,例如 ls *.txt 可以列出所有扩展名为 .txt 的文件。在编程语言中,也通常有相应的 glob 函数或类库来实现这种功能。

测试你的 Glob:https://kthompson.github.io/glob/

Glob 的常用规则

  • ?:匹配单个字符
  • *:匹配任何字符
  • /:路径分隔符
  • **:匹配所有文件和任意层级的目录。如:/src/**.js 将匹配 src 目录内的所有 js 文件(包括子目录中的文件)
  • {a, b}:花括号内的表达式被扩展为多种模式,例如**/*.{b,c} 将扩展为 **/*.b**/*.c。最终结果是检查两种模式的集合。
  • ?(a | b):匹配零次或一次出现的给定模式。
  • *(a | b):匹配零次或多次出现的给定模式。
  • +(a | b):匹配一次或多次出现的给定模式。
  • @(a | b):匹配给定模式之一。
  • !(a | b):匹配除给定模式之一以外的任何内容。

Lerna + yarn workspace

Lernayarn workspace 配合使用时,可以更好地管理具有多个包的项目。Lerna 可以轻松地管理和发布包,而 yarn workspace 可以帮助你在 Monorepo 中管理依赖项。

代码规范

ESLint - 确保代码格式规范且正确

ESLint 是什么?

ESLint 是一个用于检查 JavaScript 代码错误和风格的工具。它可以帮助开发人员在编写代码时遵循一致的编码规范,并提高代码质量。ESLint 可以通过配置文件来指定要检查的文件和规则,并支持第三方插件和解析器。

ESLint 可以为项目带来哪些好处?

  • 提高代码质量:ESLint 可以检查代码中的错误和风格问题,帮助开发人员遵循一致的编码规范,从而提高代码质量。

  • 减少错误:ESLint 可以检查代码中的错误,例如未定义的变量、未使用的变量等,帮助开发人员及时发现和修复错误。

  • 提高代码的可维护性:ESLint 可以检查代码中的风格问题,例如缩进、空格等,帮助开发人员编写易于阅读和维护的代码。

  • 支持扩展:ESLint 支持第三方插件和解析器,可以根据项目的需要进行扩展。

如何使用 ESLint?

安装

局部安装:npm i eslint --save-dev(建议)
全局安装:npm i eslint -g

初始化配置

通过 eslint --init ,cli 会根据你的选项生成对应的配置文件。你可以选择配置文件的格式,同时可以选择一些你需要的规则。

你也可以选择在根目录下手动创建 .eslintrc.js 文件,eslint 支持多种格式的配置文件,你可以创建其中一种。

按优先级排序:.eslintrc.js > .eslintrc.yaml > .eslintrc.yml > .eslintrc.json > .eslintrc > package.json 中的 eslint 配置

配置详解

我们看一下 .eslintrc.js 中都有哪些配置选项:

  • globals : Record<string, boolean | “readonly” | “writable” | “off”>

    ESLint 的一些核心规则依赖于对代码在运行时可用的全局变量的了解。由于这些在不同环境之间可能会有很大差异,并且会在运行时进行修改,因此 ESLint 不会假设执行环境中存在哪些全局变量。如 jQuery 提供的 $ 符号。在这种情况下,ESLint 会提示错误,需要向 ESLint 规则中添加需要识别的变量。

    对于这种情况,可以在配置文件中或通过在源代码中使用配置注释来定义全局变量。

    {"globals": {"$": "readonly"}
    }
    
    • readonly / false 只读
    • writable / true 可写
    • off 禁用
  • env : Record<string, boolean>

    为了避免配置每一个全局变量带来的麻烦,ESLint 具有全局变量集合的预设,如果我们要使用 jQuery 提供的全局变量,只要需要在 env 配置中添加 "jquery": true 就可以了。

    {"env": {"jquery": true}
    }
    

    查看可用的 env:https://eslint.org/docs/latest/use/configure/language-options#specifying-environments

  • root : boolean

    在 ESLint 中,可以通过 .eslintrc.* 或 package.json 文件来指定配置。ESLint 会在要检查的文件的目录中自动查找这些配置文件,并且会一直向上查找,直到到达文件系统的根目录 (/)、当前用户的主目录 (~/)。

    当配置文件中 root: true 被指定时,ESLint 不会继续向上级目录查找文件,而是让项目内需要被检测的文件都走我们的项目根目录下的这个配置。

    {"root": true
    }
    
  • rules : Record<string, 0 | 1 | 2 | “off” | “warn” | “error”>

    ESLint 内置了大量规则,rule 用于验证代码是否满足特定期望,以及如果不满足该期望该怎么办。

    检验规则具有 3 个报错等级:
    ① “off” 或 0:关闭规则
    ② “warn” 或 1:开启规则,warn 级别的错误 (不会导致程序退出)
    ③ “error” 或 2:开启规则,error 级别的错误 (当被触发的时候,程序会退出)

    {"rules": {"no-console": 2}
    }
    

    规则的值可以为字符串,也可以是数组。当规则的值是数组时,数组的第一个值是对规则的报错等级,后面的值就是这个规则的参数。

    {"rules": {"no-confusing-arrow": ["error",{"onlyOneSimpleParam": true}]
    }
    
  • extends : string[]

    extends 是一种配置规则的方式,可以通过继承一个或多个已有的配置来扩展自己的配置。这意味着可以在自己的配置文件中使用 extends 属性来继承其他配置文件中的规则。这样可以避免重复定义相同的规则,同时还可以通过继承其他配置来快速启用一些通用的规则。

    extends 可以分为以下几种类型:
    eslint: 开头的:eslint 官方的扩展。如:eslint:recommended(推荐规范)和 eslint:all(所有规范)
    plugin: / eslint-plugin- 开头的:通过插件共享的规则。如:eslint-plugin-react,可以使用其中的 plugin:react/recommended 规则集
    eslint-config- 开头的:第三方发布到 npm 上的规则。如:eslint-config-standard
    @ 开头的:和 eslint-config- 一样,但其 npm 包拥有 scope。如:@vue/eslint-config-prettier
    ⑤ 路径:ESLint 可以解析相对于使用它的配置文件的基本配置文件的相对路径或绝对路径。如:./node_modules/coding-standard/.eslintrc-es6

    {"extends": ["eslint:recommended","plugin:vue/essential","eslint-config-standard","@vue/prettier","./node_modules/coding-standard/.eslintrc-es6"]
    }
    
  • parser : string

    parser 属性用于指定 JavaScript 代码的解析器。由于不同的 JavaScript 版本和扩展语言有不同的语法和特性,因此需要使用不同的解析器来解析代码。

    ESLint 支持多种解析器,包括默认的 Espree 解析器和其他第三方解析器。通过配置 parser 属性,可以指定要使用的解析器,以便 ESLint 可以正确地解析代码并检查其中的语法错误和其他问题。

    默认的解析器只支持已经形成 ES 标准的语法特性,对于处于实验阶段以及非标准的需要使用 Babel 转换的语法,需要指定由 Babel 提供的 @babel/eslint-parser。使用这个解释器的前提是你的项目使用了 babel

    {// 使用前需先安装parser: '@babel/eslint-parser',parserOptions: {// @babel/eslint-parser相关的选项}
    }
    

    如果你的项目使用了 ts,想使用 @typescript-eslint/eslint-plugin 这个插件提供的规则来校验你的代码,此时就需要使用 @typescript-eslint/parser 来做解释器了。

    {"parser": "@typescript-eslint/parser","extends": ["plugin:@typescript-eslint/recommended"],"plugins": ["@typescript-eslint"],"parserOptions": {// @typescript-eslint/parser的选项},
    }
    
  • parserOptions : Record<string, any>

    parserOptions 是一个可选的配置项,它用于配置解析器的选项。通过这个属性,可以指定要解析的语言选项,以便 ESLint 可以正确地解析代码并检查其中的语法错误和其他问题。parserOptions 可以包含以下选项:

    • ecmaVersion:指定要解析的 ECMAScript 版本。如:"ecmaVersion": 2018 表示要解析 es2018 版本的代码。
    • sourceType:指定要解析的代码是模块代码还是脚本代码。例如,"sourceType": "module" 表示要解析模块代码。
    • ecmaFeatures:指定要解析的 ECMAScript 特性。例如,"ecmaFeatures": { "jsx": true } 表示要解析 JSX 语法的代码。
  • plugins : string[]

    插件是用来扩展 ESLint 功能的工具,可以帮助检查更多的代码类型和问题。虽然 ESLint 提供了许多规则供选择,但是随着 JavaScript 框架和语法的发展,这些规则可能无法检查到一些特定问题。

    例如,如果我们使用 Vue 的 Template 或 React 的 JSX 语法编写代码,ESLint 就无法检测到其中的问题。因此,可以通过使用插件来扩展 ESLint 的功能,以便检查这些特定问题。

    要使用 ESLint 插件,需要先安装插件。可以通过 npm 安装插件,例如 npm install eslint-plugin-react。安装完成后,在配置文件中通过 plugins 属性来启用插件。例如,要启用名为 "eslint-plugin-react" 的插件,可以在配置文件中添加以下内容:

    {"plugins": ["react"],"rules": {// 在这里配置规则}
    }
    

    在这个示例中,我们启用了名为 "eslint-plugin-react" 的插件,并在配置文件中配置了该插件提供的规则。需要注意的是,不同的插件可能提供不同的规则和功能。可以在插件的文档中查看其提供的规则和功能,并按需启用。

    ESLint 的插件有两种配置方法:
    ① plugin + rule 开启部分规则:
    使用 plugins 字段后,只是引入了插件,并没有使用具体规则。此时的校验是没有效果的,需要在rules 中显式开启你需要使用的规则。

    {"plugins": ["prettier"],"rules": {"prettier/prettier": "error"}
    }
    

    ② 使用 extends 引入插件并配置默认规则:

    {extends: ['plugin:prettier/recommended'],
    }
    

示例:启用 decorator

要使 ESLint 支持 decorator 特性,需要将 parser 设为如 @babel/eslint-parser 这种支持 experimental语法 的解析器

npm i @babel/eslint-parser @babel/eslint-plugin --save-dev
{"parser": "@babel/eslint-parser","plugins": ["@babel/eslint-plugin"]
}

同时,应该安装decorator对应的babel插件

npm i @babel/plugin-proposal-decorator --save-dev

babel 配置中启用该插件:

{"plugins": [["@babel/plugin-proposal-decorators",{"legacy": true}]]
}

配置jsconfig.json

{"complierOptions": {"experimentalDecorators": true}
}

如何触发 ESLint?

  1. 命令行方式:在命令行中运行 eslint 命令,并指定要检查的文件或目录。

    ① 校验单个文件:

    eslint a.js
    

    ② 校验一个目录:

    eslint src
    

    ③ 校验非 js 格式的文件:
    默认情况下,ESLint 仅支持校验 js 格式的文件。如果需要校验其他类型的文件,需要配置相关的 plugin。同时,在运行时指定 --ext 参数来指定扩展名。

    eslint --ext .vue,.jsx src
    

    ④ 根据配置的规则进行自动修复

    eslint src --fix
    

    ⑤ 在 package.json 配置 npm 脚本

    {"scripts": {"lint": "eslint src --fix}
    }
    
  2. 集成到编辑器中:通过安装 ESLint 插件,将 ESLint 集成到编辑器中。编辑器会在保存文件时自动触发 ESLint 检查,并在编辑器中显示检查结果。

  3. 集成到构建工具中:通过在构建工具(如 Webpack、Gulp、Grunt 等)中配置 ESLint 插件,将 ESLint 集成到构建流程中。构建工具会在打包时自动触发 ESLint 检查,并将检查结果输出到控制台或日志文件中。

  4. 集成到代码托管平台中:通过在代码托管平台(如 GitHub、GitLab 等)中配置 ESLint 插件,将 ESLint 集成到代码提交流程中。代码托管平台会在提交代码时自动触发 ESLint 检查,并根据检查结果决定是否允许代码合并。

Prettier - 使用统一风格格式化代码

Prettier 是什么?

Prettier 是一个代码格式化工具,它可以自动化地格式化你的代码,使其更易于阅读和维护。Prettier 支持多种编程语言,包括 JavaScript、TypeScript、CSS、HTML、JSON 等。你可以在你的项目中集成 Prettier,以便在提交代码之前自动格式化你的代码。

ESLint不同,Prettier 并不关心代码的语义和逻辑,它只关心代码的外观。当你在编辑器中保存你的代码时,Prettier 可以自动格式化你的代码,使其符合预定义的格式规则。

如何使用 Prettier

安装

npm install prettier --save-dev

配置

首先,在根目录创建 .prettierrc.json 文件(配置 Prettier 并让编辑器知道你正在用 Prettier

可以选择创建一个 .prettierignorePrettier 知道哪些文件不需要被格式化

Prettier 的配置项比较少,可以查看官方文档:https://www.prettier.cn/docs/options.html#parser

例:

{"semi": false,"singleQuote": true,"arrowParens": "always","htmlWhitespaceSensitivity": "ignore","trailingComma": "all"
}

如何运行 Prettier?

当你集成了 Prettier 到你的项目中,你可以使用以下方法来执行 Prettier。

  1. 使用编辑器插件:许多编辑器都有 Prettier 插件可用,你可以直接在编辑器中使用快捷键或右键菜单来执行 Prettier。常见的编辑器插件包括 VS Code、Sublime Text、Atom 等。

  2. 使用命令行工具:你可以在终端中使用命令行工具来执行 Prettier。在你的项目根目录下运行以下命令即可格式化整个项目:

npx prettier --write .

这将使用 npx 运行 Prettier,并使用 --write 参数来直接修改文件。. 表示格式化整个项目。

  1. 集成到构建工具:你可以将 Prettier 集成到你的构建工具中,如 webpack、gulp 等。这样,每次构建项目时都会自动执行 Prettier。

无论你选择哪种方法,Prettier 都会自动格式化你的代码,并将其保存到文件中。

如何搭配 ESLint 使用?

ESLint 和 Prettier 是两个不同的工具,它们的作用也不同:

  • ESLint 是一个静态代码分析工具,用于检查代码中的语法和风格错误。它可以根据预定义的规则来检查代码,也可以根据自定义规则来检查代码。
  • Prettier 是一个代码格式化工具,用于自动格式化代码。它可以根据预定义的规则来格式化代码,也可以根据自定义规则来格式化代码。

在使用 ESLintPrettier 进行代码检查和格式化时,可能会出现某些规则冲突的情况,这会导致 ESLintPrettier 之间的集成出现问题。

为了解决这个问题,可以使用 eslint-config-prettier。这个包可以关闭 ESLint 中与 Prettier 冲突的规则,确保 ESLintPrettier 之间的无缝集成。

  1. 安装:npm install --save-dev eslint-config-prettier
  2. .eslintrc.json 中添加 "prettier"extends 数组中,例如:
{"extends": ["eslint:recommended","prettier"]
}

上面介绍的工具,仅将部分 ESLint 规则禁用了。那么如何将两者结合起来使用呢?

这时可以使用一个插件 eslint-plugin-prettier。这个插件用于将 Prettier 的规则作为 ESLint 规则来运行,以便在运行 ESLint 时就可以检测到代码格式问题。它会将 Prettier 的规则作为 ESLint 规则来运行,这样就可以在运行 ESLint 时自动检测代码格式问题。

要使用 eslint-plugin-prettier,需要执行以下步骤:

  1. 安装 eslint-plugin-prettierprettier

    npm install --save-dev eslint-plugin-prettier prettier
    
  2. .eslintrc 文件中添加 prettier 插件:

    {"plugins": ["prettier"],"rules": {"prettier/prettier": "error"}
    }
    
  3. 上面 ESLint 的相关章节介绍过,你也可以使用插件推荐的配置:

    {"extends": ["plugin:prettier/recommended"]
    }
    

提交规范

Commitizen - 自动生成提交说明

什么是约定式提交?

约定式提交是一种标准化的提交消息格式,旨在提高代码库的可读性、可维护性和自动化程度。它规定了一些特定的前缀和格式,用于描述提交的类型、范围、主题和其他元数据。这些提交消息可以被用于生成CHANGELOG、自动化版本号控制、代码审查等自动化流程。

Conventional-commits 详情:https://www.conventionalcommits.org/zh-hans/v1.0.0/

约定式提交有什么要求?

提交信息结构

为了使提交格式清晰、便于阅读,对提交信息做出了一定的约束。Angular 约定包括以下部分:

  • 标题(header):用一行简短的描述来总结更改内容,并使用特殊关键字指定更改类型和影响范围。
  • 正文(body):提供更详细的更改描述,包括更改原因、影响和解决方案等信息。
  • 页脚(footer):提供一些附加信息,如相关链接、关联的BUG编号等。

其中,标题部分又包括:

  • 类型(type):描述提交的类型,如feat、fix、docs、style、refactor、test、chore等。
  • 范围(scope):描述本次提交影响的范围,如路由、模型、控制器等。
  • 主题(subject):简要描述本次提交的内容,通常不超过50个字符。

总结一下,提交信息的结构大致可以描述为:

<类型>[可选 范围]: <描述>
​
[可选 正文]
​
[可选 脚注]

提交类型

描述
feat 新功能
fix 修复 Bug
docs 文档更变
style 代码格式(不影响代码运行的变动)
refactor 重构(既不增加 feature,也不修复 Bug)
perf 性能优化
test 增加测试
chore 构建过程或辅助工具的变动
revert 回退
build 打包

特殊脚注

  • 不兼容变更
    软件或系统中的变化,可能会导致已有的代码、API或行为无法向后兼容。这种变化可能会导致现有的代码或系统出现错误或无法正常工作,需要进行修改或更新,则 FooterBREAKING CHANGE 开头,后面是对变动的描述、以及变动的理由和迁移方法。

    例:

    feat: add new API endpoint for user authenticationBREAKING CHANGE: the existing /api/auth endpoint has been removed in favor of the new /api/login endpoint. This change requires all clients to update their authentication code to use the new endpoint.
    
  • 关闭issue
    在提交消息中包含 Closes #<issue number>Fixes #<issue number> 即可关闭对应的 issue。

    例:

    feat(Shared): add new featureCloses #123
    
  • 提及 pull request
    在提交消息中包含 Ref #<pull request number> 即可提到对应的 pull request。

    例:

    fix: fix bug in login formRef #456
    

使用 Commitizen 生成提交说明

安装 Commitizen

可以理解为一个命令行工具,当使用 Commitizen 提交时,系统会提示你在提交时填写必需的提交字段(如:type、scope、subject、body、footer)。

安装 Commitizen

npm install -g commitizen

如果你想指定版本,可以选择将它安装为 devDependency,这样有助于在不同开发者间保持相同的 Commitizen 行为。

Commitizen 适配器

Commitizen adapter 提供了一些预定义的提交类型和格式,并通过用户友好的交互式命令行界面来引导你创建符合规范的提交信息。

cz-conventional-changelog

如果需要在项目中使用 commitizen 生成符合 Angular 规范的提交说明,可以选择 cz-conventional-changelog 适配器:

commitizen init cz-conventional-changelog --save-dev --save-exact

请注意,如果已经有其他适配器了会报错。可以用 --force 参数。

初始化命令做了以下事情:

  1. 在项目中安装 cz-conventional-changelog 适配器依赖
  2. 将适配器依赖保存到 package.jsondevDependencies
  3. package.json 中新增 config.commitizen 字段信息,主要用于配置cz工具的适配器路径:
{"devDependencies": {"cz-conventional-changelog": "^x.x.x"},"config": {"commitizen": {"path": "node_modules/cz-conventional-changelog"}}
}

你可以在 npm 脚本中添加一个脚本运行 Commitizen:

{"scripts": {"commit": "git cz"}
}
cz-customizable

cz-customizable 是一个 commitizen adapter,它允许用户自定义提交信息的格式和内容。与 cz-conventional-changelog 不同,cz-customizable 没有预定义的提交类型和格式,而是通过配置文件来定义。用户可以根据自己的需求定义提交信息的各个部分,例如类型、作用域、描述等。

安装:

npm install cz-customizable --save-dev

添加配置:

{"config": {"commitizen": {"path": "node_modules/cz-customizable"}}
}

在项目根目录创建 .cz-config.js,这里附上我项目中的配置文件:

module.exports = {types: [{value: ":sparkles: feat",name: "✨ feat:    新功能",},{value: ":bug: fix",name: "												

前端工程化实践 - 代码规范 提交规范 构建流程 Monorepo(附 React Native 案例)相关推荐

  1. 前端工程化实践:从开发到构建测试部署——由此及彼

    前端工程化实践 前端工程化实践 什么叫前端工程化 从实践方面来说 从理论角度来讲 前端工程化的意义: 1.规范化(从源头处约束到优雅-聚沙成塔) 1. 制定各项开发规范,让工作有章可循 2. 针对于版 ...

  2. 前端工程化实践总结 | QQ音乐商业化Web团队

    蓝字关注,回复"加群"加入前端技术群 与大家一起成长 | 导语本文主要介绍在前端工程化的一些探索和实践,结合移动端的基础库重构和UI组件库开发这两个项目详细介绍工程化方案 . 随着 ...

  3. app端前端框架对比 - Mui与ionic、Cordova 、Weex、React Native对比

    1.1.1.介绍: mui是最接近原生App体验的前端框架. 极小:100k的js文件,60k的css文件.原生编写,不依赖任何三方框架 极强:xcode和Android studio里所有原生控件都 ...

  4. 从阿里前端工程化中台实践,看中台建设的舍与得

    作者|朱华军(阿大) 出品|InfoQ&阿里巴巴新零售淘系技术部 导读:随着前端技术不断从 Web 延伸至各种"端",大前端的概念早已成为业内共识.伴随着大前端的发展,与之 ...

  5. 前端工程化详解——理解与实践前端工程化

    前言: 前端工程化一直是一个老生常谈的问题,不管是面试还是我们在公司做基建都会经常提到前端工程化,那么为什么经常会说到前端工程化,并没有听过后端工程化.Java工程化或者Python工程化呢?我们理解 ...

  6. 分享狼叔关于《大前端工程化的实践与思考》

    前言 本文来自极客前端训练营的主题公开课,非原创. 作者简介 桑世龙(狼叔),阿里巴巴前端技术专家,nodejs<狼书>作者. 快速发展的大背景 前端发展太快了,在2004年之前,大概只要 ...

  7. 前端工程化——构建工具选型

    一.什么是前端工程化 前端工程化是依据业务特点,将前端开发的规范.流程.技术.工具.经验等形成规范并建立成一种标准的体系. 二.为什么要前端工程化 实现前端工程化的目的简单来说就是通过流程规范.自动化 ...

  8. 前端类名优秀命名例子_这是一篇需要花费你15分钟阅读的干货!浅谈前端工程化...

    01前端工程化的背景 随着业务的扩展.业务需求更加复杂.项目团队的壮大以及项目的增多等.制定一套适用于团队的前端工程化方案很有必要. 02前端工程化是什么 前端工程化是一个很广泛的话题.涉及的技术与解 ...

  9. 前端架构,前端工程化

    前端架构: 1.前端工程化 web应用复杂度的增加,特别是单页面应用的风靡.组件化,工程化,自动化成了前端发展的趋势.或者说一线的互联网公司就是这么做的. 每个前端团队都在打造自己的前端开发体系,这通 ...

最新文章

  1. Pandas 基础 (1)—— Series
  2. 【NLP】Transformers 源码阅读和实践
  3. unknow Unknown type name 'NSString'
  4. Spring 整合 Mybatis
  5. python计算N维数据的笛卡尔积
  6. 使用particles.js实现网页背景粒子特效
  7. ubuntu 下安装和配置selenium
  8. 单位转换及格式化显示
  9. 计算机操作系统(第四版)课后习题答案西电版
  10. 屏蔽网站广告的Chrome谷歌浏览器插件推荐和下载地址
  11. 教务管理系统乱码服务器不可,青果教务管理系统Post登录(二)
  12. 不是吧,还有人不会做国庆头像小程序(可开通流量主,赚零花钱)
  13. python是猿辅导还是学而思_综合分析:猿辅导和学而思对比选哪个好,我的亲身感受...
  14. 用 Python 分析《红楼梦》(2)
  15. CNCF 新掌舵人首次亮相中国,KubeCon 2020 云原生峰会网上行
  16. **修炼一名程序员的职业水准(林庆忠__署名原创)**
  17. java编程细节总结(一):等于号的作用
  18. 按键精灵 网页操作插件
  19. c++ vector 先进先出_STL从0开始
  20. 旋转体表面积公式推导及证明错误

热门文章

  1. 2022-2027年中国电气化铁路牵引供电系统变压器行业发展前景及投资战略咨询报告
  2. Python 文档,给自己的程序写文档
  3. 转战C#---day7
  4. 高速数据采集专家--青翼8通道125MSPS 16位AD采集FMC子卡
  5. JavaWeb笔记之SSH(Struts2框架)
  6. Android自定义电池电量显示组件(kotlin,java)
  7. 树莓派4B 64位系统 安装python3.7+tensorflow 2.3.1
  8. 微信小程序开发 案例二 调查问卷
  9. (转载)Android花样Text,设置TextView的字体、颜色、超链接等
  10. STL、PLY、OBJ格式分析