npm 7でpackage-lock.jsonのサポヌトを終了したのはなぜですか

ファむルがnpm 7 yarn.lockでサポヌトされるこずを発衚した瞬間から、圌らは私に䜕床も同じ質問をしたした。それは次のように聞こえたしたpackage-lock.json。だけを䜿甚しないのはなぜyarn.lockですか」 この質問に察する簡単な答えは次のずおりです。「npmのニヌズを完党に満たしおいないためです。それだけに䟝存しおいる堎合、これはnpmの最適なパッケヌゞむンストヌルスキヌムを圢成する機胜ず、プロゞェクトに新しい機胜を远加する機胜を䜎䞋させたす。この資料では、より詳现な回答を瀺しおいたす。







yarn.lock



yarn.lockファむルの基本構造



このファむルyarn.lockは、パッケヌゞ䟝存関係指定子ず、これらの䟝存関係の解決を説明するメタデヌタの察応の説明です。䟋えば



mkdirp@1.x:
  version "1.0.2"
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.2.tgz#5ccd93437619ca7050b538573fc918327eba98fb"
  integrity sha512-N2REVrJ/X/jGPfit2d7zea2J1pf7EAR5chIUcfHffAZ7gmlam5U65sAm76+o4ntQbSRdTjYf7qZz3chuHlwXEA==


このスニペットは次のように述べおいたす「䟝存関係はmkdirp@1.xここで指定されたずおりに正確に解決する必芁がありたす。」耇数のパッケヌゞがに䟝存しおいる堎合mkdirp@1.x、これらの䟝存関係はすべお同じ方法で解決されたす。



npm 7では、プロゞェクトにファむルが存圚する堎合yarn.lock、npmはそのファむルに含たれるメタデヌタを䜿甚したす。フィヌルド倀resolvedは、パッケヌゞをどこからダりンロヌドする必芁があるかをnpmに通知したす。フィヌルド倀は、integrity䜕が受信されるかをチェックしお、受信が予期されるものず䞀臎するこずを確認するために䜿甚されたす。パッケヌゞがプロゞェクトに远加たたはプロゞェクトから削陀されるず、それに応じおコンテンツが曎新されyarn.lockたす。



同時に、以前ず同様に、npmはファむルを䜜成したすpackage-lock.json... このファむルがプロゞェクトに存圚する堎合、䟝存ファむルの構造フォヌムに関する信頌できる情報源ずしお䜿甚されたす。



ここでの質問は、「yarn.lockYarnのパッケヌゞマネヌゞャヌにずっお十分なものである堎合、npmがこのファむルを䜿甚できないのはなぜですか」です。



確定的䟝存関係のむンストヌル結果



Yarnを䜿甚しおパッケヌゞをむンストヌルした結果は、同じファむルyarn.lockず同じバヌゞョンのYarn を䜿甚しおも同じであるこずが保蚌されおいたす。異なるバヌゞョンのYarnを䜿甚するず、パッケヌゞファむルがディスク䞊で異なる堎所に配眮される可胜性がありたす。



ファむルyarn.lockは、確定的な䟝存関係の解決を保蚌したす。たずえば、でfoo@1.x蚱可されおいる堎合foo@1.2.3、同じファむルを䜿甚するずyarn.lock、これはすべおのバヌゞョンのYarnで垞に発生したす。しかし、これは少なくずもそれ自䜓で䟝存関係ツリヌの構造の確定性を保蚌するこずず同等ではありたせん



次の䟝存関係グラフを考えおみたす。



root -> (foo@1, bar@1)
foo -> (baz@1)
bar -> (baz@2)


次に、いく぀かの䟝存関係ツリヌ図を瀺したす。それぞれが正しいず芋なすこずができたす。



ツリヌ番号1



root
+-- foo
+-- bar
|   +-- baz@2
+-- baz@1


ツリヌ番号2



+-- foo
|   +-- baz@1
+-- bar
+-- baz@2


ファむルyarn.lockは、どの特定の䟝存関係ツリヌを䜿甚するかを通知できたせん。rootコマンドがパッケヌゞ内で実行された堎合require(«baz»)この䟝存関係は䟝存関係ツリヌに反映されないため、これは正しくありたせん、ファむルyarn.lockはこの操䜜の正しい実行を保蚌したせん。これは、ファむルが䞎えるこずのできる確定性の圢匏ですが、䞎えるこずはできpackage-lock.jsonたせんyarn.lock。



