Posted in

Monorepo 与 pnpm:前端项目管理的完美搭档_AI阅读总结 — 包阅AI

包阅导读总结

1. 关键词:Monorepo、pnpm、前端项目管理、依赖管理、权限管理

2. 总结:本文介绍了 pnpm 作为高性能的 npm 工具,其节省磁盘空间和提高安装效率的特点,还阐述了 Monorepo 模式及与包管理工具的关系,包括其优势和可能面临的问题,同时给出了解决 Monorepo 权限管理问题的方法,还讲解了 pnpm 的安装、使用及在 Monorepo 架构中的应用和常用命令。

3. 主要内容:

– pnpm 简介

– 是高性能的 npm,通过硬链接和符号链接节省磁盘空间和提高安装效率

– 创建非扁平的 node_modules 目录结构

– Monorepo 简介

– 是单一代码仓库的项目开发与管理策略

– 与包管理工具关系:为其提供依赖安装与管理支持,实现依赖共享

– 优势:回归单体管理优势,现代工具支持使其更可行,便于版本控制等

– 缺点:可能变得庞大复杂,存在权限管理问题

– 权限管理问题解决方法:使用代码所有权文件、利用 CI/CD 流程、分支策略、使用 Git 钩子、利用子模块、第三方工具和扩展

– 组件库项目选用 Monorepo 模式原因

– 可清晰划分模块,增强复用灵活性,减轻模块产物体积

– pnpm 的安装和使用

– 全局安装:`npm i pnpm -g`

– 查看版本:`pnpm -v`

– pnpm 在 monorepo 架构中的使用

– 初始化生成 `package.json`

– 配置工作空间

– 安装项目依赖

– 暴露公用方法

– 启动页面

– 模块内部指定依赖踩坑总结

– pnpm 常用命令

– 安装、更新、移除依赖等

– 在 workspace 模式下通过 `–filter` 选项操作子模块

思维导图:

文章地址:https://mp.weixin.qq.com/s/XhEDQw7QyUal3PSVB5I3Xg

文章来源:mp.weixin.qq.com

作者:嘴平伊之豬

发布时间:2024/7/26 7:11

语言:中文

总字数:3436字

预计阅读时间:14分钟

评分:91分

标签:前端开发,包管理工具,Monorepo,pnpm,依赖管理


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

一、什么是pnpm

pnpm又称 performant npm,翻译过来就是高性能的npm。

1.节省磁盘空间提高安装效率

pnpm通过使用硬链接符号链接(又称软链接)的方式来避免重复安装以及提高安装效率。硬链接:和原文件共用一个磁盘地址,相当于别名的作用,如果更改其中一个内容,另一个也会跟着改变符号链接(软链接):是一个新的文件,指向原文件路径地址,类似于快捷方式官网原话:

当使用 npm 时,如果你有 100 个项目,并且所有项目都有一个相同的依赖包,那么,你在硬盘上就需要保存 100 份该相同依赖包的副本。然而,如果是使用 pnpm,依赖包将被存放在一个统一的位置,因此:1.如果你对同一依赖包需要使用不同的版本,则仅有 版本之间不同的文件会被存储起来。例如,如果某个依赖包包含 100 个文件,其发布了一个新 版本,并且新版本中只有一个文件有修改,则pnpm update 只需要添加一个新文件到存储中,而不会因为一个文件的修改而保存依赖包的所有文件。2.所有文件都保存在硬盘上的统一的位置。当安装软件包时,其包含的所有文件都会硬链接自此位置,而不会占用额外的硬盘空间。这让你可以在项目之间方便地共享相同版本的依赖包。最终结果就是以项目和依赖包的比例来看,你节省了大量的硬盘空间,并且安装速度也大大提高了!

2.创建非扁平的node_modules目录结构
image.png
3.Monorepo 简介及其与包管理工具(npm、yarn、pnpm)之间的关系
Monorepo模式:

