<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Yarn</title>
    <description>Fast, reliable, and secure dependency management.
</description>
    <link>https://yarnpkg.com/</link>
    <atom:link href="https://yarnpkg.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 27 Jan 2017 10:40:45 +0000</pubDate>
    <lastBuildDate>Fri, 27 Jan 2017 10:40:45 +0000</lastBuildDate>
    <generator>Jekyll v3.2.1</generator>
    
      <item>
        <title>Lockfiles should be committed on all projects</title>
        <description>&lt;p&gt;Yarn is a new package manager that we built to be consistent and reliable. When
installing hundreds or even thousands of third-party packages from the internet
you want to be sure that you’re executing the same code across every system.&lt;/p&gt;

&lt;p&gt;Yarn maintains consistency across machines in two key ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Yarn uses a deterministic algorithm that builds up the entire dependency tree
before placing files where they need to be.&lt;/li&gt;
  &lt;li&gt;Important info from the install process is stored in the &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; lockfile
so that it can be shared between every system installing the dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lockfile contains information about the exact versions of every single
dependency that was installed as well as checksums of the code to make sure the
code is identical.&lt;/p&gt;

&lt;p&gt;Yarn needs this info about every dependency because packages are constantly
changing. New versions of packages are published all the time and since
&lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; specifies version ranges you need to lock them down to a single
version.&lt;/p&gt;

&lt;p&gt;These version ranges exist because Yarn follows
&lt;a href=&quot;http://semver.org/&quot;&gt;Semantic Versioning&lt;/a&gt;, or “SemVer”. SemVer is a versioning
system designed around “breaking” or “non-breaking” changes.&lt;/p&gt;

&lt;p&gt;When you have a version such as &lt;code class=&quot;highlighter-rouge&quot;&gt;v1.2.3&lt;/code&gt;, it’s broken into three parts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Major (1.x.x)&lt;/strong&gt; – &lt;em&gt;Changes that may cause user code to break&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Minor (x.2.x)&lt;/strong&gt; – &lt;em&gt;Changes that add new features (but should not break user
code)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Patch (x.x.3)&lt;/strong&gt; – &lt;em&gt;Changes that are fixing bugs in previous versions (but
do not add new features and should not break user code)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a package publishes a new version, the author bumps major, minor, or patch
based on the changes that they have made as a way to communicate them.&lt;/p&gt;

&lt;p&gt;Users of packages should typically welcome minor and patch versions but should
be wary of major versions as they could break your code.&lt;/p&gt;

&lt;p&gt;Version ranges are a way of specifying which types of changes you want to
accept and which versions you want to prevent.  These version ranges then
resolve down to a single version which is either the version you have installed
or the latest published version that matches your version range.&lt;/p&gt;

&lt;p&gt;If you don’t store which version you ended up installing, someone could be
installing the same set of dependencies and end up with different versions
depending on when they installed. This can lead to “Works On My Machine”
problems and should be avoided.&lt;/p&gt;

&lt;p&gt;Also, since package authors are people and they can make mistake, it’s possible
for them to publish an accidental breaking change in a minor or patch version.
If you install this breaking change when you don’t intend to it could have bad
consequences like breaking your app in production.&lt;/p&gt;

&lt;p&gt;Lockfiles &lt;em&gt;lock&lt;/em&gt; the versions for every single dependency you have installed.
This prevents “Works On My Machine” problems, and ensures that you don’t
accidentally get a bad dependency.&lt;/p&gt;

&lt;p&gt;It also works as a security precaution: If the package author is either
malicious or is attacked by someone malicious and a bad version is published,
you do not want that code to end up running without you knowing about it.&lt;/p&gt;

&lt;h2 id=&quot;libraries-vs-applications&quot;&gt;Libraries vs Applications&lt;/h2&gt;

&lt;p&gt;There are two primary types of projects that use Yarn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Libraries&lt;/strong&gt; – &lt;em&gt;Projects that get published as packages to the registry and
installed by users. (i.e. React or Babel)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Applications&lt;/strong&gt; – &lt;em&gt;Projects that only consume other packages, typically
building some kind of product. (i.e. Your company’s app)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For applications, most developers agree that lockfiles are A Good Idea™.
But there has been some question about using them when building libraries.&lt;/p&gt;

&lt;p&gt;When you publish a package that contains a &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt;, any user of that
library will not be affected by it. When you install dependencies in your
application or library, only your own &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; file is respected. Lockfiles
within your dependencies will be ignored.&lt;/p&gt;

&lt;p&gt;It is important that Yarn behaves this way for two reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You would never be able to update the versions of sub-dependencies because
they would be locked by other &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; files.&lt;/li&gt;
  &lt;li&gt;Yarn would never be able to fold (de-duplicate) dependencies so that
compatible version ranges only install a single version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some have wondered why libraries should use lockfiles at all if they do not and
should not affect users. Even further, some have said that using lockfiles when
developing libraries creates a &lt;em&gt;false sense of security&lt;/em&gt; since your users could
be installing different versions than you.&lt;/p&gt;

&lt;p&gt;This seems to logically makes sense, but let’s dive deeper into the problem.&lt;/p&gt;

&lt;h2 id=&quot;development-dependencies&quot;&gt;Development Dependencies&lt;/h2&gt;

&lt;p&gt;So far we’ve been talking about dependencies as if there were only one type of
dependency when in fact there are several different types. These are broken
down into two categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Runtime&lt;/strong&gt; – &lt;em&gt;Dependencies that are used by the project’s code and needed
when the code is run.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Development&lt;/strong&gt; – &lt;em&gt;Dependencies that are only needed to work directly on the
project&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a library is installed by a user, only the runtime dependencies are
installed. The development dependencies are only ever installed when working
directly on the project that specifies them.&lt;/p&gt;

&lt;p&gt;Each type of dependency creates a whole tree of dependencies which are needed
for them to be used.&lt;/p&gt;

&lt;p&gt;It turns out that most projects (libraries or applications) have far more
dependencies for development than for runtime. The tree of dependencies created
by a projects development dependencies is almost always the largest part of the
total.&lt;/p&gt;

&lt;p&gt;You can blame this on how frustratingly complicated JavaScript development is,
but it seems to hold true across every ecosystem. You almost always need more
code to develop projects than you need to run them.&lt;/p&gt;

&lt;p&gt;When working on a library, it is far more likely that a development dependency
breaks just because there are more of them that &lt;em&gt;could&lt;/em&gt; break.&lt;/p&gt;

&lt;h2 id=&quot;the-breaking-change-race&quot;&gt;The Breaking Change Race&lt;/h2&gt;

&lt;p&gt;When a package accidentally publishes a breaking change it starts the clock on
who will be the first person to catch it. Whoever installs that breaking change
first will (most likely) be the first to discover it.&lt;/p&gt;

&lt;p&gt;Let’s &lt;em&gt;imagine&lt;/em&gt; we have a package called &lt;code class=&quot;highlighter-rouge&quot;&gt;left-pad&lt;/code&gt; which takes a string and
adds a specified amount of padding in front of it. This small and seemingly
harmless package is used by a really big project, which we’ll just call…
Babel.&lt;/p&gt;

&lt;p&gt;One day, the maintainer of  &lt;code class=&quot;highlighter-rouge&quot;&gt;left-pad&lt;/code&gt;  decides they are going to do something
unspeakably evil and make it pad the right side instead. They publish it as a
patch version which quickly spreads to everyone using it.&lt;/p&gt;

&lt;p&gt;Remember, Babel is a really huge project with tens of thousands of users and
dozens of contributors. Let’s try and figure out who will catch the padding
fiasco first.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Looking at build history, Babel was installed in CI (with the &lt;code class=&quot;highlighter-rouge&quot;&gt;left-pad&lt;/code&gt;
dependency) exactly &lt;strong&gt;103 times&lt;/strong&gt; in the last 30 days.&lt;/li&gt;
  &lt;li&gt;Looking at statistics from the registry, Babel was installed (with
&lt;code class=&quot;highlighter-rouge&quot;&gt;left-pad&lt;/code&gt;) by users over &lt;strong&gt;5.5 Million times&lt;/strong&gt; in the same 30 days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To put that in a different measurement:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Contributors install Babel on average &lt;strong&gt;every 7 hours&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Users install Babel about on average &lt;strong&gt;every 0.5 seconds&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the &lt;code class=&quot;highlighter-rouge&quot;&gt;left-pad&lt;/code&gt; incident happened, users discovered it almost immediately.
Notifying the Babel contributors via GitHub issues, tweets, Facebook messages,
emails, phone calls, smoke signals, and by carrier pigeon.&lt;/p&gt;