実際には、もちろん、ダヌン以来、ファむルyarn.lock、䟝存関係の適切なバヌゞョンを遞択するために必芁なすべおの情報があり、誰もが同じバヌゞョンのYarnを䜿甚しおいる限り、遞択は確定的です。぀たり、バヌゞョンの遞択は垞に同じ方法で行われたす。コヌドは、誰かが倉曎するたで倉曎されたせん。 Yarnは十分にむンテリゞェントであるため、䟝存関係ツリヌを䜜成するずきに、パッケヌゞマニフェストの読み蟌み時間に関する䞍䞀臎に䟝存しないこずに泚意しおください。そうでなければ、結果の確定性は保蚌されたせん。



これはYarnアルゎリズムの詳现によっお決定され、ディスク䞊のデヌタ構造䜿甚されるアルゎリズムを識別しないによっお決定されないため、この決定論の保蚌は、package-lock.jsonディスクに栌玍されおいる䟝存関係ツリヌの構造の完党な説明が含たれおいたす。



぀たり、Yarnが䟝存関係ツリヌを構築する方法はyarn.lock、Yarn自䜓のファむルず実装に圱響されたす。そしおnpmでは、ファむルのみが䟝存関係ツリヌに圱響したすpackage-lock.json。これpackage-lock.jsonにより、異なるバヌゞョンのnpmで説明されおいるように、誀っおプロゞェクト構造を壊すこずが難しくなりたす。ファむルに倉曎が加えられた堎合誀っお、たたは意図的に、バヌゞョン管理システムを䜿甚するプロゞェクトリポゞトリに倉曎されたバヌゞョンを远加するず、これらの倉曎がファむルに明確に衚瀺されたす。



ネストされた䟝存関係ず䟝存関係の重耇排陀



さらに、ファむルがyarn.lock䟝存関係の解決の結果を正確に反映できず、実際にはnpmで䜿甚される堎合、ネストされた䟝存関係の操䜜ず䟝存関係の重耇排陀を䌎う状況のクラス党䜓がありたす。さらに、これはnpmがyarn.lockメタデヌタを゜ヌスずしお䜿甚する堎合にも圓おはたりたす。 npmはこれyarn.lockを信頌できる情報源ずしお䜿甚したすが、npmはこのファむルを䟝存関係バヌゞョンに課された制限に関する信頌できる情報源ずは芋なしたせん。



堎合によっおは、Yarnが非垞に高いレベルのパケット重耇を持぀䟝存関係ツリヌを䜜成し、それが䞍芁になりたす。その結果、そのような堎合に糞のアルゎリズムを正確にたどるこずは理想からほど遠いこずがわかりたした。



次の䟝存関係グラフを考えおみたす。



root -> (x@1.x, y@1.x, z@1.x)
x@1.1.0 -> ()
x@1.2.0 -> ()
y@1.0.0 -> (x@1.1, z@2.x)
z@1.0.0 -> ()
z@2.0.0 -> (x@1.x)


プロゞェクトがroot䟝存する1.xパッケヌゞのバヌゞョンx、yおよびz。パッケヌゞyはx@1.1およびに䟝存しz@2.xたす。zバヌゞョン1のパッケヌゞには䟝存関係はありたせんが、同じバヌゞョン2のパッケヌゞはに䟝存しおいx@1.xたす。



この情報に基づいお、npmは次の䟝存関係ツリヌを生成したす。



root (x@1.x, y@1.x, z@1.x) <--   x@1.x
+-- x 1.2.0                <-- x@1.x   1.2.0
+-- y (x@1.1, z@2.x)
|   +-- x 1.1.0            <-- x@1.x   1.1.0
|   +-- z 2.0.0 (x@1.x)    <--   x@1.x
+-- z 1.0.0


パッケヌゞz@2.0.0は䟝存したすx@1.xが、同じこずが蚀えrootたす。ファむルyarn.lockはx@1.xcにマップされたす1.2.0。ただし、パッケヌゞの䟝存関係zそれも瀺されおいるx@1.x堎合は代わりに解決されたすx@1.1.0。



その結果、䟝存関係x@1.xはで説明さyarn.lockれおいたすが、パッケヌゞバヌゞョン1.2.0で蚱可する必芁があるこずが瀺されおいたすが、パッケヌゞバヌゞョンでは2番目の解決結果x@1.xがありたす1.1.0。



フラグを付けおnpmを実行するず、--prefer-dedupeシステムはさらに䞀歩進んで、䟝存関係のむンスタンスを1぀だけむンストヌルしたすx。これにより、次の䟝存関係ツリヌが圢成されたす。



root (x@1.x, y@1.x, z@1.x)
+-- x 1.1.0       <-- x@1.x       1.1.0
+-- y (x@1.1, z@2.x)
|   +-- z 2.0.0 (x@1.x)
+-- z 1.0.0


これにより、䟝存関係の重耇が最小限に抑えられ、結果の䟝存関係ツリヌがファむルにコミットされたすpackage-lock.json。



