Yarn: ワークスペース:ワークスペースごとにファイルをロックする

作成日 2018年02月28日  ·  54コメント  ·  ソース: yarnpkg/yarn

機能をリクエストしバグを報告しますか?
特徴

現在の動作は何ですか?
トップレベルノードモジュールを含むモノレポにyarnワークスペースを使用すると、モノレポのルートに単一のyarn.lockのみが作成され、トップレベルノードモジュールに固有のyarn.lockは作成されません。

期待される動作は何ですか?
ヤーンワークスペースを使用して、アプリ(トップレベルノードモジュール)とライブラリの両方を含むモノリポジトリを管理したいと思います。 ただし、monorepoのルートにyarn.lockファイルが1つしかないため、たとえばアプリをDockerイメージにパッケージ化できません。 選択したワークスペース用にyarn.lockファイルを取得する方法が欲しいのですが、そのワークスペースは後でモノリポジトリの外部で使用される可能性があるためです。

例:
workspace-aworkspace-b 2つのワークスペースを持つモノレポがある場合。 workspace-aは、 workspace-bからエクスポートされたモジュールの一部を使用します。 workspace-aをDockerイメージにパッケージ化する(または、モノレポ全体を使用せずに、そのワークスペースを単独でパッケージ化する他の方法)場合、 yarn.lockはありません。 つまり、 workspace-aのファイルをモノレポ以外の別の環境に移動すると、 yarn.lockファイルが失われ、依存関係をインストールすると、すべてのファイルが失われます。ロックファイルの利点(開発で使用したものと同じ依存関係をインストールしていることを知っています)。

私はこれについての問題を見つけることができなかったことに非常に驚いています。 そのようにモノリポジトリで作業したいのは私だけですか? 多分私は何かが足りないのですか? 私の現在の回避策は、まったく持ち上げずにlernaを使用しているため、パッケージごとにロックファイルを作成します。
最近リリースされたnohoist機能も、ワークスペースごとに異なるyarn.lock作成しないため、役に立たないようです(私は望んでいましたが)。
この問題は、別の問題に関するこのコメントにいくらか関連し

node.js、yarn、およびオペレーティングシステムのバージョンをお知らせください。
ノード8.9.3、ヤーン1.5.1、OSX 10.13.3

cat-feature triaged

最も参考になるコメント

したがって、私たちにとっては、モノレポ全体を結果のDockerコンテナーにパッケージ化する必要はありません。 本番環境ではdockerを使用しており、これらの画像はできるだけ明るくする必要があります。 私たちのモノレポジトリは非常に大きく、ライブラリパッケージを使用してコードを共有する複数のマイクロサービスが含まれています(一部のライブラリは一部のマイクロサービスに関連していますが、すべてではありません)。 したがって、マイクロサービスをパッケージ化するときは、そのマイクロサービスのファイルとその他の依存関係を適切な依存関係としてイメージに含める必要があります。プライベートレジストリからダウンロードし、Dockerイメージのアーチ用に構築します。

したがって、ここでの主な考慮事項は、Dockerイメージをできるだけ明るく保つことであり、monorepo全体をパッケージ化することは私たちのニーズに合わないと思います。 また、マイクロサービスのイメージ内で「yarn」を実行する場合、シンボリックリンクは必要ありません。通常の依存関係です。

ここでの解決策は、ワークスペースごとにyarn.lockファイルを作成する必要はありません。また、特定のワークスペースをパッケージ化するプロセス、オンデマンドでワークスペースのyarn.lockファイルを生成するプロセスに役立つyarnコマンドにすることもできます。 ..

それがユースケースの明確化に役立つことを願っています..🍻

全てのコメント54件

糸のブログに基づく:

ヤーンロックを含むパッケージを公開する場合、そのライブラリのユーザーは影響を受けません。 アプリケーションまたはライブラリに依存関係をインストールする場合、独自のyarn.lockファイルのみが尊重されます。 依存関係内のロックファイルは無視されます。

個々のパッケージを公開するときにyarn.lockをバンドルする必要はないようです...これはリポジトリ全体の開発成果物であるため、各パッケージに入れる必要はありません。

@connectdotzライブラリや公開パッケージには必要ないかもしれませんが、

確かに...しかし、開発ドッカーコンテナにはレポ全体が含まれているので、とにかくyarn.lockが含まれているのではないでしょうか。 Dockerコンテナーを使用して、さまざまなOSまたはプラットフォームのmonorepoプロジェクトをテストしていることがわかります。この場合、リポジトリ全体とそのyarn.lockをデプロイするだけです。 開発サイクル中にmonorepoプロジェクトからdockerコンテナーに個々のパッケージをデプロイする必要があるユースケースの例を教えてください。そうすれば、より具体的な理解を得ることができます...

したがって、私たちにとっては、モノレポ全体を結果のDockerコンテナーにパッケージ化する必要はありません。 本番環境ではdockerを使用しており、これらの画像はできるだけ明るくする必要があります。 私たちのモノレポジトリは非常に大きく、ライブラリパッケージを使用してコードを共有する複数のマイクロサービスが含まれています(一部のライブラリは一部のマイクロサービスに関連していますが、すべてではありません)。 したがって、マイクロサービスをパッケージ化するときは、そのマイクロサービスのファイルとその他の依存関係を適切な依存関係としてイメージに含める必要があります。プライベートレジストリからダウンロードし、Dockerイメージのアーチ用に構築します。

したがって、ここでの主な考慮事項は、Dockerイメージをできるだけ明るく保つことであり、monorepo全体をパッケージ化することは私たちのニーズに合わないと思います。 また、マイクロサービスのイメージ内で「yarn」を実行する場合、シンボリックリンクは必要ありません。通常の依存関係です。

ここでの解決策は、ワークスペースごとにyarn.lockファイルを作成する必要はありません。また、特定のワークスペースをパッケージ化するプロセス、オンデマンドでワークスペースのyarn.lockファイルを生成するプロセスに役立つyarnコマンドにすることもできます。 ..

