Skip to main content

one-spa 6

· 10 min read

We have released one-spa@6! We are committed to a stable one-spa runtime with very few breaking changes. We expect over 95% of one-spa users can upgrade easily without altering their changes!

Summary

one-spa@6 provides advanced features such as async navigation cancelation and parcel-only mode (via patchHistoryApi), while also updating the package configuration to use modern NodeJS and bundler features like package entrypoints and "type": "module". We also updated urlRerouteOnly to default to true, as it boosts performance and we consider it to be a best practice to author applications that work when urlRerouteOnly is set to true.

Browser Support / IE11

We still support IE11 and the same versions of NodeJS (at least as old as Node 10). However, we've changed our defaults such that IE11 is only supported with some additional configuration, as described in the IE11 Migration section below.

For the one-spa npm package, we plan one-spa@6 to be the last major version that supports IE11. In general, we've released a major version of one-spa every 1-2 years. We do not have a concrete timeline or plans for one-spa@7, and will accept community contributions for any important patches to one-spa@6 after one-spa@7 is released.

For all surrounding packages (one-spa-react, one-spa-vue, systemjs-webpack-interop, one-spa-angular, etc) we may begin dropping IE11 support sooner than the one-spa@7 release. As we do so, we'll create documentation that lists the latest versions of packages that support IE11, and also accept community contributions to those versions for important updates.

The motivation for dropping IE11 support over time is to allow our core team to spend less time on supporting a nine year old browser and more time pushing the one-spa ecosystem forward. Also, we believe that the majority of end users should not suffer performance penalties because of a small percentage of users still using IE11. Slowly dropping IE11 also will also allow us to focus on a systemjs-less future for one-spa, where native browser modules are used rather than systemjs modules.

We understand and sympathize with companies who cannot drop IE11 support now, which is why we're supporting IE11 even though much of the ecosystem has already dropped it (Vue 3 does not support ie11, Angular only does after some effort, and even webpack 5 requires extra configuration to get it working in IE11). Many of one-spa's users are large financial institutions, large ecommerce companies, and other very large companies, where dropping IE11 support is a long process that involves many dozens of people from separate departments. We encourage one-spa users to start the conversations at your companies about dropping IE11 support, even if they take a long time or result in a decision to drop IE11 years in the future.

Migration

We think that >95% of one-spa users will be able to safely upgrade with no code changes. The breaking changes below are largely related to advanced features that most one-spa users do not use.

Steps

  1. If using SystemJS + import maps, change the URL of one-spa in your import map:
<script type="systemjs-importmap">
{
"imports": {
- "one-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/system/one-spa.min.js"
+ "one-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/es2015/system/one-spa.min.js"
}
}
</script>
  1. In all your microfrontends (including root config), upgrade one-spa:
npm install one-spa@6
yarn add one-spa@6
pnpm install one-spa@6
  1. Test things out.
  2. If your app is not re-rendering during route transitions like it should (this is most common for Angular apps, but can happen in other frameworks to if you do a route transition without modifying the URL), change your root config's call to start()
import { start } from 'one-spa';

// DO NOT MAKE THIS CHANGE unless you are experiencing problems.
- start();
+ start({
+ urlRerouteOnly: false
+ });

That's it! If you experience other issues, let us know in Github issues.

IE11

If you support IE11, use the es5 version of one-spa rather than es2015. The method of doing this depends on your configuration - some common ones are explained below:

Import Maps

<script type="systemjs-importmap">
{
"imports": {
- "one-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/es2015/system/one-spa.min.js"
+ "one-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/es5/system/one-spa.min.js"
}
}
</script>

Webpack

If externalizing one-spa in your webpack config (very common, and the default with webpack-config-one-spa), you do not need to make the changes below. Otherwise, though, these changes will ensure you use the IE11-compatible version of one-spa.

// webpack.config.js
module.exports = {
resolve: {
alias: {
"one-spa": require.resolve("one-spa/lib/es5/esm/one-spa.min.js"),
},
},
};

Rollup

Use https://www.npmjs.com/package/@rollup/plugin-alias to alias the import similarly to webpack

Import

If you do not wish to change bundler configuration, you can modify your import statements.

- import { start } from 'one-spa';
+ import { start } from 'one-spa/lib/es5/esm/one-spa.min.js';

