背景
Yarn v2についての動画で出てきた「v1のオフラインインストール」について、よく知らなかったので調べてみた。
概要
Yarnのオフラインインストールとは、パッケージを追加する際に実態のtarballをローカルにダウンロードしておき、後からそれを用いてパッケージをインストール出来るようにしたものである。パッケージをインストールする際に yarn.lock
ファイルにダウンロード元のURLが記録されているため、URLが有効な限りは何度実行しても同一のファイルがダウンロードされることが保証されるが、ダウンロード元のダウンや閉鎖等によってURLが無効になった場合はダウンロードに失敗する。このような場合に備えて予めtarballをダウンロードしておき、オフライン時に利用するのがオフラインインストールである。
詳解
事前準備
まずはじめに、適当なディレクトリを作成して以下のファイルを配置する。
{
"name": "yarn-offline",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"is-array": "^1.0.1",
"left-pad": "^1.3.0",
"mime-types": "^2.1.27"
}
}
パッケージを追加し、ディレクトリの構成が以下の通りになっていることを確認する。
$ yarn
(略)
$ ls
node_modules package.json yarn.lock
オフラインミラーの設定
オフラインミラー(ダウンロードされるtarballが配置されるパス)を設定する。ここで指定するパスはホームディレクトリからの相対パスであることに留意する。
$ yarn config set yarn-offline-mirror ./npm-packages-offline-cache
yarn config v1.22.0
success Set "yarn-offline-mirror" to "./npm-packages-offline-cache".
✨ Done in 0.04s.
$ yarn config set yarn-offline-mirror-pruning true
yarn config v0.23.2
success Set "yarn-offline-mirror-pruning" to "true".
✨ Done in 0.06s.
yarn config set
で追加した設定は ~/.yarnrc
に記録されている。これを特定のプロジェクトでのみ利用可能にするため、ファイルをプロジェクトディレクトリ内に移動する。
$ mv ~/.yarnrc ./
パッケージのダウンロード
オフラインインストールを用いる場合でも、yarn.lock
は変更されないためパッケージ管理に影響を及ぼさない。これを検証するためにファイルをコピーしておく。
$ cp yarn.lock yarn.lock.before
node_modules/
と yarn.lock
を削除して再度パッケージの追加を行う。その後、~/npm-packages-offline-cache
にtarballがダウンロードされていることを確認する。
$ rm -rf node_modules/ yarn.lock
$ yarn
yarn install v1.22.4
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
✨ Done in 0.52s.
$ ls ~/npm-packages-offline-cache
is-array-1.0.1.tgz left-pad-1.3.0.tgz mime-db-1.44.0.tgz mime-types-2.1.27.tgz
yarn.lock
が変更されていないことを確認する。
$ diff yarn.lock yarn.lock.before
$ rm yarn.lock.before
オフラインインストールの実行
オフラインインストールの検証を行うため、node_modules/
とキャッシュを削除する。
$ rm -rf node_modules/
$ yarn cache clean
yarn cache v1.22.4
success Cleared cache.
✨ Done in 0.10s.
ネットワークを切断してオフラインにする。続けて yarn --offline
を実行し、オフライン時でもパッケージが追加できることを確認する。
thara@ht-mbp-2:yarn-offline $ ls
package.json yarn.lock
thara@ht-mbp-2:yarn-offline $ yarn --offline
yarn install v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
✨ Done in 0.55s.
thara@ht-mbp-2:yarn-offline $ ls
node_modules package.json yarn.lock
検証
上記に続けて、ダウンロード済みtarball、キャッシュ、yarn.lock
の関係について検証する。
オフラインインストールはキャッシュが無い場合に行われる
オフラインインストール時のパッケージとしてダウンロード済みtarballが用いられたように思えるがこれは正確ではない。キャッシュにもtarballが存在しており、こちらが優先して用いられるため「キャッシュが無ければダウンロード済みtarballが用いられる」という説明が正しい。以下を実行し、~/npm-packages-offline-cache
が存在しなくともオフラインインストールに成功することを確認する。
$ rm -rf node_modules/
$ mv ~/npm-packages-offline-cache ~/npm-packages-offline-cache-renamed
$ yarn --offline
yarn install v1.22.4
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
✨ Done in 0.28s.
キャッシュとダウンロード済みtarballの両方が存在しなければ、当然オフラインインストールは失敗する。
$ rm -rf node_modules/
$ yarn cache clean
yarn cache v1.22.4
success Cleared cache.
✨ Done in 0.05s.
$ yarn --offline
yarn install v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
error Can't make a request in offline mode ("https://registry.yarnpkg.com/is-array/-/is-array-1.0.1.tgz")
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
ダウンロード済みパッケージの検証には yarn.lock
が用いられる
~/npm-packages-offline-cache
を元に戻し、yarn.lock
を削除してオフラインインストールに失敗することを確認する。yarn.lock
が存在しない場合は、インストールするべきパッケージの検証が出来ないためである。
$ mv ~/npm-packages-offline-cache-renamed/ ~/npm-packages-offline-cache
$ rm yarn.lock
$ yarn --offline
yarn install v1.22.4
info No lockfile found.
[1/4] 🔍 Resolving packages...
error An unexpected error occurred: "There should only be one folder in a package cache (got in /Users/thara/.cache/yarn/v6/npm-is-array-1.0.1-e9850cc2cc860c3bc0977e84ccf0dd464584279a-integrity/node_modules)".
info If you think this is a bug, please open a bug report with the information provided in "/Users/thara/Desktop/yarn-offline/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
キャッシュが存在する場合は yarn.lock
は不要である
端末をオンライン状態にし、パッケージを追加してキャッシュを作成する。
$ yarn
yarn install v1.22.4
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
✨ Done in 0.57s.
$ yarn cache list
yarn cache v1.22.4
Name Version Registry Resolved
is-array 1.0.1 npm https://registry.yarnpkg.com/is-array/-/is-array-1.0.1.tgz#e9850cc2cc860c3bc0977e84ccf0dd464584279a
left-pad 1.3.0 npm https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e
mime-db 1.44.0 npm https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92
mime-types 2.1.27 npm https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f
✨ Done in 0.04s.
端末をオフライン状態にして node_modules/
と yarn.lock
を削除し、オフラインインストールに成功することを確認する。
$ rm -rf node_modules/ yarn.lock
$ yarn --offline
yarn install v1.22.4
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
✨ Done in 0.40s.