Skip to content

Breaking Changes

Jonathan Cammisuli edited this page Dec 4, 2019 · 4 revisions

This document defines what constitutes a breaking change in Nx.

Background

Defining what constitutes a breaking change isn't easy for integrated tools like Nx.

There are two extremes:

  • A runtime library has a well-defined interface you can make assertions against. This, of course, doesn't guarantee that a code change won't break anyone. Any code change can break someone somewhere, even if it is a small bug fix. After all, someone could reply on the existence of the bug. But the probability of it is low.
  • For a IDE or an editor, you cannot meaningfully define "a breaking change" because the interface is graphical and it's hard to formally define it.

Nx sits somewhere in between.

Different Areas of Nx

Nx Commands

Nx Commands (e.g., affected) have inputs (flags) and outputs.

We apply semantic versioning to inputs. We guarantee that whatever inputs you pass right now will continue to work until the next major release. We also do our best not to break folks upgrading from one major to another one. Some of the flags we deprecated two years ago still work because we know folks use those flags in CI.

Unless the command is meant to be consumed by a tool (e.g., print-affected), we don't provide any guarantees regarding the output. For instance, we can change how we format the results of the run. We are mindful of folks using some of the commands in CI, so we do our best to keep the output exactly the same for those commands (e.g., affected:apps).

Builders

Builders have inputs (flags) and runtime behavior. As with Nx Commands, we apply semantic versioning to inputs. We guarantee that whatever inputs you pass right now will continue to work until the next major release. We also do our best not to break folks who upgrade from one major to another one.

Since builders rely on third-party tools, we cannot make any guarantees about builders' outputs. WebPack can start emitting different output and there is no much we can do about it.

Schematics / Code Generation

Since devs run schematics manually, the schematics' stability is less important. If a flag gets renamed, the developer can always pass the renamed flag. Same applies to the output. The develop can always change the output after it has been generated. We are doing out best not to change the generated code drastically in minor releases.

Runtime Components

We use semantic versioning.

Third-Party Libraries

Most of the time we don't depend on a particular version of a third-party library. So if an Nx upgrade broke you by say bumping up the version of React, you can always change it back. This doesn't always work, and we are mindful of that. One of the main culprits here is TypeScript. If you use strict: true, then any major upgrade of Nx is likely to result in new compiler errors in your workspace. They are usually easy to fix, but it's something you should be mindful of.

What Constitutes a Breaking Change

We consider a change non-breaking if the developer has to do nothing after upgrading. This can be achieved in two ways: by keeping the API exactly the same or by providing an automatic migration for your workspace. We also do our best by providing migrations that help you upgrade from one major version to another one.

Experimental

When we add new packages or commands, we treat them as experimental for 6 months. We can make breaking changes in those packages.

We try our best

Many of us work with large Nx workspaces that has been around for years. Since we have to keep them up to date, we try to make the upgrade progress as painless as we can.