Breaking Changes

  • one-spa's package.json's "main" field now points to an es2015 version of one-spa that does not work in IE11. To support IE11, see section below.
  • Delay patching history api until start() or patchHistoryApi() is called. Github link
  • Do not show start() warning when registerApplication hasn't been called (for parcel-only use cases) Github link
  • Change urlRerouteOnly default value to true. This is a performance boost for most applications, but for some situations can result in one-spa not triggering mounts/unmounts when it should. You can read more about it at https://one-spa.js.org/docs/api#start and https://github.com/bitterblossomio/one-spa/issues/484. Angular users may want to set it to false due to nuanced behavior of angular router. To do so, call start({urlRerouteOnly: false}) in your root config. Github link
  • cancelNavigation(val) no longer cancels navigation if val is falsy Github link
  • one-spa's package.json "type" is now set to "module". This only impacts NodeJS usage of one-spa (not webpack/rollup/browser). Read more at official nodejs docs.
  • one-spa's package.json now has "exports". This changes which of one-spa's bundles are used by NodeJS, webpack, and rollup. The main change is that webpack / rollup will now use an IE11-incompatible (es2015) version of one-spa. See IE11 section below for more details. Additionally, an ESM version of one-spa will now be used when loaded via import('one-spa') or import 'one-spa';, whereas a UMD version will be used when calling require("one-spa'). To avoid the dual package hazard, only use import or require to load one-spa in your NodeJS code - do not use both. You can see the package exports at https://github.com/bitterblossomio/one-spa/blob/dea22f1aac39777a07252897ae625ab1d8313e9d/package.json#L8-L25.
  • The published umd builds now have .cjs extensions rather than .js, since all .js files in the one-spa package are assumed to be ESM.
File structure published to npm

# Before
# See https://www.jsdelivr.com/package/npm/one-spa?path=lib&version=5.9.3
lib/
# IE11
umd/
one-spa.dev.js
one-spa.min.js
# IE11
esm/
one-spa.dev.js
one-spa.min.js
# IE11
system/
one-spa.dev.js
one-spa.min.js
# No IE11
es2015/
one-spa.dev.js
one-spa.min.js

# After
# See https://www.jsdelivr.com/package/npm/one-spa?path=lib&version=6.0.0
lib
# IE11
es5/
umd/
one-spa.dev.js
one-spa.min.js
system/
one-spa.dev.js
one-spa.min.js
esm/
one-spa.dev.js
one-spa.min.js
# No IE11
es2015/
umd/
one-spa.dev.cjs
one-spa.min.cjs
system/
one-spa.dev.js
one-spa.min.js
esm/
one-spa.dev.js
one-spa.min.js

Features

Async navigation cancelation

We've added support for async navigation cancelation. To use it, call cancelNavigation(promise) with a promise as an argument. One Spa will wait until that promise resolves/rejects before proceeding with navigation. If the promise resolves with a truthy value, navigation is canceled. If the promise resolves with a falsy value or rejects, navigation is not canceled. Github link

window.addEventListener("one-spa:before-routing-event", (evt) => {
if (evt.detail.oldUrl === "/settings") {
evt.detail.cancelNavigation(checkSettingsOkay());
}
});

async function checkSettingsOkay() {
const response = await fetch("/api/settings-okay");
if (response.ok) {
return true;
} else {
alert("Please fix your settings before leaving the page");
return false;
}
}

New patchHistoryApi

We've exposed a new patchHistoryApi() api. This lets you use one-spa's modified implementations of pushState/replaceState/popstate/hashchange without using one-spa applications. This is intended to be used by one-spa users who exclusively use one-spa parcels, rather than applications Github link

import { patchHistoryApi, mountRootParcel } from "one-spa";

patchHistoryApi({
urlRerouteOnly: true,
});

// now you don't need to call start() if you're only using parcels

mountRootParcel(parcelConfig, parcelProps);

New profiler

We've implemented a profiler that is available within the dev builds of one-spa@6. A visualization of the profiler is available in the [email protected] browser extension:

  • Implement profiler for lifecycle events. by @joeldenning in #868
  • Implement parcel and routing profiler events. by @joeldenning in #903
Screenshot of one-spa-inspector profiler tab

Fixes

  • Fix regression with parcel name Github link
  • Ensure all reroute promises (triggerAppChange() return value) resolve even during cancelation Github link
  • fix(types): fix OneSpaAppsByNewStatus interface by @FelixGraf in #988
  • Ensure app is unmounted during unregisterApplication. Resolves #871 by @joeldenning in #875

Maintenance

  • Switch from yarn -> pnpm Github link
  • Upgrade all dependencies Github link
  • Upgrade husky from v4 to v7. Use pinst to avoid issues with yarn 2 users as described in https://typicode.github.io/husky/#/?id=yarn-2 Github link
  • Upgrade to Jest 27. Fix tests to work with Jest 27. Github link
  • Upgrade to Node 16. Fix tests to work with Node 16 (Fix tests in Node 15 #652) Github link
  • Run upgraded version of prettier on all files. Github link
  • Remove unused babel-eslint dependency Github link
  • Upgrade to new package names for all rollup plugins. (@rollup/plugin-node-resolve instead of rollup-plugin-node-resolve) Github link
  • Remove file size impact workflow since it's broken. by @joeldenning in #879
  • Remove console.log in test by @joeldenning in #878