&lt;p&gt;Babel contributors couldn’t possibly prevent users from being affected by every
error. In order to do so, every 0.5 seconds they would need to be able to run
CI, notice the error, find a fix, publish a new version, and get every user to
upgrade. There’s just no way to make this happen.&lt;/p&gt;

&lt;p&gt;This might seem like a bit too extreme of an example to apply broadly, but the
reasoning stays the same just with different numbers. Libraries should always
be installed more frequently by users than by contributors. If that isn’t true,
it’s because no one uses that library anyways– and we should not be optimizing
our workflow around code that no one uses.&lt;/p&gt;

&lt;h2 id=&quot;user-testing&quot;&gt;User testing&lt;/h2&gt;

&lt;p&gt;Many library developers work very hard to maintain a test suite that has 100%
code coverage. This coverage ensures that every single line of code is run at
least once during the tests.&lt;/p&gt;

&lt;p&gt;But it still does not catch everything. If a library has even a small number of
users, it will be far better tested by the users than it will be by any test
suite the contributors can come up with.&lt;/p&gt;

&lt;p&gt;Users just write more code, and the code they write is not always what a
library author will expect. The more popular the library the more edge cases
users will find. Users will do things that you didn’t even think was possible–
it will &lt;em&gt;horrify&lt;/em&gt; you. It will make you question the goodness of humanity.&lt;/p&gt;

&lt;p&gt;Even if a contributor happened to beat users to finding a breaking change,
there’s a pretty decent chance they won’t catch it anyways. Untested edge cases
are the most likely things to break.&lt;/p&gt;

&lt;h2 id=&quot;the-contributors-burden&quot;&gt;The contributor’s burden&lt;/h2&gt;

&lt;p&gt;Now let’s talk a bit about the social side of not using lockfiles in libraries.&lt;/p&gt;

&lt;p&gt;As mentioned previously, the majority of breaking changes that occur in library
dependencies will be development dependencies.&lt;/p&gt;

&lt;p&gt;Some percentage of these breaking changes will be caught and (hopefully) fixed
by regular contributors. However, the remaining breaking changes will be caught
by new or infrequent contributors.&lt;/p&gt;

&lt;p&gt;Contributing to a project for the first time is a very intimidating experience
for anyone who is not an open source veteran. If the first thing a potential
new contributor runs into is a broken build or test suite, they could be so
intimidated that they decide to forget about contributing back.&lt;/p&gt;

&lt;p&gt;Even as someone who contributes to lots of open source projects, it’s a
terrible thing to have to debug a build system for a few hours when you just
want to fix a bug or add a small feature to a library.&lt;/p&gt;

&lt;h2 id=&quot;the-users-burden&quot;&gt;The user’s burden&lt;/h2&gt;

&lt;p&gt;Of course not every breaking change is a development dependency, and
theoretically contributors &lt;em&gt;could&lt;/em&gt; catch breaking changes before users notice
them. In that (narrow) scenario, aren’t we shifting the burden from
contributors to users?&lt;/p&gt;

&lt;p&gt;First, it’s not going to be every user that is affected by this. It’s well
agreed upon that applications should be using lockfiles, and if they are then
they won’t be affected by sudden breaking changes.&lt;/p&gt;

&lt;p&gt;We’re only talking about users that are either installing a package for the
first time, or are upgrading the versions of their dependencies.&lt;/p&gt;

&lt;p&gt;For users upgrading their dependencies, they should be trained to look out for
breaking changes and if they encounter one, to roll back the version to a
working state and open an issue in the library.&lt;/p&gt;

&lt;p&gt;The only really negative experience that we are adding is for new users. Which
is admittedly terrible, you want new users to have the best possible
experience.&lt;/p&gt;

&lt;p&gt;But remember that they already face this burden in the majority of cases. It’s
only when contributors could have caught breaking changes before users
experienced them that we are now placing an additional burden on new users.&lt;/p&gt;

&lt;p&gt;It’s also important to note that new users make up a minority of the total
installations. The majority of the time it will be existing users that are the
first to catch breaking changes because they are the ones installing a library
the most.&lt;/p&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In Closing&lt;/h2&gt;

&lt;p&gt;There is a simple universal rule that everyone should follow with Yarn: If you
are installing a new dependency or upgrading an existing one you should check
to make sure the package works as intended and is not breaking your code.&lt;/p&gt;

&lt;p&gt;You should follow that rule regardless of what your libraries are doing.&lt;/p&gt;

&lt;p&gt;Without lockfiles it gets even more complicated: In applications or libraries,
if there is no lockfile, you will have to check the dependencies every time you
install or re-install them and make sure that everything still works. Otherwise
the build might be broken or the tests might fail. You could break something
without even realizing it. You could run into situations where code works on
your machine but no one else’s.&lt;/p&gt;

&lt;p&gt;The idea that not using lockfiles in libraries somehow saves users from
encountering breaking changes is at best extremely rare and at worst is never
true.&lt;/p&gt;

&lt;p&gt;By not using lockfiles in libraries, the only tangible thing you accomplish is
making the project harder to contribute to.&lt;/p&gt;

&lt;p&gt;We should work as a community to keep all of our libraries up to date. We
should go out and build tooling for automatically upgrading dependencies that
makes it painless to do. There has been attempts at such tooling before, but we
can do better.&lt;/p&gt;

&lt;p&gt;Please commit your &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; files.&lt;/p&gt;
</description>
        <pubDate>Thu, 24 Nov 2016 08:00:00 +0000</pubDate>
        <link>https://yarnpkg.com/blog/2016/11/24/lockfiles-for-all</link>
        <guid isPermaLink="true">https://yarnpkg.com/blog/2016/11/24/lockfiles-for-all</guid>
        
        
        <category>announcements</category>
        
      </item>
    
      <item>
        <title>Running Yarn offline</title>
        <description>&lt;p&gt;Repeatable and reliable builds for large JavaScript projects  are vital.
If your builds depend on dependencies being downloaded from network, this build system is neither repeatable nor reliable.&lt;/p&gt;

&lt;p&gt;One of the main advantages of Yarn is that it can install node_modules from files located in file system.
We call it “Offline Mirror” because it mirrors the files downloaded from registry during the first build and stores them locally for future builds.&lt;/p&gt;

&lt;p&gt;“Offline mirror” is different from cache that both npm CLI and Yarn have.
Caches store already unzipped tarballs downloaded from registry, they also can be implementation specific and may be invalid between multiple versions of CLI tools.
The tarballs in “Offline mirror” can be consumed by any version Yarn that will build cache based on them.
It is also easier to store files when they are compressed.&lt;/p&gt;

&lt;h2 id=&quot;lets-set-up-offline-mirror-for-a-simple-js-project&quot;&gt;Let’s set up “Offline mirror” for a simple JS project&lt;/h2&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;yarn-offline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;index.js&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;MIT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;is-array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;left-pad&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.1.3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;mime-types&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^2.1.13&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When you run &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn install&lt;/code&gt;, the generated &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; file has sections for every dependency:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# yarn lockfile v1&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;is-array@^1.0.1&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.0.1&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved &quot;https://registry.yarnpkg.com/is-array/-/is-array-1.0.1.tgz#e9850cc2cc860c3bc0977e84ccf0dd464584279a&quot;&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;left-pad@^1.1.3&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.1.3&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved &quot;https://registry.yarnpkg.com/left-pad/-/left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a&quot;&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;mime-db@~1.25.0&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.25.0&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved &quot;https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392&quot;&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;mime-types@^2.1.13&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;2.1.13&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved &quot;https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;mime-db &quot;~1.25.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each of these dependencies have a &lt;code class=&quot;highlighter-rouge&quot;&gt;resolved&lt;/code&gt; field with a remote URL. If you delete your &lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; folder and run &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn install&lt;/code&gt; again, Yarn will download the same resolved dependencies specified in this lockfile.
It will even guarantee that no one modified the files since your first installs by verifying checksum for each of them.&lt;/p&gt;

&lt;p&gt;However, if for some reason these urls are unreachable during your build, it will fail. To solve this, we’ll need an “Offline mirror”.&lt;/p&gt;

&lt;h3 id=&quot;set-up-yarnrc&quot;&gt;Set up .yarnrc&lt;/h3&gt;

&lt;p&gt;First we need to setup a directory to be our “Offline mirror” storage, we can do that with &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn config&lt;/code&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;yarn config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;yarn-offline-mirror ./npm-packages-offline-cache
yarn config v0.17.8
success Set &lt;span class=&quot;s2&quot;&gt;&quot;yarn-offline-mirror&quot;&lt;/span&gt; to &lt;span class=&quot;s2&quot;&gt;&quot;./npm-packages-offline-cache&quot;&lt;/span&gt;.
✨  Done &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.06s.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;./npm-packages-offline-cache&lt;/code&gt; is an example location relative to home folder where all the source&lt;code class=&quot;highlighter-rouge&quot;&gt; .tar.gz&lt;/code&gt; files will be downloaded to from the registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will create a .yarnrc file in your HOME directory.
Let’s move this file to the project root so that offline mirror would be used only for this project.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;mv ~/.yarnrc ./
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;initialize-the-new-lockfile&quot;&gt;Initialize the new lockfile&lt;/h3&gt;

&lt;p&gt;Remove node_modules and yarn.lock that were generated previously and run yarn install again:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;rm -rf node_modules/ yarn.lock
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;yarn install
yarn install v0.17.8
info No lockfile found.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1/4] 🔍  Resolving packages...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2/4] 🚚  Fetching packages...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3/4] 🔗  Linking dependencies...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.57s.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The dependency resolutions in your &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; should now look like this:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# yarn lockfile v1&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;is-array@^1.0.1&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.0.1&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved is-array-1.0.1.tgz#e9850cc2cc860c3bc0977e84ccf0dd464584279a&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;left-pad@^1.1.3&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.1.3&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;mime-db@~1.25.0&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;1.25.0&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;mime-types@^2.1.13&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;version &quot;2.1.13&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;resolved mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;mime-db &quot;~1.25.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;resolved&lt;/code&gt; field for each resolution should now contain file names relative to the &lt;code class=&quot;highlighter-rouge&quot;&gt;npm-packages-offline-cache&lt;/code&gt;  folder that was configured earlier.
Each &lt;code class=&quot;highlighter-rouge&quot;&gt;resolved&lt;/code&gt; dependency also contains a checksum after the file name to ensure that no one mangles with the downloaded files.&lt;/p&gt;

&lt;p&gt;And inside the “Offline mirror” folder we have the .tgz files that yarn will use for the following builds without reaching out to network.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;ls npm-packages-offline-cache/
is-array-1.0.1.tgz    left-pad-1.1.3.tgz    mime-db-1.25.0.tgz    mime-types-2.1.13.tgz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;In a nutshell, to enable “Offline mirror” for your project you need:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;add “yarn-offline-mirror” configuration to .yarnrc file&lt;/li&gt;
    &lt;li&gt;generate a new yarn.lock with “yarn install” command&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;a-few-tips-and-tricks&quot;&gt;A few tips and tricks&lt;/h2&gt;

&lt;h3 id=&quot;you-can-check-in-offline-mirror-into-git-or-mercurial-repository&quot;&gt;You can check in “Offline mirror” into git or mercurial repository&lt;/h3&gt;

&lt;p&gt;The “Offline Mirror” can be shared between build servers or development machines in any way that is convenient: a Dropbox folder, stored in source control or on a network drive. At Facebook the offline mirror lives inside of our big Mercurial “monorepo”.&lt;/p&gt;

