跳至主要內容

深入了解:Yarn PnP

資訊

這些步驟完全是選配的

雖然我們建議對新專案使用 Yarn Plug'n'Play,但對現有專案啟用它可能需要花費時間。如果您願意,可以跳過此部分,並在您有更多時間和/或從中獲得具體好處時再回來。

呼叫醫生

Plug'n'Play 執行嚴格的 相依性規則。如果應用程式中的某些項目依賴於未列出的相依性,您將會收到錯誤訊息,這可能會導致應用程式變得不穩定。

為了快速偵測哪些地方可能依賴於不安全的模式,Yarn 提供了一個名為「醫生」的工具。只要在您的專案中執行 yarn dlx @yarnpkg/doctor,醫生就會開始查看您的原始檔,以偵測任何潛在有問題的模式。

範例

例如,以下是醫生用來描述 webpack-dev-server 的內容

➤ YN0000: Found 1 package(s) to process
➤ YN0000: For a grand total of 236 file(s) to validate

➤ YN0000: ┌ /webpack-dev-server/package.json
➤ YN0000: │ /webpack-dev-server/test/testSequencer.js:5:19: Undeclared dependency on @jest/test-sequencer
➤ YN0000: │ /webpack-dev-server/client-src/default/webpack.config.js:12:14: Webpack configs from non-private packages should avoid referencing loaders without require.resolve
➤ YN0000: │ /webpack-dev-server/test/server/contentBase-option.test.js:68:8: Strings should avoid referencing the node_modules directory (prefer require.resolve)
➤ YN0000: └ Completed in 5.12s

➤ YN0000: Failed with errors in 5.12s

我們可以看到醫生發現了幾個合理的問題

  • testSequencer.js 依賴 @jest/test-sequencer,但未將其列為正確的相依性,這會在 Yarn Plug'n'Play 的執行階段報告為錯誤,因為沒有任何保證 @jest/test-sequencer 的版本會與套件測試時使用的版本相符。

  • webpack.config.js 參照一個載入器,但未透過 require.resolve 傳遞其名稱,這是不安全的,因為這表示載入器將相對於 webpack 套件解析,而不是 webpack-dev-server 的相依性。

  • contentBase-option.test.js 檢查 node_modules 資料夾的內容,而這在 Plug'n'Play 中將不再存在。

啟用 Yarn PnP

  1. .yarnrc.yml 檔案中尋找 nodeLinker 設定。
  2. 如果您找不到它,或它設定為 pnp,那麼一切都很好:您已經在使用 Yarn Plug'n'Play!
  3. 否則,請從您的設定檔中移除它並執行 yarn install
  4. 提交變更。

尋找事項

現在您應該有一個可運作的 Yarn Plug'n'Play 設定,但您的儲存庫可能仍需要一些額外的注意。一些需要記住的事項

  • 沒有 node_modules 資料夾。請改用 require.resolve
  • 沒有 .bin 資料夾。如果您依賴它們,請改用 yarn run bin
  • 將不在 scripts 欄位中的任何對 node 的呼叫,改用 yarn node
  • 現在需要手動呼叫自訂前掛勾(例如 prestart) (yarn prestart).

以下各節將說明所有這些內容,以及更多資訊。一般來說,我們建議您在這個時候嘗試執行應用程式並查看中斷的部分,然後在此處查看提示,以找出如何修正您的安裝。

編輯器支援

提示

我們在此僅介紹 VSCode,但我們有一個專用的 文件頁面,涵蓋更多 IDE!

警告

請確定 typescripteslintprettier、... 等通常由 IDE 擴充功能使用的所有相依性都列在專案的頂層(而不是在任意工作區中)。

  1. 安裝 ZipFS VSCode 擴充功能。
  2. 執行 yarn dlx @yarnpkg/sdks vscode 並提交變更。
  3. 對於 TypeScript,請別忘記在 VSCode 中選取 使用工作區版本

一般建議

使用 packageExtensions 修正相依性

套件有時會忘記列出其相依性。過去這曾造成許多細微問題,因此 Yarn 現在預設會防止此類不健全的存取。不過,只要您能以安全且可預測的方式進行作業,我們不希望它妨礙您完成工作,因此我們提出了 packageExtensions 設定。

例如,如果 react 忘記列出對 prop-types 的相依性,您可以這樣修正

packageExtensions:
"react@*":
dependencies:
prop-types: "*"

如果 Babel 外掛缺少對 @babel/core 的同儕相依性,您可以這樣修正

packageExtensions:
"@babel/plugin-something@*":
peerDependencies:
"@babel/core": "*"

您應該使用相依性還是同儕相依性?這取決於脈絡;根據經驗法則,如果套件是單例(例如 reactreact-redux,它也依賴於 React 脈絡),您會希望將它設為同儕相依性。在其他情況下,如果套件只是一組公用程式,使用一般相依性應該沒問題(例如 tsliblodash 等)。

使用 yarn run bin 而不是 node_modules/.bin 來呼叫二進位檔

node_modules/.bin 資料夾是實作細節,而 PnP 安裝根本不會產生它。與其依賴它的存在,不如直接使用 yarn run bin 指令,它可以啟動腳本和二進位檔

yarn run jest
# or, using the shortcut:
yarn jest

透過 yarn node 而不是 node 來呼叫您的腳本

現在我們需要將一些變數注入到環境中,讓 Node 能夠找到您的相依性。為了做到這一點,我們請您使用 yarn node,它會透明地執行繁重的任務。

注意:此部分僅適用於shell CLI。定義在 scripts 中的指令不受影響,因為我們會確保 node 永遠指向正確的位置,並已設定正確的變數。

設定 IDE 以支援 PnP

由於 Yarn Plug'n'Play 不會產生 node_modules 資料夾,某些 IDE 整合可能無法立即運作。查看我們的 指南,了解如何修復這些問題。

查看我們的端對端測試

我們現在每天執行 端對端測試,針對各種熱門 JavaScript 工具,以確保我們永不退步,或在第三方專案發布不相容變更時收到通知。

參閱這些測試的原始碼是查看使用特定工具鏈時是否必須設定某些特殊組態值的好方法。

疑難排解

找不到模組 [...]

這個錯誤並非來自 Yarn:它是 Node.js 解析程序所發出的,表示無法在磁碟上找到套件。

如果您已啟用 Plug'n'Play,則 Node.js 解析程序應將解析要求轉發給 Yarn,表示如果您收到這則訊息,表示轉發未發生,您的第一個動作應該是找出原因。

通常,這是因為您使用 node ./my-script 而不是 yarn node ./my-script 呼叫 Node.js 腳本。

套件嘗試存取 [...]

儘管很少見,但有些套件並未列出所有相依性。現在我們在相依性樹的各個分支之間強制執行界線,因此這類問題比以前更明顯(儘管它一直存在問題)。

長期的解決方案是提交上游拉取請求,將遺失的相依性新增至套件清單。由於有時需要一些時間才能合併,我們也提供了一個較短期的解決方案:在專案中建立 .yarnrc.yml,然後使用 packageExtensions 設定 將遺失的相依性新增至相關套件。執行 yarn install 套用變更,瞧!

如果您選擇在上游儲存庫開啟 PR,您也可以將套件延伸貢獻給我們的 plugin-compat 資料庫,幫助整個生態系統向前邁進。