2020-09-14
|~3 min read
|598 words
If you ever find yourself in a situation where it makes more sense to use Yarn pack
than link
, you may want to know what it is and how it works.
That’s what this page is about!
In theory, pack
should work just like link
. Where link
creates a symlink to a project’s build directory, pack
creates a gzip of the package dependencies.
Whereas for a linked package a project would point to it with yarn link <package>
, with a packed package, there’s no symlink to point to. Instead, it will be added just like another dependency.
So, what are the actual steps to get a packed package working as an alternative to a linked one? The steps are split between work done within the package to be packed (library
) and the consuming application (app
).
In the package.json
of your library
, update the package version to a unique number. This is done to avoid conflicting with a version that already exists in the yarn cache
for app
:
{
"name": "my-awesome-libary",
- "version": "1.0.0",
+ "version": "0.0.10001",
"main": "dist/main.js",
"scripts": {
"build": "webpack",
}
}
Note: Yarn uses SemVer which can end up trimming leading zeroes. For example, 0.0.0003
is the same as 0.0.3
. So, when creating unique version numbers, keep this in mind.
Run the script to produce the bundle (e.g., yarn build
)
Navigate a terminal session to the root of the library
project and create a gzip with yarn pack
cd ~/code/library
yarn pack
yarn pack v1.22.4
success Wrote tarball to "~/code/library/my-awesome-libary-v0.0.10001.tgz".
Copy the file path to your clipboard.
Navigate to the app
directory:
cd ~/code/app
Using the file path as the name of the package, add it as a dependency:
yarn add ~/code/library/my-awesome-libary-v0.0.10001.tgz
Run yarn
again. (Note: This step should not be necessary, but seems to help clear out any cache).
Confirm that the package was updated to the local gzip. This can be done in two ways:
app/yarn.lock
, if you find the dependency for my-awesome-library
, it should resolve to the local file path:"my-awesome-library@file:../library/my-awesome-library-v0.0.10001.tgz":
version "0.0.10001"
resolved "file:../library/my-awesome-library-v0.0.10001.tgz#e37e975e51c5ce9863891eaf50395070bed10146"
app/package.json
, the dependency will include the file path, not just the version number:{
"dependencies": {
"my-awesome-library": "~/code/library/my-awesome-library-v0.0.10001.tgz"
}
}
After completing all of these steps, if you run the app locally, you should be pulling in the locally referenced build.
When linking a project, it’s common that you will need to return to the library project, make some changes, and rebuild. Because of link
’s symlink, those changes are automatically reflected in the app
. That’s no longer the case with packed projects. When a project is packed, its bundle is static. In order to see the newly updated changes, repeat the steps for packing.
Compared with link
, pack
feels like a heavy process. There are additional steps that don’t provide much additional value. So why use it?
For one, as was demonstrated in this particular instance: it works where link
doesn’t.
It’s also well suited for situations where it is easier to reference a gzip than build a link locally. Say you want to test a branch of a project that was built through a deployment pipeline. If the build pipeline exposes a URL to the bundle, you can add that version as a dependency rather than the published version, just like we did above when we used the local URL.
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!