Monorepo 是一种项目开发与管理的策略模式,它代表”单一代码仓库”(Monolithic Repository)。在 Monorepo 模式中,所有相关的项目和组件都被存储在一个统一的代码仓库中,而不是分散在多个独立的代码仓库中,这些项目之间还可能会有依赖关系。

包管理工具:

npm、yarn、pnpm 等是用来管理项目依赖、发布包、安装依赖的工具,它们都提供了对工作区(workspace)的支持,允许在单个代码库中管理多个项目或包。这种工作区支持在单个代码库中同时开发、测试和管理多个相关的项目,而无需使用多个独立的代码仓库。

关系:

这些包管理工具与 monorepo 的关系在于它们可以为 monorepo 提供依赖安装与依赖管理的支持,借助自身对 workspace 的支持,允许在 monorepo 中的不同子项目之间共享依赖项,并提供一种管理这些共享依赖项的方式,这可以简化依赖项管理和构建过程,并提高开发效率。

4.Monorepo (单仓多模块)开发模式
  • 回归单体管理:Monorepo 是一种试图回归单体管理优势的方法,但保留了多仓库开发的某些优点。它允许在一个代码库中管理多个项目、组件或服务,提供更好的代码共享和重用性。
  • 现代工具支持:现代的版本控制系统和工具链使得 Monorepo 开发模式更为可行,例如像 Pnpm、Yarn 、Lerna 和 Turborepo 等工具,它们提供了更好的管理、构建和部署多个项目的能力。
    • 管理所有项目的版本控制更加容易和一致,降低了不同项目之间的版本冲突。
    • 可以统一项目的构建和部署流程,降低了配置和维护多个项目所需的工作量。
    • Monorepo 可能随着时间推移变得庞大和复杂,导致构建时间增长和管理困难,git clone、pull 的成本增加。
    • 权限管理问题:项目粒度的权限管理较为困难,容易产生非owner管理者的改动风险。
  • 5.如何解决monorepo无法进行细粒度权限管理的缺点

    1. 使用代码所有权文件使用如 CODEOWNERS 文件(GitHub 等平台支持)来指定某个目录或文件的所有者。当这些文件或目录被修改时,只有指定的所有者才能批准更改。这种方法能够实现对项目或模块级别的权限粒度控制。
    2. 利用CI/CD流程在持续集成/持续部署(CI/CD)流程中设置权限和访问控制。例如,可以配置流程,只允许具有特定权限的用户触发构建或部署到生产环境。这种方式可以在流程层面上控制谁可以对代码库进行重要操作。
    3. 分支策略通过严格的分支管理策略,如Git Flow,控制不同级别的开发人员可以访问和修改的分支。比如只允许项目负责人合并代码到主分支,而其他开发人员只能在特定的功能分支上工作。
    4. 使用Git钩子配置Git钩子(Hooks),在代码提交或合并前执行脚本来检查提交者的权限。例如,可以设定pre-commit钩子,确保提交的代码符合访问权限要求。
    5. 利用子模块虽然这种做法在传统Monorepo中较少使用,但通过Git子模块(submodules)可以实现对特定部分的仓库独立控制,从而在需要时提供更细粒度的权限管理。
    6. 第三方工具和扩展考虑使用一些第三方工具和扩展来管理权限。例如,GitLab和Bitbucket等平台提供了更细粒度的权限控制设置,允许在项目或组织级别进行详细的访问控制。

    6.为什么组件库项目会选用 Monorepo 模式

    对于组件库项目,很自然的会涉及到划分以下模块

    • components 包,作为组件库的主要代码,实现各个 UI 组件的核心逻辑。
    • shared 包,主要存放各种杂七杂八的工具方法。
    • docs 包,组件库的示例 demo 与使用文档。
    • playground 包,组件库的在线编辑、演示应用。

    细化拆分不同模块的好处非常明显,一句话总结就是:模块划分的越清晰,复用时的灵活性、可操作性就越强,每个独立模块产物的体积也会越轻量。

    二、pnpm的安装和使用

    1.安装全局pnpm

    npm i pnpm -g

    2.查看pnpm版本

    pnpm -v
    如果显示版本,说明安装成功

    三、pnpm在monorepo架构中的使用

    如下结构,我们项目中有一个main应用,在web文件夹下还有一个react应用和vue应用,我们可以用pnpm对依赖进行统一管理

    image.png
    1.在根目录pnpm初始化生成package.json

    pnpm init

    image.png
    2.配置工作空间

    ① 新建pnpm-workspace.yaml文件

    image.png

    ② 配置pnpm-workspace.yaml文件

    packages:
    #主项目
    -'main-project'
    #子目录下所有项目
    -'web/**'
    3.安装项目依赖

    在根目录运行如下命令,一键为所有项目安装依赖

    pnpm i

    image.png
    4.暴露公用方法
    ① 创建common文件夹及index.ts
    image.png
    ② 在common文件夹中运行pnpm init初始化

    pnpm init

    ③ pnpm-workspace.yaml文件中添加common文件夹
    image.png
    ④ 编写index.ts文件暴露方法
    image.png

    export const hello = () => { console.log('hello') }

    ⑤ 根目录运行pnpm -F main-project add common将common里的方法暴露给main-project

    这里的-F是–filter的简写,用于过滤指定的package,用法 pnpm –filter

    pnpm -F main-project add common

    ⑥ 在页面中引入公共方法
    image.png
    ⑦ 启动页面

    pnpm -F main-project dev

    image.png
    ⑧使用pnpm模块内部指定依赖 踩坑总结
    image.png

    例如我要将common包添加到packages/*下面的所有子项目的package.json中执行 pnpm -F packages/* add common or pnpm -F ‘packages/*’ add common

    都会显示找不到路径原因:官网通知pnpm filter过滤器非常强大 需要依赖当前项目相对路径

    正确指令:pnpm -F "./packages/\*" add common

    四、pnpm常用命令

    #安装软件包及其依赖的任何软件包如果workspace有配置会优先从workspace安装
    pnpmadd<pkg>
    #安装项目所有依赖
    pnpminstall
    #更新软件包的最新版本
    pnpmupdate
    #移除项目依赖
    pnpmremove
    #运行脚本
    pnpmrun
    #创建一个package.json文件
    pnpminit
    #以一个树形结构输出所有的已安装package的版本及其依赖
    pnpmlist

    子包管理操作在 workspace 模式下,pnpm 主要通过 –filter 选项过滤子模块,实现对各个工作空间进行精细化操作的目的。

    为指定模块安装外部依赖。
    • 下面的例子指为 a 包安装 lodash 外部依赖。
    • 同样的道理,-S 和 -D 选项分别可以将依赖安装为正式依赖(dependencies)或者开发依赖(devDependencies)。
    //为a包安装lodash
    pnpm--filterai-Slodash//生产依赖
    pnpm--filterai-Dlodash//开发依赖
    指定内部模块之间的互相依赖。
    • 指定模块之间的互相依赖。下面的例子演示了为 a 包安装内部依赖 b。
    //指定a模块依赖于b模块
    pnpm--filterai-Sb

    pnpm workspace 对内部依赖关系的表示不同于外部,它自己约定了一套 Workspace 协议 (workspace:)。下面给出一个内部模块 a 依赖同是内部模块 b 的例子。

    {
    "name":"a",
    //...
    "dependencies":{
    "b":"workspace:^"
    }
    }

    在实际发布 npm 包时,workspace:^ 会被替换成内部模块 b 的对应版本号(对应 package.json 中的 version 字段)。替换规律如下所示:

    {
    "dependencies":{
    "a":"workspace:*",//固定版本依赖,被转换成x.x.x
    "b":"workspace:~",//minor版本依赖,将被转换成~x.x.x
    "c":"workspace:^"//major版本依赖,将被转换成^x.x.x
    }
    }