monorepo

145 阅读3分钟

1.monorepo是什么

  • 一个仓库管理多个项目,很多开源库都采用这中代码管理方法比如vue react
  • Monorepo 是单个代码库中许多不同应用程序和包的集合 可以更好的复用和抽离公共组件和方法。
  • 工作区,每个应用程序和包都将位于自己的工作区中,并具有自己的package.json,工作区间可以相互引用和依赖。
packages:
  - "apps/*"
  - "packages/*"
  "devDependencies": {
    "@repo/eslint-config": "workspace:*",
    "@repo/typescript-config": "workspace:*",
  }
}

仅在某些工作区中运行某个项目

cd docx 
turbo run dev
// 或者
turbo run dev --filter docs

  • 优点: 便于重用 代码规范
  • 缺点:项目复杂不好维护

2.安装和创建项目

pnpm dlx create-turbo@latest

image.png

会让选择包管理器 Turborepo 建议使用pnpm

目录结构

monorepo
├─ docs
├─ apps
│ ├─ docs
│ └─ web
├─ packages
│  ├─ eslint-tsconfig
│  ├─ tailwind-tsconfig 
│  ├─ typescript-tsconfig
│  └─ ui
├─ turbo.json
├─ pnpm-workspace.yaml
└─ package.json

相互依赖的工作区

{ "dependencies": { "ui": "workspace:*" }}

相当于在项目中引于引用工作区的ui包

3.在工作区中添加包

往单个项目中添加依赖

pnpm add <package> --filter <workspace>

image.png

在moporepo 项目中添加子包

新建包的文件夹

mkdir packages/cspell-config

新建package.json

  •  main 和 exports['.'].require 字段用于设置 require() 方式的加载入口(cjs 规范),使用const ** = require('**')
  • module 和 exports.*.import 字段用于设置 import 的加载入口,使用import ** from '**'
  • types 和 exports.*.types 字段用于设置 d.ts 类型声明的加载入口
  • exports 比起 mainmoduletypes,它可以暴露更多的出口,而后者只能定义主出口
  • 版本信息 ^最新minor版本 ~安装最新的patch版本
{
    "name": "@repo/math-helpers", 
    "version": "0.0.1", 
    "main": "./src/index.ts",
    "types": "index.d.ts",
    
    "exports": 
        { ".": {
             "require": "./src/index.js"
            },
           "./button": {
               "require":""./src/button.tsx" "
           }
        },
    "dependencies": { "typescript": "latest" }
}

新建src/index文件 image.png

之后添加tsconfig.json

{
  "compilerOptions": {
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "preserveWatchOutput": true,
    "skipLibCheck": true,
    "noEmit": true,
    "strict": true
  },
  "exclude": ["node_modules"]
}

4.发包

将构建好的包,可以发布到npm上 公开访问或者发布私有包,提供团队内部使用

在pakeage.json中

  • private 是否是私有包
  • 项目需要发布到私有的 npm 仓库时需要设置
  • files 指定了发布为 npm 包时,哪些文件或目录需要被提交到 npm 服务器中。
{
    "files": [ "LICENSE", "README.md", "dist" ],
    "private": true,
    "publishConfig":{
        "registry": "https://mynpm.com",
        }
}

发包流程

在npm上注册一个账号 npm login会提示让你注册一个账号

npm login
npm publish 
//发布到公有包
npm pubilsh 

注意:发包的过程可能会遇到一些问题

image.png

在npm上建立一个组织,名字要与package.json 中的name对应

image.png

image.png

一个管理版本和变更日志的工具 changesets

发包的时候,需要管理一些版本的变更,而且monorepo 项目结构复杂,手动一个一个发包不是很方便,所以使用changesets 来管理发包流程,更加方便

  • 在根项目中添加脚本
{ 
"scripts": { 
    "publish-packages": "turbo run build lint test && changeset version && changeset publish"
    }
}

  • 添加changeset并且初始化
    pnpm install @changesets/cli && npx changeset init
    npx changeset

会有一个选项让你选择要发布的包和包的版本 image.png

image.png

npx changeset publish

发布版本成功 image.png

在changeset/config.json中 ignore 可以忽略你不想发布的包

{
  "$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json",
  "changelog": [
    "@changesets/cli/changelog",
    {
      "repo": "https://github.com/ivy-rong/turbo-study"
    }
  ],

  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": ["docs", "web"]
}

5. 测试在别的项目中使用npm发布的包

image.png

image.png

总结

简单介绍了monorepo的基本概念和基本构建方式,通过pnpm方式配置了monorepo基础环境,感兴趣可以补充相关内容,一起交流合作探究。