Skip to content

Instantly share code, notes, and snippets.

@TheYarin
Last active July 18, 2020 18:12
Show Gist options
  • Save TheYarin/b44e8e9b6f33ca3f317900b8744b13c6 to your computer and use it in GitHub Desktop.
Save TheYarin/b44e8e9b6f33ca3f317900b8744b13c6 to your computer and use it in GitHub Desktop.
Using yarn for an offline environment setup, including a script that uses yarn to download packages and their dependencies as tgz archives. Compatible with git bash on windows.
#!/bin/bash
set -e
if [[ $# -eq 0 ]]; then
echo "Usage: $(basename $0) [packages ...]"
exit
fi
if ! command -v yarn &> /dev/null; then
echo "Failed: yarn is not installed"
exit 1
fi
yarnVersion="$(yarn -v)"
if [[ "$yarnVersion" != 1.* ]]; then
echo "Invalid yarn version - you should have yarn v1.*"
exit 1
fi
cacheDir="$(mktemp -d)"
oldCacheDir="$(yarn config get -s yarn-offline-mirror)"
tmpProjectFolder="$(mktemp -d)"
pushd . &> /dev/null
cd $tmpProjectFolder
function cleanup()
{
if [[ "$oldCacheDir" == "undefined" ]]; then
yarn config delete -s yarn-offline-mirror
else
yarn config set -s yarn-offline-mirror "$oldCacheDir"
fi
popd &> /dev/null
rm -rf "$tmpProjectFolder"
}
trap cleanup EXIT
yarn config set -s yarn-offline-mirror "$cacheDir" # Adds new setting to ~/.yarnrc
yarn init -y &> /dev/null # -s doesn't silence enough
yarn cache clean -s && echo "yarn cache cleared."
echo "Downloading..."
printf '\n\n'
yarn add $@
printf '\n\n'
echo "Download is complete. Your packages are waiting at $cacheDir"
echo "Don't forget to delete the folder after you're done with it."
if command -v explorer.exe &> /dev/null; then
cd $cacheDir
explorer.exe .
fi

I'm after a few hours of research, and these are my conclusions. The following was true today, 17/07/2020, with yarn v1.22.4/yarn 2 v2.1.1 (wtf is wrong with you, yarn devs? why don't I get yarn2 when installing yarn?)

Online side - getting those precious tgz's

On the online side, yarn v1 is useful for downloading npm packages with their dependencies included as tgz archives. This can be done by setting the following setting: nevermind, wrote a script that does everything for you.

Offline side - installing the damn packages:

You need to set up an NPM server (AKA registry). I tried getting around it, but there's no practical solution for that. I recommend Verdaccio, since it's easy to set up. (very docker-friendly!) (An important tip about Verdaccio)

Then, after properly configuring your new server to be your NPM repo, you can upload the tgz's from the online side by running:

npm publish --ignore-scripts package.tgz

Bonus: yarn 2 has a very cool feature that allows your project to not need the node_modules folder, and rely on a local cache of the (zipped, not tgzed) packages.
This way, it's a bit more sane to upload the packages to your source control, which can be very useful if your NPM server is flakey and you don't want to rely on it. You can read more about it here.
For that you'll need to set up a yarn 2 project (yarn init -2) at the online side so it'll download yarn2 into the project folder.

Further research

You might be able to use yarn v1's offline cache as a serverless npm repository. I didn't give this option a proper check yet.

An important tip about Verdaccio:

At the time of writing this, Verdaccio is not properly designed for a real offline environment, so it's still a bit flakey. More specifically, if any uplinks are configured, they must be available at all times, otherwise Verdaccio will bitch every time you try to install or publish a package, when you publish something that already exists in one of the uplinks, or if you don't have upload permission on the uplink (not 100% sure about that last one).
For a true, easy "offline NPM repository" experience, I recommend not messing with uplinks. if you have dependencies that are available from another NPM server, just use the script to download the desired packages from it and then publish them to your Verdaccio server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment