TurboSnap

TurboSnap is an advanced Chromatic feature that speeds up builds for faster UI testing and review using Git and Webpack’s dependency graph. It identifies component files that change, then intelligently builds and snapshots only the stories associated with those components.

⚠️ When using TurboSnap, your builds may complete in less time using fewer snapshots. However, we don’t recommend using TurboSnap immediately when starting out with Chromatic since the configuration is more complicated and can lead to difficult to debug scenarios or UI changes being missed. Instead, become familiar with Chromatic’s out of the box behavior and once your project has been running smoothly for some time consider trying out TurboSnap.

Prerequisites

  • Storybook 6.2+
  • Webpack
  • Stories correctly configured in Storybook’s main.js

Enable

Run Chromatic’s CLI with the --only-changed option to enable TurboSnap. Alternatively, you can use the onlyChanged option to the Chromatic GitHub action.

It will build and test stories that may have been affected by the Git changes since the last build. Depending on how your project is setup, you may need additional configuration.

How it works

  1. Chromatic considers the Git changes between the current commit and the commit of the ancestor build.
  2. Chromatic then uses Webpack’s dependency graph to track those changes back up to the story files that depend on them.
  3. Chromatic only tests the stories defined in those story files.

Stories that have not changed will not be tested (i.e., snapshotted), despite appearing in Chromatic’s UI as if they were. In many cases this will lead to much decreased snapshot usage and faster build times.

Certain circumstances could potentially affect all stories. To prevent false positives, we re-test everything if any of the following situations apply:

  • Changes to package versions in package.json, yarn.lock, package-lock.json
  • Changes to your Storybook’s configuration
  • Changes in files that are imported by your preview.js (as this could affect any story)
  • Changes in your static folder (e.g., fonts, images that aren’t loaded via Webpack imports)
  • Changes to files specific by the --externals option (see below)
  • Re-run of the same build (commit and branch match the parent build)
  • Infrastructure upgrades
  • UI Test in a new browser

Configure

Static Storybook builds

If you’re using --storybook-build-dir to provide a prebuilt Storybook, adjust your build-storybook script to include the --webpack-stats-json option. If Chromatic builds your Storybook for you, this is not necessary, it will take care of it for you.

For example:

{
  "scripts": {
    "build-storybook": "build-storybook --webpack-stats-json storybook-static"
  }
}

In Storybook 6.2, --webpack-stats-json must be set to the value of --output-dir (storybook-static by default). In Storybook 6.3+, the value can be omitted as it will use the value of --output-dir automatically. Note that --webpack-stats-json is not supported before Storybook 6.2, and therefore cannot be used with TurboSnap.

Specify which changes trigger a full re-test

TurboSnap relies on Webpack’s dependency graph. That means if you’re using files that are processed externally to Webpack, with the output consumed by Webpack, you’ll need to trigger a re-test when they change.

For example, if you use an external SASS compiler (not sass-loader) to compile .sass files to .css files (which are then consumed by Webpack), then a change to a .sass file will not match any dependencies, preventing stories from being captured (i.e., snapshotted).

To work around this, run Chromatic’s CLI with the --externals option (or externals action option) to specify one or more globs of “externally processed” files. For example:

chromatic --only-changed --externals "*.sass" --externals "*.mjml"`

Enable for specific branches

To enable this feature for specific branches, pass a glob to --only-changed (e.g. chromatic --only-changed "feature/*").

Support for monorepos

If you’re working in a monorepo, there are some situations where you’re certain no UI has changed. For instance, if you make a backend-only change. In such cases, you can skip Chromatic entirely.

With TurboSnap enabled, you’ll be able to publish your Storybook to Chromatic, but UI testing will be automatically skipped. So there is no need to skip manually.

Only test subprojects of monorepos

If you’re working in a monorepo, there are situations where you know changes only affect a subproject. In those cases, you can run Chromatic on a subset of your Storybook.

With TurboSnap enabled, running tests on subprojects that change happens automatically. You’ll be able to build and publish your Storybook, but Chromatic won’t test unchanged subprojects or take snapshots. So there is no need to build a subset of your Storybook manually.


Troubleshooting

How can I tell if TurboSnap is working?

The best way to see if TurboSnap is working is to inspect your CLI output. There are a couple of messages the CLI outputs of particular relevance:

Traversing dependencies for X files that changed since the last build

This message tells us how many git changes Chromatic detected since the last Chromatic build. Usually, that’s just one or two commit’s worth of files.

Found Y story files affected by recent changes

This message tells you the number of story files that depend on the X changes above. This message also might be replaced by a message telling you that we need to capture all stories (see below).

Tested A stories across B components; capture C snapshots in S seconds.

This message tells you how many snapshots we actually took instead of the number of stories we found in your Storybook. Usually, C would be the number of stories in the Y component files above.

Why are no changes being detected?

If the messages above indicate no story files are being detected by changes, then possibly there is an issue matching up the git changes with the files in your Storybook build. Use the –debug flag to get more information about what Chromatic is doing (use the chromatic-cli@canary version for better debugging).

We are adding some tools to the CLI to help you debug further; for now, contact Chromatic support if this is happening to you.

Another reason that changes may be missed is if the changed files aren’t directly included in the webpack build; use the –externals flag to tell Chromatic about this.

Why are full rebuilds required?

Full rebuilds can be required for various reasons (see the list in how it works).

Some reasons that can be surprising are:

  1. A change to a package.json or lock file for a subproject that doesn’t affect the Storybook (we need to be very conservative as we cannot tell if a change to a lock file could affect node_modules imported by Storybook).
If you run into this situation frequently, upvote the open issue in the Chromatic CLI's issue tracker to opt-out of this behavior for specific directories in your repository.
  1. If the previous Chromatic build is linked to a commit that no longer exists in the repository. It can happen for a couple of reasons, most commonly rebasing a feature branch and force-pushing. When we don’t know the previous commit, we cannot tell what has changed since then automatically.
If you're encounter this situation often, upvote the open issue in the Chromatic's CLI's issue tracker to address this situation.
Why is my build failing with an Out of memory error?

If you have a large dependency tree, the build process may fail due to an out of memory error. Re-run Chromatic’s CLI with the NODE_OPTIONS=--max_old_space_size=4096 (or higher) environment variable to increase the amount of available memory. Your CI provider may require additional configuration to allow more memory usage.