Exec 協定
exec:
協定會在取得時於暫存目錄中執行 Node.js 指令碼,並使用預先設定的執行時間環境。然後,此指令碼預期會填入環境中定義的特殊目錄,並在產生完成後結束。
您為何需要
典型的 Yarn 取得器會從網際網路下載套件 - 如果您想使用的專案事先已打包,這樣做會很順利,但只要您需要自行打包,就會失敗。Yarn 的內建機制允許您在相容的 git 儲存庫上執行 prepare
指令碼,並將結果用作最終套件,但即使這樣也不總是足夠 - 您可能需要複製特定分支、進入特定目錄、執行特定建置指令碼 ... 所有這些事情都讓我們難以支援每一個使用案例。
exec:
協定表示一種方法,讓您自行定義如何取得指定的套件。在某種意義上,它可以被視為 Yarn 提供的 取得器 API 的更高級版本。
產生器指令碼和 require
由於產生器會在非常特殊的環境中被呼叫(在任何套件已安裝在磁碟上之前),它將無法呼叫 require
函式(即使使用相對路徑)。如果您需要非常複雜的產生器,只需使用 Webpack 或 Rollup 等工具將它們事先打包在單一指令碼中。
由於此限制,且產生器幾乎總是需要使用 Node 內建模組,因此這些模組會在全域範圍內提供 - 與 Node REPL 已執行的操作方式非常類似。因此,無需手動要求 fs
模組:它可透過全域 fs
變數取得!
執行時間環境
為了讓腳本了解產生程序中涉及的各種預定義資料夾,Yarn 將注入一個腳本可用的特殊 execEnv
全域變數。此物件的 介面 定義如下
屬性 | 類型 | 說明 |
---|---|---|
tempDir | 字串 | 腳本可自由使用的空暫存目錄的絕對路徑。在呼叫腳本之前自動建立。 |
buildDir | 字串 | 腳本預期會產生封裝檔案的空目錄的絕對路徑。在呼叫腳本之前自動建立。 |
locator | 字串 | 識別產生器封裝的字串化 定位器。 |
您可以在 execEnv.tempDir
中執行任何您想做的事,但在執行結束時,Yarn 會預期 execEnv.buildDir
包含可壓縮成封存檔並儲存在快取中的檔案。
範例
產生 hello world 封裝
fs.writeFileSync(path.join(execEnv.buildDir, 'package.json'), JSON.stringify({
name: 'hello-world',
version: '1.0.0',
}));
fs.writeFileSync(path.join(execEnv.buildDir, 'index.js'), `
module.exports = 'hello world!';
`);
複製單一儲存庫並建置特定封裝
const pathToRepo = path.join(execEnv.tempDir, 'repo');
const pathToArchive = path.join(execEnv.tempDir, 'archive.tgz');
const pathToSubpackage = path.join(pathToRepo, 'packages/foobar');
// Clone the repository
child_process.execFileSync(`git`, [`clone`, `git@github.com:foo/bar`, pathToRepo]);
// Install the dependencies
child_process.execFileSync(`yarn`, [`install`], {cwd: pathToRepo});
// Pack a specific workspace
child_process.execFileSync(`yarn`, [`pack`, `--out`, pathToArchive], {cwd: pathToSubpackage});
// Send the package content into the build directory
child_process.execFileSync(`tar`, [`-x`, `-z`, `--strip-components=1`, `-f`, pathToArchive, `-C`, execEnv.buildDir]);