&lt;p&gt;Whether to commit binary files into a repository or not depends on the number and size of your project’s dependencies.
For example, out of 849 React Native dependencies totaling 23MB, only 10% are larger than 30KB.
&lt;img src=&quot;/assets/posts/2016-11-24-offline-mirror/yarn-offline-blog-offline-mirror-list.png&quot; alt=&quot;list of React Native .tgz files sorted by size descending&quot; style=&quot;max-width: 700px&quot; /&gt;
&lt;img src=&quot;/assets/posts/2016-11-24-offline-mirror/yarn-offline-blog-offline-mirror-size.png&quot; alt=&quot;Size of all .tgz files used in React Native&quot; style=&quot;max-width: 700px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Many Facebook teams, including the React Native team, decided to check in their “Offline mirror”.
They all share the same “Offline mirror” which means that most dependencies for new projects are often already checked into that folder, so the cost of storing the packages in source control gets lower the more projects use it.&lt;/p&gt;

&lt;h3 id=&quot;lets-compare-checking-in-nodemodules-to-checking-in-offline-mirror&quot;&gt;Let’s compare checking in node_modules to checking in “Offline mirror”&lt;/h3&gt;

&lt;p&gt;The React Native team used to check in the &lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; folder but they hit several limits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; contains more than 37,000 files (and more than 100,000 files back when we were using npm2). This had a bad performance impact on our Mercurial repository.&lt;/li&gt;
  &lt;li&gt;Reviewing Pull Requests that changed a dependency was quite hard as all the files in &lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; that were added and removed created a ton of noise, making code reviews unpleasant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In comparison, updating a third-party dependency with the Offline Mirror adds just a few files that are very easy to review:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;yarn add shelljs@0.7.0 --dev
yarn add v0.17.8
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1/4] 🔍  Resolving packages...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2/4] 🚚  Fetching packages...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3/4] 🔗  Linking dependencies...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 4 new dependencies.
├─ interpret@1.0.1
├─ rechoir@0.6.2
└─ shelljs@0.7.0
│  └─ glob@7.1.1
✨  Done &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;8.15s.

&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;git diff
diff --git a/package.json b/package.json
index 4619f16..7acb42f 100644
--- a/package.json
+++ b/package.json
@@ -220,7 +220,7 @@
     &lt;span class=&quot;s2&quot;&gt;&quot;mock-fs&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;^3.11.0&quot;&lt;/span&gt;,
     &lt;span class=&quot;s2&quot;&gt;&quot;portfinder&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;0.4.0&quot;&lt;/span&gt;,
     &lt;span class=&quot;s2&quot;&gt;&quot;react&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;~15.3.1&quot;&lt;/span&gt;,
-    &lt;span class=&quot;s2&quot;&gt;&quot;shelljs&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;0.6.0&quot;&lt;/span&gt;,
+    &lt;span class=&quot;s2&quot;&gt;&quot;shelljs&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;0.7.0&quot;&lt;/span&gt;,
     &lt;span class=&quot;s2&quot;&gt;&quot;sinon&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;^2.0.0-pre.2&quot;&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
diff --git a/yarn.lock b/yarn.lock
index 11ce116..f5d81ba 100644
--- a/yarn.lock
+++ b/yarn.lock
...
-shelljs@0.6.0:
-  version &lt;span class=&quot;s2&quot;&gt;&quot;0.6.0&quot;&lt;/span&gt;
-  resolved shelljs-0.6.0.tgz#ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec
+shelljs@0.7.0:
+  version &lt;span class=&quot;s2&quot;&gt;&quot;0.7.0&quot;&lt;/span&gt;
+  resolved shelljs-0.7.0.tgz#3f6f2e4965cec565f65ff3861d644f879281a576
+  dependencies:
+    glob &lt;span class=&quot;s2&quot;&gt;&quot;^7.0.0&quot;&lt;/span&gt;
+    interpret &lt;span class=&quot;s2&quot;&gt;&quot;^1.0.0&quot;&lt;/span&gt;
+    rechoir &lt;span class=&quot;s2&quot;&gt;&quot;^0.6.2&quot;&lt;/span&gt;

 shellwords@^0.1.0:
   version &lt;span class=&quot;s2&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;git status
