pnpmに基づくmonorepoプロジェクトの構築

一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加した初日です。クリックしてイベントの詳細をご覧ください

一部のクラスメート(@dongdong acridine)の影響を受けて、ピットを踏むのが良い経験であるかどうか、アカウントを実行しているように見える人もいるかもしれませんが、私が行ったことのいくつかを記録する必要があると感じていますが、いつも少し便利だと思う人もいれば、アドバイスをいただければ助かります。
私は@Lafferyです。これは、始めたばかりのフロントエンドの初心者です。この記事が役に立ったと思われる場合は、親指を立ててスワイプしてください。

バックグラウンド

トピックに戻ると、最近自分のプロジェクトを開発していたとき、プロジェクトの規模がどんどん大きくなり、追加のライブラリを開発したかったので、元のプロジェクト構造は適用できなくなりました。

たとえば、元のプロジェクト構造は次のようになります

# app
├── lib
│   ├── pkg1
│   │   └── package.json
│   ├── pkg2
│   │   └── package.json
│   └── pkg3
│       └── package.json
└── package.json
复制代码

私が今経験している主な問題点はこれです

  • プロジェクトにこれらのパッケージがあるのはなぜですか?

    • これらのパッケージは、開発プロセス中に徐々に落ち着いた一般的な(私自身の)パッケージであり、プロジェクトの本体はappこれらのパッケージに依存しています。

    • 再利用できるコードがたくさんあるので、このプロジェクトで一緒に開発したいです

  • pkg1、、およびメインプロジェクトの依存関係が重複しているpkg2想像してみてください。node_modulesに拷問された友人は、これが意味することを知っていると思います。pkg3app

    • 遅いダウンロード
    • プロジェクトのサイズが大きすぎます
  • 各pkgにはさまざまなnpmスクリプトがありますが、もちろん、主なスクリプトはdev、、、buildなどtestですlintこのようなワークフローがある場合(各PRの後、すべてのパッケージは、マージが許可される前にCIでlintまたはテストされます。次に、各パッケージディレクトリでスクリプトを順番に実行する必要があるという問題が発生します。

モノレポとは?

简单来说就是把多个项目放在同一个代码仓库里,区别于multirepo(每个项目对应一个代码仓库)。它的核心优势就是便于代码复用版本管理

这里不多做介绍,如果有不清楚的小伙伴,可以自行搜索。

pnpm

大家都知道,npm是下载nodejs自带的包管理工具,它当然十分优秀,但是有时候下载龟速,为人诟病。

而我近来一直在使用的yarn,很好的解决了一些下载慢的问题,但是这和这篇文章的主题没有关系了。(其实yarn也能做monorepo,但是为什么我用pnpm呢?因为我在上一家公司见到的就是pnpm)

谈谈这篇文章的主角,pnpm

节约磁盘空间并提升安装速度

pnpm有一个概念,叫做workspace,就是将一个仓库分成不同的工作空间,一般是一个package对应一个workspace。

pnpm在执行pnpm install(根目录下)时,做的事情就是将所有workspace的所有的依赖,下载到node_modules/.pnpm目录下,然后再根据各workspace的依赖,在其目录下通过软链接的方式将这些依赖添加进来。

盗用一下官方的图

image.png

相信看到这里大家能意识到,所有依赖只需要下载一次,那么下载不仅快,而且占用的磁盘体积也小。

对原有项目进行monorepo改造

我们重新调整下项目的结构

# app
├── packages
│   ├── pkg1
│   │   ├── package.json
│   │   └── pnpm-lock.yaml
│   ├── pkg2
│   │   ├── package.json
│   │   └── pnpm-lock.yaml
│   ├── pkg3
│   │   ├── package.json
│   │   └── pnpm-lock.yaml
│   └── app
│       ├── package.json
│       └── pnpm-lock.yaml
├── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
复制代码

是不是感觉清爽很多[旺柴]。

我们在pnpm-workspace.yaml中对workspace进行配置,好让pnpm知道都有哪些workspace。

# ./pnpm-workspace.yaml
packages:
  # root directory
  - "."
  # all packages in subdirs of packages/
  - "packages/**"
  # exclude packages that are inside test/ directories
  - "!**/test/**" # '!' means exclude
复制代码

现在动手执行pnpm install,和前面说的一样,所有设定好的workspace的依赖同时被下载下来了。

执行各workspace的脚本

现在我们回到开头提到的一个场景。

如果你有这样一个workflow--每次PR后在CI里面把所有包都进行lint或test测试之后才允许合并,那么你一定会为需要依次到各个包目录下执行脚本而烦恼。

在根目录下执行app下的脚本

通常你要执行app包下指令,可能会这样做

cd packages/app
npm run xxx
复制代码

或者你是个省事小能手,在./package.json里面这样写

# ./package.json
{
    // ...
    "scripts": {
        "app:xxx": "cd packages/app && npm run xxx"
    }
    // ...
}
复制代码

这样你就只需要在根目录下执行npm run app:dev就可以了。

这种做法未尝不可,但是假如有一天你心血来潮,把这个包的目录名称改成了webapp,就得忍痛把这些指令全部改成cd packages/webapp && npm run xxx

pnpm提供一个--filter-F)指令,你可以设定选择器,让pnpm在特定包下执行指令

我们假设上面提到的包叫这些名字(package.json里的name)

  • pkg1: @laffery/pkg1
  • pkg2: @laffery/pkg2
  • pkg3: @laffery/pkg3
  • app: @laffery/app

现在你要执行app下的dev指令,只需要

pnpm run --filter @laffery/app dev
复制代码

我们一般很少改包的名字,所以这样改目录名字就不会有问题。

当然了,我们还是一个省事小能手,可以把所有常用的指令都配置在根目录下。

# ./package.json
{
    // ...
    "scripts": {
        "app:dev": "pnpm run --filter @laffery/app dev",
        "app:build": "pnpm run --filter @laffery/app build",
        "app:deploy": "pnpm run --filter @laffery/app deploy"
    }
    // ...
}
复制代码

现在我们所有的命令都可以在根目录下执行了。

批量执行命令

这个--filter既然是过滤器,又不是只选择其中一个,当然是支持筛选多个workspace啦。

现在你想对所有的包进行lint或test,可以这样做

# ./package.json
{
    // ...
    "scripts": {
        "lint": "pnpm run --filter=\"@laffery/*\" lint",
        "test": "pnpm run --filter=\"@laffery/*\" test"
    }
    // ...
}
复制代码

然后在你的.github/workflows/ci.yaml下轻松地写下

# .github/workflows/ci.yaml
jobs:
  check:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Install
        run: npm i -g pnpm && pnpm i
      - name: ESlint
        run: pnpm lint
      - name: Tests
        run: pnpm t
复制代码

大功告成!

もちろん、publish npmパッケージを統合するなど、他にもいくつかの機能があります。公式Webサイトで確認できます。

同じリポジトリでコードを再利用する

appに依存し[email protected][email protected]後者は両方ともに依存するとし[email protected]ます。通常は、npmのバージョンを直接使用します。ただし、現在開発中のものを直接使用したいが[email protected]、npmで公開されていない場合は、実行が困難です。

まったくありませんimport xxx from "../../pacakge/pkc3/xxx"

このとき、ワークスペースが便利です。次のようなpkg1依存関係を記述できます。

// packages/pkg1/package.json
{
    "dependencies": {
        "@laffery/pkg3": "workspace:1.5.1",
    }
}
复制代码

詳細な紹介については、公式Webサイトのドキュメントを参照してください。

VSCodeワークスペース

さらに、私のようなVSCodeファンの場合は、ルートディレクトリに新しいxxx.code-workspaceファイルを作成することを検討できます。

{
  "folders": [
    {
      "path": "packages/pkg1",
      "name": "Package 1"
    },
    // ...
    {
      "path": "packages/app",
      "name": "Web Application"
    },
  ]
}
复制代码

エディターがボタンをポップアップし打开工作区、クリックすると奇跡的な効果があります〜、詳細については、を参照してください。

要約する

この記事では、pnpmに基づいてmonorepoプロジェクトを構築した経験を紹介します。

  • ディスク容量を節約し、インストール速度を上げる
  • 便利な統合管理、テスト、構築、公開などの一連の手順を実行します
  • 同じリポジトリにある他のパッケージのコードを再利用する

この記事は私の個人ブログにも同時に掲載されています。興味があれば、ここをクリックしてください

私は@Lafferyです。フロントエンドの新人です。私の記事が気に入った場合、または役立つと思われる場合は、いいね/フォローしてください。

おすすめ

転載: juejin.im/post/7084582387060834340