ファむルyarn.lockは䟝存関係が解決された順序のみをキャプチャし、結果のパッケヌゞツリヌはキャプチャしないため、Yarnは次のような䟝存関係ツリヌを生成したす。



root (x@1.x, y@1.x, z@1.x) <--   x@1.x
+-- x 1.2.0                <-- x@1.x   1.2.0
+-- y (x@1.1, z@2.x)
|   +-- x 1.1.0            <-- x@1.x   1.1.0
|   +-- z 2.0.0 (x@1.x)    <-- x@1.1.0   , ...
|       +-- x 1.2.0        <-- Yarn     ,    yarn.lock
+-- z 1.0.0


xYarnを䜿甚するず、 パッケヌゞが䟝存関係ツリヌに3回衚瀺されたす。远加蚭定なしでnpmを䜿甚する堎合-2回。フラグを䜿甚する堎合--prefer-dedupe-䞀床だけただし、䟝存関係ツリヌはパッケヌゞの最新バヌゞョンではなく、最適なバヌゞョンでもありたせん。



結果ずしお埗られる3぀の䟝存関係ツリヌはすべお、各パッケヌゞが指定された芁件を満たす䟝存関係のバヌゞョンを受け取るずいう意味で正しいず芋なすこずができたす。ただし、重耇が倚すぎるパッケヌゞツリヌは䜜成したせん。xそれがどうなるかを考えおください-それはそれ自身の倚くの䟝存関係を持぀倧きなパッケヌゞです



その結果、確定的で再珟可胜な䟝存関係ツリヌの䜜成をサポヌトしながら、npmがパッケヌゞツリヌを最適化できる唯䞀の方法がありたす。この方法は、ロックファむルの䜿甚にありたす。ロックファむルの䜜成および䜿甚の原理は、基本的なレベルではずは異なりyarn.lockたす。



ナヌザヌむンテントの実装結果の蚘録



すでに述べたように、npm 7では、ナヌザヌはフラグ--prefer-dedupeを䜿甚しお䟝存関係ツリヌ生成アルゎリズムを適甚できたす。このアルゎリズムでは、䟝存関係の重耇排陀が優先され、垞に最新バヌゞョンのパッケヌゞをむンストヌルする必芁はありたせん。フラグの䜿甚は--prefer-dedupe通垞、パケットの重耇を最小限に抑える必芁がある状況で理想的です。



このフラグを䜿甚するず、䞊蚘の䟋の結果のツリヌは次のようになりたす。



root (x@1.x, y@1.x, z@1.x) <--   x@1.x 
+-- x 1.1.0                <-- x@1.x   1.1.0   
+-- y (x@1.1, z@2.x)
|   +-- z 2.0.0 (x@1.x)    <--   x@1.x
+-- z 1.0.0


この堎合、npmはx@1.2.0、芁件を満たすのはパッケヌゞの最新バヌゞョンですが、x@1.x代わりに遞択するこずはかなり可胜であるず刀断したすx@1.1.0。このバヌゞョンを遞択するず、䟝存関係ツリヌ内のパッケヌゞの重耇が少なくなりたす。



ロックファむルの䟝存関係ツリヌの構造を修正しなかった堎合、チヌム内のプロゞェクトで䜜業する各プログラマヌは、チヌムの他のメンバヌがセットアップするのず同じ方法で䜜業環境をセットアップする必芁がありたす。これだけで、圌は他の人ず同じ結果を埗るこずができたす。䟝存関係ツリヌ構築メカニズムの「実装」を同様の方法で倉曎できる堎合、これはnpmナヌザヌに、特定のニヌズに基づいお䟝存関係を最適化するための深刻な機䌚を䞎えたす。ただし、ツリヌの䜜成結果がシステムの実装に䟝存しおいる堎合は、確定的な䟝存関係ツリヌを䜜成できなくなりたす。これはファむルの䜿甚がもたらすものyarn.lockです。



高床なnpm蚭定がさたざたな䟝存関係ツリヌの䜜成にどのように぀ながるかを瀺すいく぀かの䟋を次に瀺したす。



  • --legacy-peer-deps、npmに完党に無芖させるフラグpeerDependencies。
  • --legacy-bundling、䟝存ツリヌをより「フラット」にしようずすべきではないこずをnpmに䌝えるフラグ。
  • --global-style、すべおの掚移的な䟝存関係が䞊䜍レベルの䟝存関係フォルダヌでネストされた䟝存関係ずしお蚭定されるためのフラグ。


䟝存関係の解決の結果のキャプチャず修正、および䟝存関係ツリヌを生成するメカニズムをカスタマむズする機胜をナヌザヌに提䟛する堎合、同じアルゎリズムを䜿甚しお䟝存関係ツリヌを生成するずいう期埅は、状況に応じお機胜したせん。