On branch testing-yarn
Changes not staged &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;commit:
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git add &amp;lt;file&amp;gt;...&quot;&lt;/span&gt; to update what will be committed&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git checkout -- &amp;lt;file&amp;gt;...&quot;&lt;/span&gt; to discard changes &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;working directory&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    modified:   package.json
    modified:   yarn.lock

Untracked files:
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git add &amp;lt;file&amp;gt;...&quot;&lt;/span&gt; to include &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;what will be committed&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    yarn-offline-mirror/interpret-1.0.1.tgz
    yarn-offline-mirror/rechoir-0.6.2.tgz
    yarn-offline-mirror/shelljs-0.7.0.tgz

no changes added to commit &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git add&quot;&lt;/span&gt; and/or &lt;span class=&quot;s2&quot;&gt;&quot;git commit -a&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;did-you-know-that-yarn-is-also-distributed-as-a-single-bundle-js-file-in-releaseshttpsgithubcomyarnpkgyarnreleases-that-can-be-used-on-ci-systems-without-internet-access&quot;&gt;Did you know that Yarn is also distributed as a single bundle JS file in &lt;a href=&quot;https://github.com/yarnpkg/yarn/releases&quot;&gt;releases&lt;/a&gt; that can be used on CI systems without internet access?&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/2016-11-24-offline-mirror/yarn-offline-blog-releases.png&quot; alt=&quot;Files distributed with Yarn releases&quot; style=&quot;max-width: 700px&quot; /&gt;
**yarn-&lt;version&gt;.js** (for Node 5+) and **yarn-legacy-&lt;version&gt;.js** (for Node 4) can be used stand-alone in CI systems without a need to install it.&lt;/version&gt;&lt;/version&gt;&lt;/p&gt;

&lt;p&gt;Just check it into your project’s repository and use it in the build script:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;rougeHighlight&quot;&gt;&lt;code&gt;node ./yarn-0.17.8.js install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is quite convenient for teams that use multiple operating systems and want to have atomic updates for Yarn.&lt;/p&gt;

&lt;h3 id=&quot;this-is-going-to-get-better&quot;&gt;This is going to get better&lt;/h3&gt;

&lt;p&gt;The “Offline mirror” was implemented early in Yarn’s development cycle and we are working on improving it in a backwards compatible way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;resolved&lt;/code&gt; field is used both for offline mirror paths and registry URIs. This means that the &lt;code class=&quot;highlighter-rouge&quot;&gt;yarn.lock&lt;/code&gt; file that React Native team uses internally can’t be shared with the open source community because the React Native team does not sync the offline mirror with the open source version of React Native. &lt;a href=&quot;https://github.com/yarnpkg/yarn/issues/394&quot;&gt;Issue&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;There is an &lt;a href=&quot;https://github.com/yarnpkg/yarn/issues/393&quot;&gt;improved workflow being considered&lt;/a&gt; for future versions of Yarn. It is not drastically different but some settings and lock files may change.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 24 Nov 2016 08:00:00 +0000</pubDate>
        <link>https://yarnpkg.com/blog/2016/11/24/offline-mirror</link>
        <guid isPermaLink="true">https://yarnpkg.com/blog/2016/11/24/offline-mirror</guid>
        
        
        <category>announcements</category>
        
      </item>
    
      <item>
        <title>Yarn: A new package manager for JavaScript</title>
        <description>&lt;p&gt;We’re pleased to announce the open source release of Yarn, a collaboration between Facebook, Exponent, Google, and Tilde. With Yarn, engineers still have access to the npm registry, but can install packages more quickly and manage dependencies consistently across machines or in secure offline environments. Yarn enables engineers to move faster and with confidence when using shared code so they can focus on what matters — building new products and features. Read the full announcement on &lt;a href=&quot;https://code.facebook.com/posts/1840075619545360&quot;&gt;code.facebook.com&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 11 Oct 2016 08:00:00 +0000</pubDate>
        <link>https://yarnpkg.com/blog/2016/10/11/introducing-yarn</link>
        <guid isPermaLink="true">https://yarnpkg.com/blog/2016/10/11/introducing-yarn</guid>
        
        
        <category>announcements</category>
        
      </item>
    
  </channel>
</rss>