それがユースケースの明確化に役立つことを願っています..🍻

詳細については、@netanelgiladおかげで、それはあなたのユースケースは、ドッキングウィンドウのコンテナに、生産や開発のために、個々のパッケージを公開の詳細であることを明確にする助けをします。 #4521のディスカッションに参加して、統合を開始してください。

個別のロックファイルを使用することはできますが、必須ではありません。 個々のファイルを指す-fフラグを使用してリポジトリのルートからdockerを実行すると、リポジトリ全体がコンテキストとして保持され、ルートからpackage.jsonとyarn.lockにコピーできます。

イメージでビルドするパッケージにはpackage.jsonのみが必要であり、yarn.lockに含まれているものがはるかに多い場合でも、yarnはコピーしたpackage.jsonファイルのパッケージのみをインストールします。

編集:そうは言っても。 ビルドに含まれていない場合でも、Dockerキャッシュはどのパッケージのパッケージ変更にも使用されません。

4206は関連/重複しており、そこで説明されているユースケースはまさに私たちが直面している問題です。

10個の異なるパッケージがあるとしましょう。 私たちは、必要に応じて人々が独立して作業できるように、すべてを独自のリポジトリに配置することを望んでいますが、必要に応じてそれらをリンクできるようにすることも望んでいます。 これを行うために、各パッケージのサブモジュールを備えたメガリポジトリと、これらの各サブモジュールをワークスペースとして参照するpackage.jsonがあります。

ワークスペースでも同様の問題があります。 私のプロジェクトはweb-appで、多くのローカルパッケージに依存しています。

web-app/
|--node_modules/
|--packages/
|  |--controls/
|  |  |--src/
|  |  |--package.json
|  |--utils/
|     |--src/
|     |--package.json
|--src/
|--package.json
|--yarn.lock

ワークスペースパッケージcontrolsおよびutilsは公開されず、パスによって使用されます。 問題は、 controlsパッケージ( yarn pack )をリリースする必要があり、それを単独でビルド/テストしたくないということです。 つまり、 web-app/packages/constols/内でyarn installを実行したいということです。 ワークスペースでは、トップレベルのweb-app/yarn.lockファイルをトップレベルのweb-app/node-modules/と一緒に使用します。 したがって、 web-app/packages/controls/package.jsonで指定されたサブセットではなく、すべてのパッケージをインストールします。 しかし、パッケージがそれ自体のpackage.json必要なすべての依存関係を持っており、他のワークスペースから不足しているdepsを埋めることができずに機能しないことを確認する必要があります。

2つの可能な解決策があります:

  1. ルートでない場合は、ルートのyarn.lock使用しますが、ローカルのpackage.json指定されたパッケージのみをインストールします。
  2. トップレベルの設定は検索せず、 .yarnrc/.npmrc検索します。

これにも苦労しています。 APIと一緒にAngularCLIプロジェクトがあるので、それらは同じリポジトリにあり、フロントエンドをHerokuにプッシュしようとしています。

最初にフロントエンドリポジトリにジャンプするようにHerokuに指示するビルドパックを使用しています: https

問題は、そのnohoistパッケージ内にyarn.lockがないため、Herokuはnpmでインストールするだけで、ロックされたパッケージではなく、すべての新しいパッケージになってしまうことです。

個々のパッケージでグローバルyarn.lockファイルを使用できます。 私は最近、次のようにDockerfileにアプローチしました。

WORKDIR /app
ENV NODE_ENV=production

ADD yarn.lock /app/
ADD package.json /app/

# Only copy the packages that I need
ADD packages/my-first-package /app/packages/my-first-package
ADD packages/my-second-package /app/packages/my-second-package

RUN cd /app && yarn install --frozen-lockfile

これにより、コピーした2つのパッケージで実際に使用されている依存関係のみがインストールされ、他のユーザーはインストールしません。

最初に1つのパッケージからリリースアーティファクトを作成し、次にその依存関係をインストールしないビルドプロセスがあります。 これは、Dockerのマルチステージビルドでかなり簡単です

  1. dockerにyarn.lock、package.json、UIパッケージのみを追加します
  2. yarn install --frozen-lockfile実行します
  3. ビルドプロセスを実行します
  4. 新しいステージを開始し、yarn.lock、package.json、および必要なランタイムパッケージ/ワークスペースフォルダーを追加します
  5. 構築されたアーティファクトに対してCOPY --from=<stage>を実行します
  6. yarn install --frozen-lockfileを実行し、 RUNコマンドを公開します。

そして、yarn.lockファイルで指定され、本番環境で必要な依存関係のみを含む小さなコンテナーになります。

@ johannes-scharlach
私はあなたが説明しているものとほとんど同じ方法を使用することになりました。 多段階ビルドは良いヒントです:)。

@connectdotz私の終わりから、この問題は解決される可能性があり、問題#4521に取り組み続けることができると思います。 メインのyarn.lockファイルはパッケージのサブセットで機能する可能性があるため、ワークスペースごとのyarn.lockは必要ないようです(これはより良い開発ワークフローになると思いますが😉)。 しかし、#4521の問題は依然として重要です。ここに到達したソリューションでは、yarnが相互依存性と特定のワークスペースの「ベンダー」を知っている必要がある場合でも、Dockerfile内のすべての依存関係ワークスペースに言及する必要があるためです。

私はここ数日、monorepoを最初にLerna、次にYarnワークスペースに変換しようとして過ごしました。 ヤーンは一般的により確実に機能し、特に最近のyarn workspaces run <script>wsrunのような他の素晴らしいものの導入により、私たちが必要としているものに本当に近いものになっています。

ただし、単一のyarn.lockは問題点です。

  • 既存のロックファイルを単一のロックファイルに正しく移行する方法がわかりません。https://github.com/yarnpkg/yarn/issues/6563を参照して
  • 特定のパッケージにのみ依存関係をインストールする(「de-hoisting」/「vendoring」)Dockerizedビルドは十分にサポートされていません。上記(https://github.com/yarnpkg/yarn/issues/5428#issuecomment-403722271)またはhttpsを参照してください

Yarnワークスペースが単なる小さなコアであるとどう思いますか?特定の機能のないパッケージの宣言です。 例えば:

  • ワークスペース全体でスクリプトを実行する場合は、 yarn workspaces run <script>ます。
  • 単一のロックファイルと巻き上げが必要な場合(2つは必ず一緒に結び付けられていますか?)、これがルートpackage.jsonます:
    json "workspaces": { "packages": ["packages/*"], "hoistDependencies": true }
  • 現在のロックファイルを吊り上げられた構造に移行する場合は、 yarn workspaces hoist-dependenciesます。

などこれらは単なる例であり、実際には、一部の機能はオプトインではなくオプトアウトになる可能性があります(たとえば、人々は単一のyarn.lockを期待し、今では巻き上げます)が、一般的な考え方は、ワークスペースはレポ全体のタスクの軽量な基盤になります。

どう思いますか?

この機能リクエストが対処している問題は、#4521と同じだと思います。 @ johannes-scharlachが説明することを本質的に実行するコマンドは、ワークスペースごとのロックファイルよりも確かに実行可能です。

ネストされたワークスペース用に現在オープンしているます。これは、別の問題を解決していると思いますが、この機能要求に似ているように聞こえ

Yarnワークスペースが単なる小さなコアであるとどう思いますか–特定の機能のないパッケージの宣言

ワークスペースは大幅に変更されることはなく、現在のインターフェースに満足していると思います。

ワークスペース全体でスクリプトを実行する場合は、 yarn workspaces run <script>

それはすでに可能です(v1.10、#6244)。

現在のロックファイルを吊り上げ構造に移行する場合は、 yarn workspaces hoist-dependenciesます。

ワークスペースインターフェイスは変更しないため、逆になります( dehoistDependencies )。

これについて私が気に入らないのは、それが技術的な振る舞い(巻き上げ)を取り、それを意味的な振る舞いに変えようとすることです。 ユーザーストーリーに焦点を合わせてから、その逆ではなく実装を理解する必要があります。

この場合、あなたのユースケース(「特定のパッケージにのみ依存関係をインストールする」)は、 yarn --focus拡張することでよりよく解決されると思います。

中心的な問題は、ワークスペースに巻き上げと単一のyarn.lockファイルが厳密に必要かどうかだと思います。 つまり、それは本当に彼らを定義するものなのか、それとも彼らが歴史的に得た最初の機能であるのか?

たとえば、このユースケースでは、ワークスペースの最適な仮想動作は次のようになります。

  • 効率を上げるために、開発時にnode_modulesを持ち上げます。
  • ローカルのyarn.lockファイルをビルド用に保持し(Dockerで特定のパッケージをビルドします。これは、他の人もこのスレッドで言及しています)、パッケージが特定のバージョンをロックできるようにします。 #6563も参照してください。
  • 巻き上げが必要ない(または回避する必要がある)場合でも、 yarn workspaces run <script>を介してスクリプトを実行します。

巻き上げはnohoistで無効にでき、 runはコマンドを使用しないだけで「無効」にできますが、単一のyarn.lockファイルを「無効」にすることはできません。 m無効にできないほどのコア機能なのか、それともまだ十分にリクエストされていないだけなのかわからない:)

これを解決する最善の方法はyarn install --app-mode package@versionを持つことだと思います

そうすれば、特定のバージョンでアプリを公開するときにワークスペースのロックファイルをコピーするだけで、バンドルされたロックファイルを尊重してapp-modeインストールできます。

Yarnはロックファイル全体をインストールする必要はありません。 そのパッケージに関連する依存関係グラフの一部のみを簡単に抽出できるはずです。

実際、これは今でも手動で行うのはかなり簡単かもしれません。

  • レジストリからパッケージzipを直接ダウンロードします(yarnには同等のものはありませんが、npmには同等のものがあります: npm pack package@version
  • gzipをnode_modules / packageに抽出します
  • node_modules / packageにcdします
  • そこからyarninstall --productionを実行します(バンドルされたロックファイルを尊重します)

編集:残念ながら、これはすべて間違っています。ワークスペースのロックファイルには、アプリパッケージの依存関係である可能性がある、ワークスペース内のパッケージのバージョンが含まれていないためです。 ワークスペースのロックファイルからアプリのロックファイルを作成する場合は、コピーよりも複雑な処理が必要になります。

別々のロックファイルが答えであるかどうかは正確にはわかりませんが、同様の問題があります。 CLIとバックエンドを使用してmonorepoをセットアップしています。 CLIには、プラットフォーム固有で、特定のセットアップを備えたデスクトップマシンでのみ機能するいくつかのパッケージが必要です。 一方、APIをDockerイメージに組み込むことができる必要があります。これは、現在のワークスペースの実装では基本的に不可能です。

ここでは@samuelaと非常によく似たユースケースです! これは大いに役立つでしょう!

私のユースケースは、他の「本物の」ユースケースと比べて笑えるように見えるかもしれません。 しかし、私はいくつかのutils(この場合はreactフック)のmonorepoをpackages/*内に持っています。

packages/*隣に2つ目のワークスペースがあり、それはlocal/*です。 これは実際にはgitignoreにあり、会社の開発者はそこで好きなことをすることができます。たとえば、そこにcreate-react-appアプリを入れて、開発中にフックをテストします。

現在、 local/*パッケージはgitignore上にありますが、ルートyarn.lockは、ローカルワークスペースのために、単純に肥大化して汚染されており、gitにチェックインされています。

私が望むのは、いくつかのワークスペースがいくつかの特定のロックファイルを使用するように指定する方法です。たとえば、次のようなマッピングです。

  "workspaces": {
    "packages": [
      "packages/*",
      "local/*"
    ],
    "lockfiles": {
      "local/*": "./local.yarn.lock"
    }
  }

または、「_ this_ワークスペースからロックファイルに何も入れないでください」を指定する方法もあります。

しかし、ええ、私のものはそもそも深刻なユースケースではありません:)

別々のロックファイルが答えであるかどうかは正確にはわかりませんが、同様の問題があります。 CLIとバックエンドを使用してmonorepoをセットアップしています。 CLIには、プラットフォーム固有で、特定のセットアップを備えたデスクトップマシンでのみ機能するいくつかのパッケージが必要です。 一方、APIをDockerイメージに組み込むことができる必要があります。これは、現在のワークスペースの実装では基本的に不可能です。

あなたはそれを釘付けにしました-私が見るように、yarn.lockファイルの非常にコアな利点の1つは、frozen-depプロダクションビルドを作成することです! ヤーンの作成者はそれを忘れましたか?

単一のロックファイルの問題を解決するためのもう1つの議論は、コードの所有権です。 GitHub CODEOWNERS機能のようなものを使用しているモノリポジトリがある場合、開発者のグループにパッケージの完全な所有権を与えることはできません。 これは、自分のワークスペースに何かをインストールすると、常にルートレベルのロックファイルが変更されるためです。 この変更は、ロックファイルのコード所有者によって承認される必要があります。十分な規模のモノレポが与えられると、元のワークスペースの所有者とは異なります。

ワークスペースごとにロックファイルを生成するオプションがあるもう1つの理由:Google App Engineは、ロックファイル(NPM / Yarn)なしでノードサービスを起動することを拒否します。 これは彼らの側では優れたDevOpsですが、私たちにとっては苦痛です。 これまでのところ、オプションは次のとおりです。

  • 意味するサービスを示すenvvarsを使用してすべてをデプロイし、 yarn start (サポートされている唯一のエントリポイント)をenvvarsに基づいて分岐するように変更します
  • ビルドスクリプトにメインロックファイルを各ワークスペースにコピーしてもらい、関心のあるサービスだけをデプロイします。(@ johannes-scharlachに感謝)

最終的には、ワークスペースのロックファイルごとに生成されるyarn install --workspace-lockfileコマンドが最善の解決策になると思います。

パッケージレベルのロックファイルのオプションがあると、私たちにも役立ちます。 私たちのユースケースは少し異なり、ローカルの依存関係を管理する新しい方法を試しています。

したがって、すでにいくつかのモノリポジトリがあり、単一のパッケージのみを含むいくつかのリポジトリがあります。 これらはすべて公開されているため、一緒に使用できますが、ローカルに配置してシンボリックリンクすると非常に便利な場合が多くあります。

ただし、一部の開発者はシンボリックリンクなどの管理に苦労しているため、すべてのマシンに複製する標準の空のヤーンワークスペースモノレポジトリを試し、次にパッケージリポジトリをそのローカルモノレポジトリに複製します。 パッケージのクローンが1つしかない場合もあれば、5つある場合もあります。これは非常に便利で、ローカル、クロスリポジトリ、クロス依存関係の開発が

しかし、解決できない問題が1つあります。依存関係を編集しても、ローカルのヤーンロックファイルは更新されません。更新の依存関係を更新しない空のモノリポジトリのルートファイルは常に更新されます( /packages gitignored。

ロックファイルの書き込みをモノレポジトリルートに巻き上げないオプションがあると便利で、パッケージレベルで書き出すことができます。

注意として、私は他の人が言及したDockerの周りのデプロイメントとビルドの問題にも遭遇しました、そしてこれはそれも解決するでしょう!

この機能は私にとっても非常に価値があります。 私の場合、いくつかのパッケージが異なるプラットフォームにデプロイされたモノリポジトリがあります。 1つはNow.shでデプロイされたNext.jsアプリで、もう1つはFirebaseにデプロイされた一連のクラウド機能です。

これらの展開の両方で、ソースコードはバンドルされ、クラウドにインストールしてビルドするためにアップロードされます。 ソースと一緒に移動するyarn.lockファイルがないということは、依存関係がpackage.jsonのバージョンを使用してインストールされ、バージョンがロックされていないことを意味します。

また、各ワークスペースでyarn.lockファイルを有効にできるようにしたいと思います。

@LeeChenelerさんとかなり類似している場合、私は糸のワークスペースがほとんどmonoreposために意図されている実感が、私たちのユースケース。

基本的に、さまざまなプロジェクトの依存関係として使用するReactコンポーネントライブラリを作成しました(すべて独自のリポジトリがあります)。 ヤーンワークスペースを使用することで、コンポーネントライブラリのローカルバージョンを簡単に参照し、変更を他のプロジェクトのローカルバージョンにすばやく反映させることができます。 また、依存関係library: "*"は変更なしで機能するため、本番環境にプッシュするときにpackage.jsonを変更する必要はありません。 私たちの唯一の問題は、ヤーンロックファイルがないと、各プロジェクトの製品バージョンが異なるパッケージバージョンを使用してしまう可能性があることです。

この問題は、yarnワークスペースを使用するすべてのパッケージ開発者に共通することを想像する必要があります。

トップレベルのロックファイルに関するもう1つの重大な問題は、Dockerのレイヤーキャッシュが壊れることです。 通常、最初にpackage.jsonとyarn.lockをコピーすることで、Dockerキャッシングを最適化できます。 Dockerがこれらのファイルに変更を検出しない場合、Dockerは前のレイヤーを使用します。 ただし、そのロックファイルがモノリポジトリ全体に対して単一のロックファイルである場合、パッケージを変更するとキャッシュが無効になります。 私たちにとって、これは、すべてのパッケージがキャッシュなしで構築される、途方もなく遅いCI / CDパイプラインをもたらします。 特定のスクリプトを実行するためにパッケージの変更をチェックするLernaのような他のツールがあります。 ロックファイルの依存関係の変更がトップレベルであるために取得されない可能性があるため、これも機能しません。

この(少し古い)問題を提起して申し訳ありませんが、これが役立つユースケースもあります。 独立してホストおよび開発されているマイクロサービスが10個ほどありますが、 yarn installと入力してすべてのフォルダーに依存関係をインストールし、 yarn start実行できる中央のワークスペースリポジトリがあると便利です。すべてのマイクロサービスを起動するスクリプトを実行します。 これは比較的単純なスクリプトで実行できるものですが、yarnワークスペースでも実行できるように見えましたが、各micorserviceのyarn.locksを尊重しながら動作させることができませんでした。

@nahtnam Yarn 1.xmonorepoの考え方は少し違うと思います。 これは、1つの屋根の下にある独立したプロジェクトではなく、コンポーネントの一部が公開された(ワークスペースと呼ばれる)単一の大きなプロジェクトに関するものです。 これらのコンポーネントは完全に独立しているわけではありませんが、次のように使用できます。Babelコンパイラを1つの大きなエンティティとして、 preset-envをサブモジュールとして使用します。 また、依存関係が統一されているという意味で同種です。一部のパッケージがcore-jsに依存している場合、すべてのパッケージで同じcore-jsバージョンである必要があります。単一のルートロックファイルで異なるバージョンをロックすることも、プロジェクトのパーツが異なるバージョンに依存することも意味がありません。 また、これは1つのプロジェクトであるため、そのすべてのコンポーネントがルートnode_modulesに自動的にリンクされます。これは、完全に独立したプロジェクトでは奇妙なことです。

したがって、マイクロサービスのパックを開発している場合(独立していて、何年も触れられないものもあれば、別のチームによって作成/更新されるものもあります)、ルートのない個人用ロックファイルが必要ですロック(Dockerの問題もここにあります)。 唯一の問題は、スクリプトの実行にどのツールが役立つかということです。 レルナは糸に縛られていないので答えかもしれません。

唯一の問題は、スクリプトの実行にどのツールが役立つかということです。 レルナは糸に縛られていないので答えかもしれません。

@ the-spykeそれだけではありません。 yarn workspacesも解決し、 npm linkと同じ方法で開発用のモジュールをリンクします。これが、私たちがそれを使用している主な理由です。 npm linkがうまく機能しない場合があります。

@ the-spykeありがとうございます! どういうわけか、私はそれがひっくり返ったと思いました(レルナ対糸のワークスペース)。 lernaを調べたところ、問題が解決したようです。

必要に応じて(公開されていても)更新できる個別のutilitiesパッケージを簡単に作成できるため、作業中のすべてのプロジェクトにワークスペースを使用することになりました。いくつかのパッケージをフォークしたい場合(基本的に、2つのブランチで同時に作業できるようにするため、これは前代未聞でした)、およびutilitiesパッケージを使用したい場合は、依存関係を再インストールする必要はありません。 package.jsonに追加せずにすぐに使用できます(ただし、個別にインストールする場合は明らかに良い考えであり、必須です自動IDEインポートの場合); すべてがうまくいきます。 @ the-spykeは良い点です。おそらく、 independent projects under one roofはワークスペースの目的ではありませんが、それでも私がここで行っているように見えます。単一のmonorepo-baseリポジトリがあります。 packagesフォルダーを除外しますが、 packages下の各フォルダーは個別の独立したgitリポジトリです。
image
もちろん、それは私をこのスレッドのトピックに連れて行きます。 すべてのパッケージを1つのリポジトリとしてコミットするわけではないので、ルートレベルのyarn.lockは無意味です。 私は--no-lockfileを使用してすべてをインストールしてきましたが、最近、競合するバージョンのclass-validatorで問題が発生しました。 今のところ、すべての部門を特定のバージョンにロックし(正直なところ、そのレベルの制御は私にとってより理にかなっています)、それがどのように機能するかを確認します。 トレッド全体をもう一度読みます。ユースケースに使用できるヒントがいくつかあるかもしれません。

PS。
yarn whyは、ロックファイルがないと機能しません。AppEngineの問題について言及している人もいます。 すべてのパッケージが個別のリポジトリである場合、ロックファイルはインストール時に毎回(VCSに追加せずに)生成される可能性があると思いますか? その特定のケースについてはよくわかりません。

残念ながら、@ johannes-scharlachによって提案されたソリューションは、ビルドされたイメージにビルドフォルダーに含まれていないランタイムノードモジュールが必要な場合、実行に必要なモジュールを正確に把握し、それらを入念にコピーする必要があるため、非常に面倒になります。最終ビルド段階。

(少しオフトピック) @GrayStrider package.jsonの「resolutions」フィールドを利用することもできます-これは、ネストされた依存関係にバージョンを強制する唯一の方法です。たとえば、すべてのlodashを正確なバージョンにしたい場合は、どれだけ深くネストされているか。 ただし、それは見つけるのが難しい非常に微妙なバグをもたらす可能性があります。

これが私たちが到達したソリューションです-既存のDockerワークフローへの影響を最小限に抑えます。

  1. ln project/yarn.lock packages/package1/yarn.lock -ルートyarn.lockから各パッケージにハードシンボリックリンクを作成します。
  2. packages/package1/DockerfileCOPY yarn.lock .を追加します
  3. Docker内のyarn install

利点

  • モノレポ全体を画像レイヤーにコピーする必要はありません
  • パッケージレベルのDockerfileをルートで単一のDockerfileにマージする必要はありません
  • 基本的にワークスペースロックファイルの要件を満たします

短所

  • --frozen-lockfileは機能しません。 ワークスペースパッケージはyarn.lockに含まれていないため、yarnは、 yarn.lock存在しないpackage.json 「追加」したパッケージを認識します。

CI / CDパイプラインの最初のステップとしてyarn --frozen-lockfileを実行することで回避できるため、これはマイナーな欠点です。

編集:
余談ですが、インストールに関するyarnのドキュメントは、パッケージ解決プロセスでロックファイルがどのように使用されるかによって、もう少し明確になると思います。

編集:
したがって、gitは実際にはハードリンクをサポートしておらず、ソフトシンボリックリンクのみをサポートしているため、この戦略は機能しません。

もう1つの方法は、precommit githookを使用してyarn.lockを各ワークスペースにコピーすることです...ローカルマシンからデプロイするときに問題が発生する可能性があるため、理想的ではありません。

@ dan-cookeは、洞察に感謝します。

@ dan-cooke、これはDockerのレイヤーキャッシュを壊します。これは、ワークスペースに新しい依存関係があると、すべてのDockerfileのインストールレイヤーが無効になるためです。

@miguelollerインストールレイヤーを変更してはならない場合は、すべてのパッケージに1つのロックファイルを使用しないでください。 依存関係をフラット化して単一の巨大なリストに引き上げることが、ワークスペースの全体的な目的です。 Dockerキャッシュを「壊す」のではなく、実際の依存関係がpackage.jsonで指定されていないため、キャッシュが無効になります。したがって、パッケージの最終的なコードはyarn.lock内容に依存します。 その結果、 yarn.lockを変更するたびにすべてのパッケージを再構築する必要があり、Dockerはすべてを正しく実行します。 また、すべてのビルドでレイヤーをyarn install再利用できるため、 where every package is built without the cacheとは異なります(おそらくこれを設定する必要があります)。

@migueloller
正しい。 幸い、新しい依存関係を頻繁に追加することはないため、これはせいぜいスプリントで1回だけ問題になります。

そしてそれでも、Dockerで再現可能な依存関係に対して(私たちのために)支払うのは小さな代償です

@ the-spyke、確かに。 これが、この問題がパッケージごとに個別のロックファイルを持つことに関するものである理由です。 このように、キャッシュされたレイヤーは、パッケージの依存関係が変更され、他のパッケージから独立している場合にのみ無効になります。

たぶん、この議論をnpm自体に移すことも価値があります。npm自体は、v7.0以降のワークスペースもサポートしています。

私は関連するトピックを調査しており、上記のコメントにいくつかの説明を追加したいと思います(私が直面した問題は、 lockfile重要性を理解できなかったことがある程度原因だったため、主に経験の浅い開発者を対象としています

「すべての依存関係を特定のバージョンにロックする」は、ピン留めと呼ばれます。 残念ながら、私が考慮していなかったサブ依存関係の更新(ここの記事の最後の段落)があったとしても、物事が壊れる可能性を防ぐことはできません。 それはまさにlockfileが起こるのを防ぐことを意味したものです。

私は過去に何度も更新を壊すのに十分な時間を無駄にしてきました。 マイナーアップデートによって引き起こされる目に見えないバグよりも、マージの競合や組織の頭痛の種に対処したいので、monorepoでlockfileを使用して実験します。

上記のように、私はこの問題の進展を非常に楽しみにしています

@migueloller個々のロックファイルは、個々のYarnMonoreposを意味します。 モノレポの深度の均一性を損なうため、ワークスペースのロックファイルを作成することはできません。 そうする場合は、Yarn Monorepoの元のアイデアから離れます。それは、異なるワークスペースに異なるバージョン(さらにはサブツリー全体)を配置するのではなく、ルートのフラットリストにデップを統合、巻き上げ、削減することです。 。

@ the-spykeですが、元の問題は正反対です。 ワークスペースごとのロックファイル。

ワークスペースごとにロックファイルを作成できない方法がわかりません。

モノレポのデップの均一性を壊しますか? 開発は確実です。 ただし、各ワークスペースから軽量のマイクロサービスをデプロイする必要がある場合、共有依存関係の目的全体がウィンドウから外れます。

共有され、持ち上げられたデップは、開発においてのみ意味があります。

ワークスペースをDockerに配置するには、ロックファイルが必要です。

@ dan-cookeご覧のとおり、2018年にもこの問題が発生しましたが、今では意見が異なります。

あなたはDockerとマイクロサービスを言っています。 しかし、通常のnpmパッケージを開発した場合はどうなりますか? dependencies仕様に従ってエンドユーザーによって提供されるため、ピン留めするproduction依存関係サブツリーはありません。 ですから、私が望んでいるのは、開発経験を最大化することであり、MonoreposとYarnWorkspacesが完全に行うことです。

同時に、マイクロサービス(MS)を開発している場合、2つの状況が考えられます。

  1. 独立したプロジェクト。 一部のMSは開発中であり、一部は何年も触れられていません。 この場合、それらは完全に独立しています。 持っていることが可能であるUserService使用して[email protected]MessagesService使用して[email protected] 。 これは、ワークスペースからルートnode_modulesフォルダをリンクするだけの簡単な世界ではありません。 したがって、ルートロックファイルを使用しても意味がありません。 個別のファイル(ルート)を作成し、それらを個別に管理します。 これは、YarnドキュメントではMultirepoと呼ばれていました。 しかし、今あなたが言っているのは、「便宜上、ルートフォルダーとは別のフォルダーでタスクを実行したい」ということです。 そして、それはまったく別のトピックです。

  2. Jest / Babel / etcのような統一された依存関係を持つプロジェクト。 これがワークスペースの目的ですが、MSには追加の要件があります。 リンティングやテストなどのCIステージでは、開発者のマシンと同じように機能するため、すべて正常に機能します。つまり、Yarnによってルートnode_modulesにインストールされ、フラット化されたdepsです。 それに加えて、おそらくyarn installフェーズをキャッシュして、並行ビルドを高速化します。

    本番環境では完全に異なります。最初は1つのワークスペースに必要な部門のみが必要であり、最後にそのutilsパッケージをインストールする方法がありますか? tarballとしてリンクまたはダウンロードする必要がありますか? したがって、本当に必要なのは、ワークスペースごとにロックファイルを用意することではなく、ワークスペースを指定して実行できるyarn install --prod <workspace>ようなコマンドを用意することです。これにより、本番部門のみがインストールされ、同時に、参照されていない他のワークスペースは無視されます。 私の場合のようにdata WSが依存するutils WSはなく、上のlogging WS、その後、 logging自体とそのDEPSに表示されませんnode_modules 。 同様の結果ですが、「ワークスペースごとのロックファイル」へのアプローチはまったく異なります。

    ビルドパッケージをリポジトリ(npm、Arifactory、GutHub)に公開している場合は、ロックファイルをワークスペースにコピーしてここでyarn install --prod実行するだけで、同様の動作を得ることができます。 古いファイルについて警告する必要がありますが、新しいバージョンで最初から再作成するのではなく、余分なdepsを削除する必要があります(試してみて、正当に見えます)。 オフラインミラーを使用すると、さらに優れた堅牢性が得られるはずです。

    そして最終的には、Multirepos用に正確に実装されたFocusedWorkspacesができました。

だから、私が言っていたのは、おそらく問題はそれが何であるかとは思えないということです。

@ the-spyke
あなたの言っていることがわかります。 それは間違いなく、この結果がどのように達成されるかにかかっていると思います。 おそらく、ワークスペースごとのロックファイルは、実際には望ましい結果を達成するための最良の方法ではありません。 あなたはいくつかの良い点を作ります。

とにかく、「1つのサイズですべてに対応」するソリューションではありません。

@ the-spyke、あなたは良い点を持ち出します。 おそらく、Yarnワークスペースが解決するように設計された問題と、それを使用して大規模なモノリポジトリを管理する場合は、その設計と一致するかどうかについて、さらに検討する必要があります。

このようなシナリオをどのように解決するかについて興味があります。

.
└── packages
    ├── app1
    ├── app2
    ├── lib1
    ├── lib2
    └── lib3

lib3は共有ライブラリであり、 app1app2依存しています。 lib1app1によってのみ使用され、 lib2app2によってのみ使用されます。 あなたの提案に基づいて、 lib1app1は、独自のロックファイルを使用して独自のワークスペースに配置し、 lib2app2と同じにする必要があります。 さて、問題は、_両方_ app1app2がそれに依存している場合、 lib3どうするかということです。 おそらく、両方のワークスペース( app1app2 )がlib3をワークスペースに追加してから、各アプリでyarn installするようにすることができますか? 糸はこれを許可しますか? ローカルで開発中にapp1app2両方を実行したい場合、競合はありますか(おそらく、 app1はReactアプリであり、 app2はGraphQL APIです) ? これはうまくいくようです。

次の質問は、「この方法で巻き上げることの利点をどのように得るか」です。 たとえば、 app1app2が多くの共通の依存関係を共有している場合、それらを引き上げると便利です。 ただし、これが範囲外である可能性があり、Yarn PnPによって解決される問題であることがわかります(ファイルをnode_modulesにコピーせず、代わりに共有キャッシュがあります)。

私はこれを試してみて、報告します。 これが機能するようになった場合は、Yarnワークスペースをずっと間違って使用している可能性があります...

編集:私はそれを試してみました、そしてそれはうまくいきます。

私は今、スタンスを変えて、ワークスペースごとに個別のロックファイルを持つことが、Yarnワークスペースでモノリポジトリ全体を管理するときに最初に頭に浮かぶかもしれないが、それは正しい質問ではないかもしれないことに気付きました。 より良い質問は、「Yarnワークスペースはモノレポを管理するように設計されていますか?」かもしれません。 いつものように、答えは「状況次第」です。

あなたがバベルであり、モノレポに取り組んでいる単一のチームがあり、すべてがロックステップで変更されることを意図している場合、はい、これはYarnワークスペースが設計された目的です。 ただし、複数のチームを持つ組織でモノレポを使用している場合は、単一のYarnワークスペースルートでモノレポ全体を管理したくない可能性があります。 おそらく、モノリポジトリ内でYarnのデフォルトの動作または複数のYarnワークスペースルートを使用したいだけです。 これは、構築しているアプリ、チームの数などによって決まります。

私たちにとって、デプロイ可能なエンティティ(この場合はDockerfileがあります)ごとに、(ワークスペースルートであるかどうかに関係なく)それぞれに対して個別のyarn install実行する必要があることが明らかになりました。 これにより、コードの所有権が明確になり、さまざまなリズムで発生する分離されたデプロイメントが可能になり、ロックファイルやDockerなどのキャッシュの問題が解決されます。ただし、これにはいくつかの欠点があります。

  • 複製されたnode_modulesパッケージはどうですか? これはモノリポジトリの一般的なクラスの問題であり、Yarnワークスペースは巻き上げに役立ちますが、一般的なモノリポジトリソリューションではありません。 ただし、他の解決策もあります。 たとえば、YarnPnPがこれを処理します。 糸なしでLernaを使用し、 --hoistオプションを使用することもできます。
  • 開発中にワークスペース間でコマンドを実行するユーティリティはどうですか? 繰り返しになりますが、Yarnワークスペースではこれを行うことができますが、モノレポ全体をYarnワークスペースのルートにする必要があるという意味ではありません。 必要なツールとスクリプトの作成はチームごとに異なり、チームのモノレポによって異なります。 ヤーンワークスペースは、おそらくモノレポタスクランナーとして設計されていません。 この仕事をするためにYarnワークスペースを少し曲げようとするかもしれません(つまり、 yarn workspace ...を使用してmonorepo全体でNPMスクリプトを実行します)が、monorepo全体の単一のワークスペースルートはおそらくそうではないことを覚えておくことが重要ですBabel、Jest、Reactなどでない限り、必要なものを提供してください。

モノレポの実行に伴う問題は他にもたくさんあります。 たとえば、依存関係を追跡し、CIで時間を節約するために変更されたものだけを再構築するのはどうですか? ヤーンワークスペースは、依存関係グラフをクエリできるようにすることで、そこで役立つ可能性があります。 Lernaはこれを実行して、実行中のコマンドのトポロジカルソートを可能にします。 Yarn v2では、実際には依存関係グラフもクエリできます。 パッケージマネージャーPNPMもそれを行います。 しかし、私はmonorepoの1の複雑さに依存し、そのために構築されたツールを(マネージャーをパッケージ化しない)しようとする場合がありますことを主張のようなBazelパンツバックなど、

@migueloller要件から、厳密に独立したパッケージやその他のエキゾチックなものは必要ないことがわかりました。また、よりスリムな開発者インストールも必要です。 このような場合は、通常のYarn Monorepoから始める必要があります。単一のルートとすべてのパッケージをワークスペースとして使用します。 インストール時間が短縮され、ディスク使用量が少なくなり、 app1はローカルにリンクされたlib1lib3ます。 唯一の欠点は、 lib1 devDepを追加すると共有yarn.lockが更新されるため、CIキャッシュが無効になることが多いことです。 ただし、通常、このトレードオフについて多くのことを心配するような依存関係は更新しません。

lib1lodash@^4.5.0" and lib2 may depend on lodash@^4.10.0 "に依存する場合があります。Monorepoの場合、 lodash単一バージョンを使用する必要があるためです。 Yarnは、ルートnode_modulesに引き上げられた ` [email protected] "のように、両方の指定子と互換性のある最新のものをインストールします。 また、更新の場合は、その単一の統合バージョンを更新するため、すべてのワークスペースは常に同じページにとどまります。 これは望ましい動作です。

独立したチームが独立したプロジェクトを開発する状況もあります。 この場合、 proj1[email protected]に留まり、 proj2[email protected]あり、独自のリズムで更新することができます。 もちろん、 lodash@~4.5.0ようなより厳密な指定子を使用することでこれを実現できますが、それでも第2レベルの依存関係の更新が早す​​ぎる可能性があります。 したがって、これらのプロジェクトは全体として完全に無関係である可能性があり、たまたま1つのgitリポジトリ内にあるだけです。 この場合、それらをYarn Monorepoとしてバインドし、共有ロックファイルの独立性をトレードオフする理由はありません。 それらをそれらが何であるかとして扱ってください:それらの独立した生活を持つ別々のプロジェクト。 そしてそれはマルチレポと呼ばれています。 Unixでは、すべてのディレクトリが/下にありますが、PCで可能なすべてのJSプロジェクトがMonorepoである必要があるという意味ではありません:-)

本番環境で使用するために最小限のDockerイメージを構築することは、Yarnとはまったく関係ありませんが、Yarnにyarn.lockという開発アーティファクトを再利用させて、このタスクを支援することもできます。

@ the-spyke、この例では3つのワークスペースのみを使用しましたが、実際のリポジトリには、フロントエンドとバックエンドの両方にライブラリとデプロイされたワークロードを組み合わせた20を超えるワークスペースがあります。 私が今見ているのは、独立したロックファイルを持つ複数のYarnワークスペースルートを持つことがおそらく理にかなっているmonorepo(またはいわゆるmultirepo)があるということです。 展開可能なユニットを分離のユニットとして使用することを考えています。これは、ロックファイルとうまく連携します。

私にとって、これを非常にうまく機能させるのは、最初のブログ投稿でそうではないと言われていても、Yarnワークスペースがワークスペースルートの外側のパスをサポートしているという事実です。 たとえば、次のようにすることができます。

{
  "workspaces": [
    "../lib1",
    "../lib3"
  ]
}

@miguelollerと同じユースケースがあり、考えられる1つのアイデアは、Yarnが次のような複数のワークスペースセットをサポートすることです。

{
  "workspaces": {
    "frontend-app": ["frontend", "common"],
    "backend-app": ["backend", "common"]
  }
}

Yarnは2つの追加のロックファイルを維持します(メインのyarn.lockはまだ存在すると思います):

.
└── monorepo/
    ├── yarn.frontend-app.lock
    ├── yarn.backend-app.lock
    └── packages/
        ├── frontend
        ├── backend
        └── common

フロントエンドなどのDockerイメージを構築する場合、次の内容を含むコンテキストを(たとえば、 tar経由で)作成します。

.
└── <Docker build context>/
    ├── yarn.frontend-app.lock
    └── packages/
        ├── frontend
        └── common

私が深く考えていなかったのは、フロントエンドとバックエンドが異なるバージョンをロックした場合に、適切なバージョンの依存関係をインストールできるかどうか( node_modulesリンク)です。 しかし、純粋に高レベルのビューから、2次元のYarnワークスペースはおそらく私たちが求めているものです。

(同様の何かもここに投稿され

ワークスペースごとにロックファイルは必要ないようですが、代わりに展開のためにワークスペースごとにnode_modulesが必要です

@gfortaine 、ディスカッションを読むと、実際にはそうではないことが

これはユーザーランドで実行できることを言及する価値があるかもしれません。 @yarnpkg/lockfileパッケージを使用すると、最上位のロックファイルを解析でき、次にyarn workspaces infoを使用して、ワークスペースの依存関係を判別できます。 この情報を各ワークスペースのpackage.jsonと一緒に使用すると、ワークスペースごとにロックファイルを生成できます。 次に、それをリポジトリ内のpostinstallスクリプトとして設定して、これらの個々のロックファイルをトップレベルのものと同期させておくことができます。

私はこれを構築することを突き刺して、私の発見を報告するかもしれません。

pnpmの場合でも、この実装を見つけたようです: @ pnpm / make-dedicated-lockfile

これがお役に立てば幸いです👍

この動作(ワークスペースごとのバージョン管理、ただし各パッケージにロックファイルが残っている)の必要性は、サブツリーが別のリポジトリに完全にエクスポートされるネストされたモノリポジトリがあるため、独立したままにする必要があることです。 現在、私はlerna / npmと、バージョンを均等化しようとするいくつかのカスタムロジックで立ち往生しています。 ヤーン(ネストされたサポートが存在する場所を考えると、v2だと思いますか?)がそれらすべてを一度に管理できればいいのですが、それぞれにグローバルピンの正しいサブセットを残します。

インストール後のスクリプトは、ロックファイルを直接管理しようとする可能性があると思います。 複雑に聞こえますが、どちらにしてもいいでしょう。

このページは役に立ちましたか?
0 / 5 - 0 評価