Feature flaggable NPM dependency upgrades

Marco de Jongh
ITNEXT
Published in
2 min readJun 13, 2018

--

Atlassian is in the process of adopting their own design system called Atlaskit. This means that more and more we’re “outsourcing” product functionality to npm modules from the Atlaskit repo.

While this is a great development, some of the dependencies contain so much functionality. That we the felt the need to ship upgrades to a subset of users before giving it to the masses. Preferably through a feature flag.

I initially thought that this would be impossible, because how the hell are you going to install 2 versions of the same dependency?! But after giving it a go it turned out relatively straightforward using a package.json alias & code-splitting.

How

Add a alias for the dependency you want to FF to your package.json and run yarn so the lock gets updated. This is what I added to the package.json:

"@atlaskit/editor-core": "^70.2.18",
"@atlaskit/editor-core-latest": "npm:@atlaskit/editor-core@71.0.22",

Then make sure you use code-splitting for loading the dependency. In Confluence we use react-loabable to code split our components. Add the second loader for the npm alias:

const getEditorLoader = () =>
isDarkFeatureEnabled("fabric.editor.next") ? latestEditorLoader : defaultEditorLoader;
const defaultEditorLoader = () => import(/* webpackChunkName: "@atlaskit_editor-core" */ "@atlaskit/editor-core")const latestEditorLoader = () => import(/* webpackChunkName: "@atlaskit_editor-core-latest" */ "@atlaskit/editor-core-latest")
const LoadableEditor = Loadable({
loader: getEditorLoader(),
loading() {
return <div>Loading...</div>
}
});

Important: Make sure that the webpackChunkName’s are different

That’s all you need to do, simple right?

Caveats

In the case of a big dependency like @atlaskit/editor-core we take a considerable webpack build time hit due to now having 2 versions we need to bundle.

yarn tooling doesn’t like the package.json aliases so tools like upgrade & upgrade-interactive won’t work for upgrading the latest version. Instead you will have to manually upgrade the version in the package.json + run yarn for updating the lock file

This approach doesn’t support FF’s changing at runtime and requires a refresh before the FF is changed. This can be fixed by creating the loaders inside a redux container, but for our particular use-case I didn’t feel like it was worth the extra complexity.

Useful scripts

We’ve added some scripts to automate the process for us, these could be handy for anyone else wanting to re-use this approach.

Script for upgrading the feature flagged version: https://gist.github.com/marcodejongh/8cc8d16fbc451838581014098dc0fb71

Script for accepting the feature flagged version and re-bumping the hidden version: https://gist.github.com/marcodejongh/fa2bc1ebb7845af0119c6748d8c26750

--

--