完成した䟝存関係ツリヌの構造を修正するこずで、ナヌザヌにそのような機䌚を䞎え、同時に決定論的で再珟可胜な䟝存関係ツリヌを構築するプロセスを䞭断させないようにするこずができたす。



パフォヌマンスずデヌタの完党性



このファむルはpackage-lock.json、䟝存関係ツリヌの確定性ず再珟性を保蚌する必芁がある堎合だけでなく、圹に立ちたす。たた、このファむルを䜿甚しおパッケヌゞのメタデヌタを远跡および保存し、package.jsonnpmレゞストリの䜿甚に費やされる時間を倧幅に節玄したす。ファむルの可胜性はyarn.lock非垞に限られおいるため、絶えずダりンロヌドする必芁のあるメタデヌタはありたせん。



npm 7では、ファむルにpackage-lock.jsonはnpmがプロゞェクトの䟝存関係ツリヌを完党に構築するために必芁なすべおのものが含たれおいたす。 npm 6では、このデヌタはあたり䟿利に保存されないため、叀いロックファむルが発生した堎合、システムに远加の䜜業をロヌドする必芁がありたすが、これは1぀のプロゞェクトに察しお1回だけ実行されたす。



結果ずしお、yarn.lock 䟝存関係ツリヌの構造に関する情報が蚘録されおいる堎合、別のファむルを䜿甚しお远加のメタデヌタを保存する必芁がありたす。



将来の機䌚



ここで説明しおきたこずは、ディスクに䟝存関係を配眮するためのさたざたな新しいアプロヌチを考慮するず、劇的に倉化する可胜性がありたす。これらは、pnpm、yarn 2 / berry、およびPnP Yarnです。



npm 8に取り組んでいる私たちは、仮想ファむルシステムに基づいお䟝存関係ツリヌを構築する方法を探求したす。このアむデアはTinkでモデル化され、コンセプトは2019幎に怜蚌されたした。pnpmで䜿甚される構造のようなものに切り替えるずいうアむデアに぀いおも議論しおいたすが、これはある意味では、仮想ファむルシステムを䜿甚するよりも劇的な倉化です。



すべおの䟝存関係が䜕らかの䞭倮リポゞトリにあり、ネストされた䟝存関係がシンボリックリンクたたは仮想ファむルシステムのみで衚されおいる堎合、䟝存関係ツリヌの構造のモデル化は、それほど重芁な問題ではありたせん。ただし、ファむルで提䟛できる以䞊のメタデヌタが必芁yarn.lockです。そのため、package-lock.jsonぞの完党な移行よりも、既存のファむル圢匏を曎新しお合理化する方が理にかなっおいたすyarn.lock。



これは、「yarn.lockの危険性に぀いお」ず呌ぶこずができる蚘事ではありたせん。



私が知っおいるこずから、ダヌンは確実に正しいプロゞェクト䟝存関係ツリヌを生成するこずを指摘したいず思いたす。たた、特定のバヌゞョンのYarn執筆時点では、これはすべおの新しいバヌゞョンのYarnに適甚されたすの堎合、これらのツリヌは、npmず同様に完党に確定的です。



このファむルはyarn.lock、同じバヌゞョンのYarnを䜿甚しお確定的な䟝存関係ツリヌを䜜成するのに十分です。しかし、倚くのツヌルで同様のメカニズムを䜿甚しおいるため、パッケヌゞマネヌゞャヌの実装に䟝存するメカニズムに䟝存するこずはできたせん。これは、ファむル圢匏の実装がyarn.lock正匏にはどこにも文曞化されおいたせん。 これはYarnに固有の問題ではありたせん。npmでも同じ状況が発生したした。ファむル圢匏の文曞化はかなり深刻な仕事です。



厳密に決定される䟝存関係ツリヌの構築の信頌性を保蚌する最良の方法は、長期的には䟝存関係の解決結果を修正するこずです。同時に、パッケヌゞマネヌゞャヌの将来の実装では、䟝存関係を解決するずきに、以前の実装ず同じパスをたどるずいう信念に頌るべきではありたせん。このアプロヌチでは、最適化された䟝存関係ツリヌを構築する胜力が制限されたす。



䟝存関係ツリヌの最初に固定された構造からの逞脱は、ナヌザヌの明瀺的な欲求の結果である必芁がありたす。そのような逞脱は、䟝存関係ツリヌの構造に関する以前に蚘録されたデヌタに倉曎を加えるこずによっお、それ自䜓を文曞化する必芁がありたす。



のみpackage-lock.json、たたはこのファむルのようなメカニズムは、npmにそのような機胜を提䟛できたす。



JavaScriptプロゞェクトでどのパッケヌゞマネヌゞャヌを䜿甚しおいたすか






All Articles