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

前端工程化实践 - 代码规范 & 提交规范 & 构建流程 & 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 :创建一个新的 package。查看文档

    # lerna create  [location]
    
    # 执行 lerna init 后,默认的 lerna workspace 是 packages/*。在 packages 文件夹中创建 package1
    lerna create package1
    # 在 packages/pwd1 目录下,生成 package2 依赖包
    lerna create package2 packages/pwd1
    
  3. lerna add [--scope ] [--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 匹配的目录中安装依赖

  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

你可能感兴趣的:(前端,react,native,代码规范,git,yarn)