<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://one-spa.js.org/blog</id>
    <title>One Spa Blog</title>
    <updated>2023-11-27T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://one-spa.js.org/blog"/>
    <subtitle>One Spa Blog</subtitle>
    <icon>https://one-spa.js.org/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[one-spa 6]]></title>
        <id>https://one-spa.js.org/blog/2023/11/27/one-spa-6</id>
        <link href="https://one-spa.js.org/blog/2023/11/27/one-spa-6"/>
        <updated>2023-11-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[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>
        <content type="html"><![CDATA[<p>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!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>one-spa@6 provides advanced features such as async navigation cancelation and parcel-only mode (via <code>patchHistoryApi</code>), while also updating the package configuration to use modern NodeJS and bundler features like <a href="https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_package_entry_points" target="_blank" rel="noopener noreferrer" class="">package entrypoints</a> and <a href="https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_type" target="_blank" rel="noopener noreferrer" class=""><code>"type": "module"</code></a>. We also updated <code>urlRerouteOnly</code> to default to <code>true</code>, as it boosts performance and we consider it to be a best practice to author applications that work when urlRerouteOnly is set to true.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="browser-support--ie11">Browser Support / IE11<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#browser-support--ie11" class="hash-link" aria-label="Direct link to Browser Support / IE11" title="Direct link to Browser Support / IE11" translate="no">​</a></h2>
<p><strong>We still support IE11</strong> 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.</p>
<p>For the <code>one-spa</code> 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.</p>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration">Migration<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#migration" class="hash-link" aria-label="Direct link to Migration" title="Direct link to Migration" translate="no">​</a></h2>
<p>We think that &gt;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.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="steps">Steps<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#steps" class="hash-link" aria-label="Direct link to Steps" title="Direct link to Steps" translate="no">​</a></h3>
<ol>
<li class="">If using SystemJS + import maps, change the URL of one-spa in your import map:</li>
</ol>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;script type="systemjs-importmap"&gt;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    "imports": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">-     "one-spa": "https://cdn.jsdelivr.net/npm/one-spa@5.9.2/lib/system/one-spa.min.js"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+     "one-spa": "https://cdn.jsdelivr.net/npm/one-spa@6.0.0/lib/es2015/system/one-spa.min.js"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;/script&gt;</span><br></div></code></pre></div></div>
<ol start="2">
<li class="">In all your microfrontends (including root config), upgrade one-spa:</li>
</ol>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">npm install one-spa@6</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add one-spa@6</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">pnpm install one-spa@6</span><br></div></code></pre></div></div>
<ol start="3">
<li class="">Test things out.</li>
<li class="">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 <code>start()</code></li>
</ol>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">import { start } from 'one-spa';</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">// DO NOT MAKE THIS CHANGE unless you are experiencing problems.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">- start();</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+ start({</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+   urlRerouteOnly: false</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+ });</span><br></div></code></pre></div></div>
<p>That's it! If you experience other issues, let us know in Github issues.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ie11">IE11<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#ie11" class="hash-link" aria-label="Direct link to IE11" title="Direct link to IE11" translate="no">​</a></h3>
<p>If you support IE11, use the <code>es5</code> version of one-spa rather than <code>es2015</code>. The method of doing this depends on your configuration - some common ones are explained below:</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="import-maps">Import Maps<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#import-maps" class="hash-link" aria-label="Direct link to Import Maps" title="Direct link to Import Maps" translate="no">​</a></h4>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;script type="systemjs-importmap"&gt;</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    "imports": {</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">-     "one-spa": "https://cdn.jsdelivr.net/npm/one-spa@6.0.0/lib/es2015/system/one-spa.min.js"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+     "one-spa": "https://cdn.jsdelivr.net/npm/one-spa@6.0.0/lib/es5/system/one-spa.min.js"</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  }</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;/script&gt;</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="webpack">Webpack<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#webpack" class="hash-link" aria-label="Direct link to Webpack" title="Direct link to Webpack" translate="no">​</a></h4>
<p>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.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// webpack.config.js</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">resolve</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">alias</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string-property property">"one-spa"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa/lib/es5/esm/one-spa.min.js"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rollup">Rollup<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#rollup" class="hash-link" aria-label="Direct link to Rollup" title="Direct link to Rollup" translate="no">​</a></h4>
<p>Use <a href="https://www.npmjs.com/package/@rollup/plugin-alias" target="_blank" rel="noopener noreferrer" class="">https://www.npmjs.com/package/@rollup/plugin-alias</a> to alias the import similarly to webpack</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="import">Import<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#import" class="hash-link" aria-label="Direct link to Import" title="Direct link to Import" translate="no">​</a></h4>
<p>If you do not wish to change bundler configuration, you can modify your import statements.</p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">- import { start } from 'one-spa';</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">+ import { start } from 'one-spa/lib/es5/esm/one-spa.min.js';</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="breaking-changes">Breaking Changes<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#breaking-changes" class="hash-link" aria-label="Direct link to Breaking Changes" title="Direct link to Breaking Changes" translate="no">​</a></h2>
<ul>
<li class="">one-spa's package.json's <code>"main"</code> field now points to an es2015 version of one-spa that does not work in IE11. To support IE11, see section below.</li>
<li class="">Delay patching history api until start() or patchHistoryApi() is called. <a href="https://github.com/bitterblossomio/one-spa/pull/827" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Do not show start() warning when registerApplication hasn't been called (for parcel-only use cases) <a href="https://github.com/bitterblossomio/one-spa/pull/827" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">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 <a href="https://one-spa.js.org/docs/api#start" target="_blank" rel="noopener noreferrer" class="">https://one-spa.js.org/docs/api#start</a> and <a href="https://github.com/bitterblossomio/one-spa/issues/484" target="_blank" rel="noopener noreferrer" class="">https://github.com/bitterblossomio/one-spa/issues/484</a>. Angular users may want to set it to false due to nuanced behavior of angular router. To do so, call <code>start({urlRerouteOnly: false})</code> in your root config. <a href="https://github.com/bitterblossomio/one-spa/pull/828" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class=""><code>cancelNavigation(val)</code> no longer cancels navigation if <code>val</code> is falsy <a href="https://github.com/bitterblossomio/one-spa/pull/826" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">one-spa's package.json <code>"type"</code> is now set to <code>"module"</code>. This only impacts NodeJS usage of one-spa (not webpack/rollup/browser). Read more at <a href="https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_type" target="_blank" rel="noopener noreferrer" class="">official nodejs docs</a>.</li>
<li class="">one-spa's package.json now has <code>"exports"</code>. 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 <code>import('one-spa')</code> or <code>import 'one-spa';</code>, whereas a UMD version will be used when calling <code>require("one-spa')</code>. To avoid the <a href="https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_dual_commonjs_es_module_packages" target="_blank" rel="noopener noreferrer" class="">dual package hazard</a>, only use <code>import</code> or <code>require</code> to load one-spa in your NodeJS code - do not use both. You can see the package exports at <a href="https://github.com/bitterblossomio/one-spa/blob/dea22f1aac39777a07252897ae625ab1d8313e9d/package.json#L8-L25" target="_blank" rel="noopener noreferrer" class="">https://github.com/bitterblossomio/one-spa/blob/dea22f1aac39777a07252897ae625ab1d8313e9d/package.json#L8-L25</a>.</li>
<li class="">The published <code>umd</code> builds now have <code>.cjs</code> extensions rather than <code>.js</code>, since all <code>.js</code> files in the one-spa package are assumed to be ESM.</li>
</ul>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token plain">File structure published to npm</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"># Before</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"># See https://www.jsdelivr.com/package/npm/one-spa?path=lib&amp;version=5.9.3</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">lib/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  umd/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  esm/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  system/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # No IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  es2015/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"># After</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"># See https://www.jsdelivr.com/package/npm/one-spa?path=lib&amp;version=6.0.0</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">lib</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  es5/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    umd/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    system/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    esm/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  # No IE11</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  es2015/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    umd/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.cjs</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.cjs</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    system/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    esm/</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.dev.js</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      one-spa.min.js</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="features">Features<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#features" class="hash-link" aria-label="Direct link to Features" title="Direct link to Features" translate="no">​</a></h2>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="async-navigation-cancelation">Async navigation cancelation<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#async-navigation-cancelation" class="hash-link" aria-label="Direct link to Async navigation cancelation" title="Direct link to Async navigation cancelation" translate="no">​</a></h2>
<p>We've added support for async navigation cancelation. To use it, call <code>cancelNavigation(promise)</code> 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. <a href="https://github.com/bitterblossomio/one-spa/pull/826" target="_blank" rel="noopener noreferrer" class="">Github link</a></p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token dom variable" style="color:rgb(191, 199, 213)">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">addEventListener</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa:before-routing-event"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">evt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">evt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">detail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">oldUrl</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"/settings"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    evt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">detail</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">cancelNavigation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">checkSettingsOkay</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">checkSettingsOkay</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> response </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">fetch</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/api/settings-okay"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">ok</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">alert</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Please fix your settings before leaving the page"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-patchhistoryapi">New patchHistoryApi<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#new-patchhistoryapi" class="hash-link" aria-label="Direct link to New patchHistoryApi" title="Direct link to New patchHistoryApi" translate="no">​</a></h3>
<p>We've exposed a new <code>patchHistoryApi()</code> 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 <a href="https://github.com/bitterblossomio/one-spa/pull/827" target="_blank" rel="noopener noreferrer" class="">Github link</a></p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> patchHistoryApi</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> mountRootParcel </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">patchHistoryApi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">urlRerouteOnly</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// now you don't need to call start() if you're only using parcels</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">mountRootParcel</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">parcelConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> parcelProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-profiler">New profiler<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#new-profiler" class="hash-link" aria-label="Direct link to New profiler" title="Direct link to New profiler" translate="no">​</a></h3>
<p>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 one-spa-inspector@0.6.0 browser extension:</p>
<ul>
<li class="">Implement profiler for lifecycle events. by @joeldenning in <a href="https://github.com/bitterblossomio/one-spa/pull/868" target="_blank" rel="noopener noreferrer" class="">#868</a></li>
<li class="">Implement parcel and routing profiler events. by @joeldenning in <a href="https://github.com/bitterblossomio/one-spa/pull/903" target="_blank" rel="noopener noreferrer" class="">#903</a></li>
</ul>
<img src="https://one-spa.js.org/img/profiler-screenshot.png" alt="Screenshot of one-spa-inspector profiler tab">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fixes">Fixes<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#fixes" class="hash-link" aria-label="Direct link to Fixes" title="Direct link to Fixes" translate="no">​</a></h2>
<ul>
<li class="">Fix regression with parcel name <a href="https://github.com/bitterblossomio/one-spa/pull/825" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Ensure all reroute promises (triggerAppChange() return value) resolve even during cancelation <a href="https://github.com/bitterblossomio/one-spa/pull/831" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">fix(types): fix OneSpaAppsByNewStatus interface by @FelixGraf in <a href="https://github.com/bitterblossomio/one-spa/pull/988" target="_blank" rel="noopener noreferrer" class="">#988</a></li>
<li class="">Ensure app is unmounted during unregisterApplication. Resolves #871 by @joeldenning in <a href="https://github.com/bitterblossomio/one-spa/pull/875" target="_blank" rel="noopener noreferrer" class="">#875</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="maintenance">Maintenance<a href="https://one-spa.js.org/blog/2023/11/27/one-spa-6#maintenance" class="hash-link" aria-label="Direct link to Maintenance" title="Direct link to Maintenance" translate="no">​</a></h2>
<ul>
<li class="">Switch from yarn -&gt; pnpm <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Upgrade all dependencies <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Upgrade husky from v4 to v7. Use pinst to avoid issues with yarn 2 users as described in <a href="https://typicode.github.io/husky/#/?id=yarn-2" target="_blank" rel="noopener noreferrer" class="">https://typicode.github.io/husky/#/?id=yarn-2</a> <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Upgrade to Jest 27. Fix tests to work with Jest 27. <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Upgrade to Node 16. Fix tests to work with Node 16 (Fix tests in Node 15 #652) <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Run upgraded version of prettier on all files. <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Remove unused babel-eslint dependency <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Upgrade to new package names for all rollup plugins. (@rollup/plugin-node-resolve instead of rollup-plugin-node-resolve) <a href="https://github.com/bitterblossomio/one-spa/pull/824" target="_blank" rel="noopener noreferrer" class="">Github link</a></li>
<li class="">Remove file size impact workflow since it's broken. by @joeldenning in <a href="https://github.com/bitterblossomio/one-spa/pull/879" target="_blank" rel="noopener noreferrer" class="">#879</a></li>
<li class="">Remove console.log in test by @joeldenning in <a href="https://github.com/bitterblossomio/one-spa/pull/878" target="_blank" rel="noopener noreferrer" class="">#878</a></li>
</ul>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[one-spa 5]]></title>
        <id>https://one-spa.js.org/blog/2020/02/24/one-spa-5</id>
        <link href="https://one-spa.js.org/blog/2020/02/24/one-spa-5"/>
        <updated>2020-02-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Today we released one-spa@5.0.0.]]></summary>
        <content type="html"><![CDATA[<p>Today we released one-spa@5.0.0.</p>
<p>Here are the highlights:</p>
<ul>
<li class="">Performance focus: 35% decrease in library size.</li>
<li class="">A CLI for one-spa: <a class="" href="https://one-spa.js.org/docs/create-one-spa">create-one-spa</a></li>
<li class="">New framework-specific example repositories - <a href="https://github.com/react-microfrontends" target="_blank" rel="noopener noreferrer" class="">React example</a>, <a href="https://github.com/vue-microfrontends" target="_blank" rel="noopener noreferrer" class="">Vue example</a>, <a href="https://github.com/polyglot-microfrontends" target="_blank" rel="noopener noreferrer" class="">Multiple frameworks example</a>, <a class="" href="https://one-spa.js.org/docs/examples">Full list</a></li>
<li class="">Massively improved documentation, including <a class="" href="https://one-spa.js.org/docs/microfrontends-concept">Concept: Microfrontends</a> and <a class="" href="https://one-spa.js.org/docs/recommended-setup">The Recommended Setup</a>.</li>
</ul>
<p><a href="https://github.com/bitterblossomio/one-spa/releases/tag/v5.0.0" target="_blank" rel="noopener noreferrer" class="">Release notes here</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-from-4-to-5">Migration from 4 to 5<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#migration-from-4-to-5" class="hash-link" aria-label="Direct link to Migration from 4 to 5" title="Direct link to Migration from 4 to 5" translate="no">​</a></h2>
<p>For every user we're aware of, <strong>you do not need to change anything in your code in order to upgrade to one-spa@5</strong>. The breaking changes listed in the release notes are the removal of features that were never documented.</p>
<p>If installing from npm, you can simply <code>npm install --save one-spa@5.0.0</code> or <code>yarn add one-spa@5.0.0</code>.</p>
<p>Alternatively, one-spa is available on <a href="https://cdnjs.com/libraries/one-spa" target="_blank" rel="noopener noreferrer" class="">cdnjs</a>, <a href="https://www.jsdelivr.com/package/npm/one-spa" target="_blank" rel="noopener noreferrer" class="">jsdelivr</a>, and <a href="https://unpkg.com/browse/one-spa/" target="_blank" rel="noopener noreferrer" class="">unpkg</a>.</p>
<p>The one-spa core team is committed to treating our users well, which includes not introducing massive breaking changes. The core one-spa API has not seen massive breaking changes <a href="https://github.com/bitterblossomio/one-spa/releases/tag/v3.0.0" target="_blank" rel="noopener noreferrer" class="">since one-spa@3 in August 2016</a>. We have added features and improved things, but one-spa is a stable technology. We are committed to maintaining it, documenting it, and adjusting it as technologies like in-browser modules become more and more popular and viable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="performance-improvements">Performance improvements<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#performance-improvements" class="hash-link" aria-label="Direct link to Performance improvements" title="Direct link to Performance improvements" translate="no">​</a></h2>
<p>The ESM version of one-spa@4 was 23.8kb (7.2kb gzipped). That was improved in one-spa@5 to 15.5kb (5.1kb gzipped). We did this by optimizing our build process and removing unused features.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-spa-cli">one-spa CLI<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#one-spa-cli" class="hash-link" aria-label="Direct link to one-spa CLI" title="Direct link to one-spa CLI" translate="no">​</a></h2>
<p>Since one-spa's inception, bundler configuration has been a huge source of user pain. We have heard this pain and implemented <a class="" href="https://one-spa.js.org/docs/create-one-spa">create-one-spa</a>, which creates (and sometimes can update) repositories that are ready to be used as one-spa microfrontends. For Angular and Vue, the official CLIs are used with a few extra plugins automatically installed. For React, a default webpack config with decent eslint / prettier defaults is set up.</p>
<p>Additionally, we have added a lot of documentation for webpack in <a class="" href="https://one-spa.js.org/docs/recommended-setup#build-tools-webpack--rollup">The Recommended Setup</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-example-repositories">New example repositories<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#new-example-repositories" class="hash-link" aria-label="Direct link to New example repositories" title="Direct link to New example repositories" translate="no">​</a></h2>
<p>What started out as one company's special sauce for independently deployed frontend microservices is now fully accessible to the public with our <a class="" href="https://one-spa.js.org/docs/examples">new set of example repos</a>. We have a React example, a Vue example, and a polyglot (multiple framework) example. We hope to add an Angular example, after we achieve support for Angular 9. These example repositories are actively watched and maintained, and reflect our current opinions on the best, production-viable way to do microfrontends.</p>
<p>Furthermore, we have deployed each of the examples to our new domains:</p>
<ul>
<li class=""><a href="https://react.microfrontends.app/" target="_blank" rel="noopener noreferrer" class="">https://react.microfrontends.app</a></li>
<li class=""><a href="https://polyglot.microfrontends.app/" target="_blank" rel="noopener noreferrer" class="">https://polyglot.microfrontends.app</a></li>
<li class=""><a href="https://vue.microfrontends.app/" target="_blank" rel="noopener noreferrer" class="">https://vue.microfrontends.app</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-overhaul">Documentation overhaul<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#documentation-overhaul" class="hash-link" aria-label="Direct link to Documentation overhaul" title="Direct link to Documentation overhaul" translate="no">​</a></h2>
<p>We removed several dated documentation pages, and added several that were very much lacking. Here are a few pages that give you the most bang for your buck:</p>
<ul>
<li class=""><a class="" href="https://one-spa.js.org/docs/microfrontends-concept">Concept: Microfrontend</a></li>
<li class=""><a class="" href="https://one-spa.js.org/docs/recommended-setup">The Recommended Setup</a></li>
<li class=""><a class="" href="https://one-spa.js.org/docs/create-one-spa">create-one-spa CLI</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="development-builds-and-error-codes">Development builds and error codes<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#development-builds-and-error-codes" class="hash-link" aria-label="Direct link to Development builds and error codes" title="Direct link to Development builds and error codes" translate="no">​</a></h2>
<p>Taking inspiration from the <a href="https://reactjs.org/docs/optimizing-performance.html#use-the-production-build" target="_blank" rel="noopener noreferrer" class="">react development and production builds</a>, we now publish to NPM both development and production builds in the following formats: UMD, ESM, and System.register.</p>
<p>You can see the <a href="https://unpkg.com/browse/one-spa@5.0.0/lib/" target="_blank" rel="noopener noreferrer" class="">published build files here</a>. The <code>.dev.js</code> files provide full debugging information in the browser console, whereas the <code>.min.js</code> files give you a numeric error code and a link to a documentation page that explains the error. We hope that these error codes and documentation for them will improve discoverability of relevant documentation when you're setting up one-spa.</p>
<p>An example of these new documentation pages for error codes is <a class="" href="https://one-spa.js.org/error/?code=35&amp;arg=application&amp;arg=app1&amp;arg=%7B%7D">found here</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="governance">Governance<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#governance" class="hash-link" aria-label="Direct link to Governance" title="Direct link to Governance" translate="no">​</a></h2>
<p>The project is fully managed by the open source community.</p>
<p>This change does not mean anything drastic for one-spa. Its license was and is MIT, and we have no plans to do anything with the project besides make it better.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-next">Where next?<a href="https://one-spa.js.org/blog/2020/02/24/one-spa-5#where-next" class="hash-link" aria-label="Direct link to Where next?" title="Direct link to Where next?" translate="no">​</a></h2>
<p>We are actively <a href="https://github.com/bitterblossomio/zh-hans.one-spa.js.org" target="_blank" rel="noopener noreferrer" class="">translating the one-spa documentation to Chinese</a>, and hope to add other languages soon. We will add full <a href="https://github.com/bitterblossomio/one-spa-angular/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+is%3Aopen+angular+9" target="_blank" rel="noopener noreferrer" class="">Angular 9 support</a> soon, and hope to add <a href="https://github.com/bitterblossomio/one-spa/issues/103" target="_blank" rel="noopener noreferrer" class="">server rendering</a> in an upcoming release.</p>
<p>Please <a class="" href="https://one-spa.js.org/docs/contributing-overview">contribute to our code</a> and <a class="" href="https://one-spa.js.org/docs/ecosystem">ecosystem</a>.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[one-spa Inspector and 4.1]]></title>
        <id>https://one-spa.js.org/blog/2019/02/20/one-spa-inspector</id>
        <link href="https://one-spa.js.org/blog/2019/02/20/one-spa-inspector"/>
        <updated>2019-02-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Background]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://one-spa.js.org/blog/2019/02/20/one-spa-inspector#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h2>
<p>For a long time, teams have had the benefit of using a tool called <a href="https://github.com/bitterblossomio/sofe-inspector" target="_blank" rel="noopener noreferrer" class="">sofe inspector</a> (note: this is an out-of-date version of it) to list, override, and interact with one-spa applications. There has always been a desire to <a href="https://github.com/bitterblossomio/one-spa/issues/151" target="_blank" rel="noopener noreferrer" class="">figure out how to share this tool so others can benefit as well</a>.</p>
<p>With that in mind, I'm proud to announce an initial release for <strong><a href="https://github.com/bitterblossomio/one-spa-inspector" target="_blank" rel="noopener noreferrer" class="">one-spa Inspector</a></strong>! one-spa Inspector is a Firefox and Chrome extension, much like React/Vue devtools, that allows you see and interact with your one-spa applications and configuration.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="current-inspector-features">Current Inspector Features<a href="https://one-spa.js.org/blog/2019/02/20/one-spa-inspector#current-inspector-features" class="hash-link" aria-label="Direct link to Current Inspector Features" title="Direct link to Current Inspector Features" translate="no">​</a></h2>
<ul>
<li class="">List registered applications</li>
<li class="">Show application status</li>
<li class="">Force an app to mount or unmount</li>
<li class="">Hover over an app name to have an "inspect element"-like view of your apps (Overlays)</li>
</ul>
<p>(Note: Overlays require a small update to your code, but should hopefully be simple! See <a href="https://github.com/bitterblossomio/one-spa-inspector#configuring-app-overlays" target="_blank" rel="noopener noreferrer" class="">how to configure app overlays</a>)</p>
<p><strong>The one-spa Inspector will only work with one-spa versions 4.1 and higher</strong>, since we had to expose and add some functionality to the one-spa library itself in order to implement these features.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-spa-41">one-spa 4.1<a href="https://one-spa.js.org/blog/2019/02/20/one-spa-inspector#one-spa-41" class="hash-link" aria-label="Direct link to one-spa 4.1" title="Direct link to one-spa 4.1" translate="no">​</a></h2>
<p>one-spa 4.1 was released, which includes a couple of key updates:</p>
<ol>
<li class="">Support for one-spa Inspector</li>
<li class="">ESM bundle output</li>
<li class="">Simpmlified test configuration for developers/contributors to one-spa</li>
</ol>
<p>For most people, ESM (EcmaScript Module) support shouldn't affect how you use one-spa, but for those looking to play around with modules or other advanced Javascript things, it's a welcome addition.</p>
<p>We also changed our test suite to purely use Jest instead of Saucelabs, and hopefully false positive "failing" tests on pull requests will be a thing of the past.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="help-wanted">Help Wanted!<a href="https://one-spa.js.org/blog/2019/02/20/one-spa-inspector#help-wanted" class="hash-link" aria-label="Direct link to Help Wanted!" title="Direct link to Help Wanted!" translate="no">​</a></h2>
<p>If you would like to suggest a new feature for one-spa Inspector, report a bug, improve our (admittedly horrible and hopefully temporary) UI/UX, or add features, please see the <a href="https://github.com/bitterblossomio/one-spa-inspector" target="_blank" rel="noopener noreferrer" class="">github repo</a> and hack away!</p>
<p>We also hope to update some of our example repos to the lastest one-spa so that anyone with the extension installed can test out the features and see how to implement overlays. But this process will go faster if someone wants to help out. :)</p>
<p>Thank you!</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[one-spa parcels, explained]]></title>
        <id>https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained</id>
        <link href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained"/>
        <updated>2018-06-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Ever since one-spa@1.0.0, the one-spa team has been dedicated to bringing microservices to the frontend. We have made it possible for AngularJS, React, Angular, Vue, and other frameworks to coexist side by side in the same page.]]></summary>
        <content type="html"><![CDATA[<p>Ever since one-spa@1.0.0, the one-spa team has been dedicated to bringing microservices to the frontend. We have made it possible for AngularJS, React, Angular, Vue, and other frameworks to coexist side by side in the same page.</p>
<p>And with the release of <a href="https://github.com/bitterblossomio/one-spa/releases/tag/v4.0.0" target="_blank" rel="noopener noreferrer" class="">version 4</a>, I’m pleased to announce that <a href="https://github.com/bitterblossomio/one-spa" target="_blank" rel="noopener noreferrer" class="">one-spa</a> is expanding that effort so that <strong><em>individual components</em></strong> written with different frameworks can interoperate. It is new terrain for the one-spa community, which previously had focused on getting large applications to interoperate with each other, instead of the individual components.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="another-way-to-do-framework-agnostic-components">Another way to do framework agnostic components?<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#another-way-to-do-framework-agnostic-components" class="hash-link" aria-label="Direct link to Another way to do framework agnostic components?" title="Direct link to Another way to do framework agnostic components?" translate="no">​</a></h2>
<p>For those familiar with <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" target="_blank" rel="noopener noreferrer" class="">web components</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements" target="_blank" rel="noopener noreferrer" class="">custom elements</a>, you may be wondering why a JavaScript library would try to do what browsers are starting natively to do.</p>
<p>And as one of the contributors to the custom elements polyfill, let me be the first one to say that we did not make this decision lightly.</p>
<p>If you’re interested in diving into the details, check out <a href="https://medium.com/canopy-tax/one-companys-relationship-with-custom-elements-d360baf3b253" target="_blank" rel="noopener noreferrer" class="">One Company’s Relationship With Custom Elements</a>, which explains some of the difficulties we’ve been through with web components and custom elements.</p>
<p>TLDR: React and some other frameworks don’t interop with custom elements very well. Additionally dealing with inner HTML, attributes vs properties, and customized builtins can be a pain.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="okay-but-you-havent-told-me-what-a-one-spa-parcel-is">Okay but you haven’t told me what a one-spa parcel is<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#okay-but-you-havent-told-me-what-a-one-spa-parcel-is" class="hash-link" aria-label="Direct link to Okay but you haven’t told me what a one-spa parcel is" title="Direct link to Okay but you haven’t told me what a one-spa parcel is" translate="no">​</a></h2>
<p>A parcel is one-spa’s way of building a component in one framework and using it in another.</p>
<p>To implement a parcel, just create a JavaScript object that has 3–4 functions on it. We call this JavaScript object a <em>parcel config</em> and there are three required functions to implement: bootstrap, mount, and unmount. A fourth function, update, is optional.</p>
<p>Each of the functions will be called by one-spa at the right time, but the parcel config will control what happens. In other words, one-spa controls the “when,” but the parcel config controls the “what” and the “how.”</p>
<p>Once you’ve implemented the parcel config, simply call oneSpa.mountRootParcel(parcelConfig, parcelProps) to mount it. This is the key to what makes parcels framework agnostic — regardless of whether the parcel config is implemented with React, Angular, Vue, or anything else, to use the parcel you always just call mountRootParcel().</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-few-more-specifics">A few more specifics<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#a-few-more-specifics" class="hash-link" aria-label="Direct link to A few more specifics" title="Direct link to A few more specifics" translate="no">​</a></h2>
<p>We’ve glossed over a few things that I want to touch on real quick:</p>
<ul>
<li class="">
<p><strong>How do you implement the lifecycle functions on the parcel config?</strong></p>
<p>Use a helper library for your framework of choice. <a href="https://github.com/bitterblossomio/one-spa-react" target="_blank" rel="noopener noreferrer" class="">one-spa-react</a>, <a href="https://github.com/bitterblossomio/one-spa-angular" target="_blank" rel="noopener noreferrer" class="">one-spa-angular</a> (for angular@2+), <a href="https://github.com/bitterblossomio/one-spa-angularjs" target="_blank" rel="noopener noreferrer" class="">one-spa-angularjs</a>, <a href="https://github.com/bitterblossomio/one-spa-vue" target="_blank" rel="noopener noreferrer" class="">one-spa-vue</a>, and <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/one-spa-ecosystem.md" target="_blank" rel="noopener noreferrer" class="">others</a> will implement the entire parcel config for you.</p>
</li>
<li class="">
<p><strong>What are the props you pass to mountRootParcel()?</strong></p>
<p>The props passed as the second argument to oneSpa.mountRootParcel(parcelConfig, parcelProps) are an object with one required prop and as many custom props as you’d like. The required prop is domElement, which tells the parcel where to mount. And the custom props get passed through to the parcel config lifecycle functions.</p>
</li>
<li class="">
<p><strong>How do you re-render and unmount a parcel?</strong></p>
<p>The oneSpa.mountRootParcel() function returns a parcel object that lets you re-render and unmount the parcel whenever you’d like to.</p>
<iframe src="https://medium.com/media/b2d981b380b937009f7ce84e1cc2d753" frameborder="0"></iframe>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="syntactic-sugar-makes-this-easier">Syntactic sugar makes this easier<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#syntactic-sugar-makes-this-easier" class="hash-link" aria-label="Direct link to Syntactic sugar makes this easier" title="Direct link to Syntactic sugar makes this easier" translate="no">​</a></h2>
<p>Calling all of those functions manually might get annoying. So let’s make it easier. Here’s an example of some syntactic sugar for React. Similar features will be added soon for Angular, Vue, and other frameworks.</p>
<iframe src="https://medium.com/media/9b5904d3423359cb2eef410f9ee35648" frameborder="0"></iframe>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-hard-is-it-to-try-this-out">How hard is it to try this out?<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#how-hard-is-it-to-try-this-out" class="hash-link" aria-label="Direct link to How hard is it to try this out?" title="Direct link to How hard is it to try this out?" translate="no">​</a></h2>
<p>You can get started with parcels immediately, without using the rest of one-spa. To do so, either npm install or script tag one-spa, then call mountRootParcel with your first parcel config.</p>
<p>You can also check out <a href="https://codepen.io/joeldenning/pen/qKVoQg?editors=0010#0" target="_blank" rel="noopener noreferrer" class="">this codepen example</a> to start out.</p>
<p>And if you are already a user of <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/applications.md" target="_blank" rel="noopener noreferrer" class="">one-spa applications</a>, parcels mean that your applications can mount and unmount shared functionality whenever you want them to. Since parcels don’t have <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/configuration#activity-function" target="_blank" rel="noopener noreferrer" class="">activity functions</a>, you don’t have to set up routes for them.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="let-us-know-what-you-think">Let us know what you think!<a href="https://one-spa.js.org/blog/2018/06/19/one-spa-parcels-explained#let-us-know-what-you-think" class="hash-link" aria-label="Direct link to Let us know what you think!" title="Direct link to Let us know what you think!" translate="no">​</a></h2>
<p>We’d love to get your feedback on parcels. What do you think of this new way of framework interop? Is the implementation easy to understand? Are parcels useful for you or do they not quite fit into what you’re trying to accomplish?How hard was it for you to try out?</p>
<p>Check out the <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/parcels.md" target="_blank" rel="noopener noreferrer" class="">official docs</a> for more examples, explanations, and <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/parcels-api.md" target="_blank" rel="noopener noreferrer" class="">api documentation</a>.</p>
<p>And let us know your thoughts in a <a href="https://github.com/bitterblossomio/one-spa/issues" target="_blank" rel="noopener noreferrer" class="">Github issue</a>!</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[A step-by-step guide to one-spa]]></title>
        <id>https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa</id>
        <link href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa"/>
        <updated>2016-12-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Running Angular 1, React, Angular 2, and Vue.js side by side sounds pretty cool. And it seems appealing to have multiple applications coexisting on the same page, each lazily loaded.]]></summary>
        <content type="html"><![CDATA[<p>Running Angular 1, React, Angular 2, and Vue.js side by side sounds pretty cool. And it seems appealing to have multiple applications coexisting on the same page, each lazily loaded.</p>
<p>But using <a class="" href="https://one-spa.js.org/">one-spa</a> for the first time can be tricky because you’ll come across terms like “application lifecycles”, “root application”, “loading function”, “child application”, and “activity function.”</p>
<p>This blog post will take you through setting things up and what choices you have when using one-spa. It’s based on a real migration from an Angular 1 monolith to an Angular 1, React, and Svelte polyglot.</p>
<p>If you’d like to jump straight to a fully working, self contained code example, check out this <a href="https://github.com/joeldenning/simple-single-spa-webpack-example" target="_blank" rel="noopener noreferrer" class="">webpack one-spa starter project</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-one-choose-a-module-loader">Step One: choose a module loader.<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#step-one-choose-a-module-loader" class="hash-link" aria-label="Direct link to Step One: choose a module loader." title="Direct link to Step One: choose a module loader." translate="no">​</a></h2>
<p>Your module loader / bundler is the library you’ll use to lazy load code. I recommend either <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="">Webpack</a> or <a href="https://jspm.io/" target="_blank" rel="noopener noreferrer" class="">JSPM</a>, if you’re starting from scratch.</p>
<p>If you go with Webpack, try to use Webpack 2 if you can, since it has <a href="https://webpack.js.org/guides/migrating/#code-splitting-with-es2015" target="_blank" rel="noopener noreferrer" class="">support for promise-based lazy loading</a>. This will make things easier for you later on, since one-spa requires that your <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/root-application.md#loading-function" target="_blank" rel="noopener noreferrer" class="">loading functions</a> return promises. If you can’t use Webpack 2, getting one-spa to lazy load your code with Webpack 1 will require some boilerplate code.</p>
<p>JSPM/SystemJS has worse documentation than Webpack, but is a great solution for module loading if you can get past that. I recommend using jspm@0.17 — it’s still in beta but has been worked on for over a year and has proven stable enough to use in production.</p>
<p>If you’re struggling to decide between the two, then ask yourself the following: Do I want multiple completely separate bundles? If you don’t, I recommend Webpack because it has better docs, a larger community, and fewer gotchas. Otherwise, I’d go with JSPM, since Webpack has no plans to support dynamic runtime loading <a href="https://twitter.com/TheLarkInn/status/789968589419745280" target="_blank" rel="noopener noreferrer" class="">(See tweet below from Mr. Larkin, himself)</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-two-create-a-brand-new-html-file">Step Two: create a brand new HTML file<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#step-two-create-a-brand-new-html-file" class="hash-link" aria-label="Direct link to Step Two: create a brand new HTML file" title="Direct link to Step Two: create a brand new HTML file" translate="no">​</a></h2>
<p>The next step is to create what one-spa calls your <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/root-application.md" target="_blank" rel="noopener noreferrer" class="">“root application.”</a> Really your root application is just the stuff that initializes one-spa, and it starts with an HTML file.</p>
<p>Even if you’ve got an existing project that already has it’s own HTML file, I recommend starting fresh with a new HTML file. That way, there is a clear distinction between what is in your root application (shared between all apps) and what is in a child application (not shared with everything).</p>
<p>You’ll want to keep your root application as small as possible, since it’s sort of the master controller of everything and could become a bottleneck. You don’t want to be constantly changing both the root application and the child applications.</p>
<p>So for now, just have a <code>&lt;script&gt;</code> to a single JavaScript file (root-application.js), which will be explained in Step Three.</p>
<p>Since Webpack is probably the more common use case, my code examples from here on will assume that you’re using Webpack 2. The equivalent Webpack 1 or JSPM code has all the same concepts and only some minor code differences.</p>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token doctype punctuation" style="color:rgb(199, 146, 234);font-style:italic">&lt;!</span><span class="token doctype doctype-tag" style="color:rgb(199, 146, 234);font-style:italic">doctype</span><span class="token doctype" style="color:rgb(199, 146, 234);font-style:italic"> </span><span class="token doctype name" style="color:rgb(199, 146, 234);font-style:italic">html</span><span class="token doctype punctuation" style="color:rgb(199, 146, 234);font-style:italic">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">html</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">head</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">meta</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">charset</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">utf-8</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">meta</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">name</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">viewport</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">content</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">width=device-width</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">title</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain">A one-spa application</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">title</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">head</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">body</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">div</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">id</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">cool-app</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">div</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">script</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">root-application.js</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">script</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">body</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">html</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-three-register-an-application">Step Three: register an “application”<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#step-three-register-an-application" class="hash-link" aria-label="Direct link to Step Three: register an “application”" title="Direct link to Step Three: register an “application”" translate="no">​</a></h2>
<p>Now it’s time to finish up your root application by writing your “root-application.js” file. The primary purpose of root-application.js is to call <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/root-application.md#declaring-child-applications" target="_blank" rel="noopener noreferrer" class="">oneSpa.registerApplication(..)</a> for each of the applications that will be managed by one-spa.</p>
<p>If you’re into analogies, you can think of one-spa as the operating system for your single page application, managing which “processes” (or “child applications”) are running at any given time. At any moment, some of the child applications will be active on the DOM and others will not. As the user navigates throughout the app, some applications will be unmounting from the DOM and others will be mounting to the DOM.</p>
<p>Another way to look at it is that one-spa is a master router on top of your other routers.</p>
<p>To do this, first <code>npm install one-spa</code> and then call the <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/root-application.md#declaring-child-applications" target="_blank" rel="noopener noreferrer" class="">registerApplication</a> function:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> registerApplication</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> start </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Register your first application with one-spa. More apps will be registered as you create them</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">registerApplication</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"cool-app"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> loadCoolApp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> isCoolAppActive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Tell one-spa that you're ready for it to mount your application to the DOM</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// This is a "loading function"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">loadCoolApp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">import</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"./cool-app/cool.app.js"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// This is an "activity function"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isCoolAppActive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(191, 199, 213)">window</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">hash</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">startsWith</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"#/cool"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>Because one-spa is <em>so very</em> cool, we’ve created an app called “cool-app” that will be lazy loaded and mounted to the DOM whenever the url hash starts with <code>#/cool</code>.</p>
<p>The <code>loadCoolApp</code> function is what one-spa calls a loading function. Inside of it, the <code>import</code> introduces a code splitting point — Webpack will create separate code chunks that will be lazy loaded by one-spa.</p>
<p>For your specific project, you probably won’t have a hash prefix of “cool”, but I recommend establishing some kind of convention that makes it easy to determine which apps are active. This will simplify the maintenance of your activity functions, as you add more and more child applications.</p>
<p>If you’re going to start out with just one child application, then it might make sense to implement the activity function as <code>() =&gt; true</code>. You can worry about getting fancier once you have more than one application.</p>
<p>The last thing is to call <code>start()</code>. This is something you <strong>must do for things to work.</strong> The purpose is to give control over timing and performance. But until that is a concern, <code>start</code> is just one of those things you do, and then maybe <a href="https://github.com/bitterblossomio/one-spa/blob/master/docs/one-spa-api.md#start" target="_blank" rel="noopener noreferrer" class="">read about it</a> later if you ever need to.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-four-create-appjs-file">Step Four: create “.app.js” file<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#step-four-create-appjs-file" class="hash-link" aria-label="Direct link to Step Four: create “.app.js” file" title="Direct link to Step Four: create “.app.js” file" translate="no">​</a></h2>
<p>When you open up your index.html file in the browser, you’ll now see….. a blank screen! We’re really close, but there’s one crucial step left: building your app.js file.</p>
<p>After that, you’ll have everything working for your first one-spa application.</p>
<p>An app.js file is a configuration file that you create for each child application. It is the code that is lazy loaded when your activity function returns true.</p>
<p>There are three things that you need to implement in the app.js file:</p>
<ol><li><a href="" target="_blank" rel="noopener noreferrer">A bootstrap lifecycle</a></li><li><a href="" target="_blank" rel="noopener noreferrer">A mount lifecycle</a></li><li><a href="" target="_blank" rel="noopener noreferrer">An unmount lifecycle</a></li></ol>
<p>A “lifecycle” is a function or array of functions that will be called by one-spa; you export these from the app.js file. Each function must return a Promise so that one-spa knows when it is completed.</p>
<p>Here is a simple example:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// one-spa will import this file and call the exported lifecyle functions</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> user</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">bootstrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">fetch</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/api/users/0"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">then</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">response</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">then</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">user </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">mount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* This is normally where you would have your framework-specific code like</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   * ReactDOM.render or angular.bootstrap(). The fact that you can put *anything*</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   * into this function is what makes one-spa so powerful -- any framework</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   * can implement a "mount" and "unmount" to become a one-spa application.</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(255, 203, 107)">Promise</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">then</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token dom variable" style="color:rgb(191, 199, 213)">document</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">getElementById</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"user-app"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">innerHTML</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string html language-html"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token template-string html language-html">        </span><span class="token template-string html language-html tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token template-string html language-html tag" style="color:rgb(255, 85, 114)">div</span><span class="token template-string html language-html tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token template-string html language-html"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token template-string html language-html">          Hello </span><span class="token template-string html language-html interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string html language-html interpolation">user</span><span class="token template-string html language-html interpolation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token template-string html language-html interpolation property-access">name</span><span class="token template-string html language-html interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string html language-html">!</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token template-string html language-html">        </span><span class="token template-string html language-html tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token template-string html language-html tag" style="color:rgb(255, 85, 114)">div</span><span class="token template-string html language-html tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token template-string html language-html"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token template-string html language-html">      </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">unmount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Real world use cases would be something like ReactDOM.unmountComponentAtNode()</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   * or vue.$destroy()</span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">   */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(255, 203, 107)">Promise</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">then</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token dom variable" style="color:rgb(191, 199, 213)">document</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">getElementById</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"user-app"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">innerHTML</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>At this point, you might be seeing the <code>document.getElementById</code> and <code>innerHTML =</code> and worry that you’ve been duped — maybe one-spa is really just a poor excuse for a ui component framework.</p>
<p>And really, don’t we already have a lot of different ways to write UI components?</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-all-of-those-frameworks-to-work-together">Getting all of those frameworks to work together.<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#getting-all-of-those-frameworks-to-work-together" class="hash-link" aria-label="Direct link to Getting all of those frameworks to work together." title="Direct link to Getting all of those frameworks to work together." translate="no">​</a></h3>
<p><em>Using multiple frameworks</em> is where one-spa really shines. It is not a ui framework itself, but a framework for using other frameworks.</p>
<p>Each child application can be written in any framework, so long as it implements application lifecycle functions. Then the mini-apps cooperate to form the entire single page application.</p>
<p>So going back to our previous example, we could choose to write our “cool.app.js” as an Angular 1 app, and choose something else for future apps:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports">oneSpaAngularJS</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa-angularjs"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports">angular</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"angular"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"./app.module.js"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"./routes.js"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(130, 170, 255)">domElementGetter</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(191, 199, 213)">document</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">getElementById</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"cool-app"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> angularLifecycles </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">oneSpaAngularJS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  angular</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  domElementGetter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">mainAngularModule</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"one-spa-app"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">uiRouter</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">preserveGlobal</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> bootstrap </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  aboutToBootstrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  angularLifecycles</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">bootstrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  doneBootstrapping</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> mount </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">angularLifecycles</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">mount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> unmount </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">angularLifecycles</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">unmount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">aboutToBootstrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(255, 203, 107)">console</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"about to bootstrapping"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(255, 203, 107)">Promise</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">doneBootstrap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(255, 203, 107)">console</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"finished bootstrapping"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name" style="color:rgb(255, 203, 107)">Promise</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></div></code></pre></div></div>
<p>In this example, we use a helper library called <a href="https://github.com/bitterblossomio/one-spa-angularjs" target="_blank" rel="noopener noreferrer" class="">one-spa-angularjs</a> which abstracts away the specifics of initializing Angular 1 apps. This blogpost doesn’t show you the <code>app.module.js</code> or <code>routes.js</code> files, but you can see an example implementation <a href="https://github.com/bitterblossomio/one-spa-examples/tree/master/src/angularJS" target="_blank" rel="noopener noreferrer" class="">here</a>.</p>
<p>The pattern is to call <code>oneSpaAngularJS</code> at the very beginning, which returns <code>bootstrap</code>, <code>mount</code>, and <code>unmount</code> lifecycle functions for you.</p>
<p>You might notice that this time the lifecycles are exported as arrays of functions instead of just functions — you can choose whichever works best for you.</p>
<p>The advantage of exporting an array of functions is that you can add in your own custom behavior (like <code>aboutToBootstrap</code> and <code>doneBootstrap</code>) that will run before or after the Angular 1 lifecycles. When you export an array, each item in the array must be a function that returns a promise. One Spa will wait for each promise to resolve, in order, before calling the next function in the array.</p>
<p>To learn more about one-spa helper libraries, check out these github projects:</p>
<ul><li><a href="https://github.com/bitterblossomio/one-spa-angularjs" target="_blank" rel="noopener noreferrer">one-spa-angularjs</a></li><li><a href="https://github.com/bitterblossomio/one-spa-angular" target="_blank" rel="noopener noreferrer">one-spa-angular</a></li><li><a href="https://github.com/bitterblossomio/one-spa-react" target="_blank" rel="noopener noreferrer">one-spa-react</a></li><li><a href="https://github.com/bitterblossomio/one-spa-vue" target="_blank" rel="noopener noreferrer">one-spa-vue</a></li><li><a href="https://github.com/bitterblossomio/one-spa-svelte" target="_blank" rel="noopener noreferrer">one-spa-svelte</a></li><li><a href="https://github.com/bitterblossomio/one-spa-preact" target="_blank" rel="noopener noreferrer">one-spa-preact</a></li></ul>
<p>You can also see a fully working example of an angular app coexisting with other apps at the <a href="https://github.com/bitterblossomio/one-spa-examples" target="_blank" rel="noopener noreferrer" class="">one-spa-examples</a> repo or the <a href="http://one-spa.surge.sh/" target="_blank" rel="noopener noreferrer" class="">live demo</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-five-test-it-out">Step Five: test it out!<a href="https://one-spa.js.org/blog/2016/12/16/a-step-by-step-guide-to-one-spa#step-five-test-it-out" class="hash-link" aria-label="Direct link to Step Five: test it out!" title="Direct link to Step Five: test it out!" translate="no">​</a></h2>
<p>Refresh your page and you should now have a functioning one-spa application!</p>
<p>Try navigating to a url that your child app is active for (<code>#/cool</code>) and then navigating away from it. When you do so, the page will not refresh but you should see your application mount itself to the DOM and then unmount.</p>
<p>If you run into problems, try to narrow down whether the problem is in the root application or in the child application. Is your root application being executed? Are the declareChildApplication calls being made? Have you called <code>start()</code>? Is there a network request to download the code for your child application? Is your child application's <code>bootstrap</code> lifecycle being called? What about <code>mount</code>?</p>
<img src="https://cdn-images-1.medium.com/max/1600/1*WMFuo-hz-Q31UVbTHAx4lw.png" alt="cdn-images-1">
<p>It may be helpful to add a navigation menu, so you can verify everything mounts and unmounts to the DOM correctly. If you want to level up your one-spa skills even more, make the navigation menu an entire child application whose activity function is <code>() =&gt; true</code>. An example that does just that is found <a href="https://github.com/bitterblossomio/one-spa-examples/blob/master/src/one-spa-examples.js#L3" target="_blank" rel="noopener noreferrer" class="">here</a> and <a href="https://github.com/bitterblossomio/one-spa-examples/blob/master/src/navbar/navbar.app.js" target="_blank" rel="noopener noreferrer" class="">here</a>.</p>
<p>While you are verifying that everything is working, keep in mind that each application goes through five phases:</p>
<img src="https://cdn-images-1.medium.com/max/1600/1*utKlcxBkDXfQAQR52B0hAA.png" alt="an applications's lifecycle">
<p>Conclusion</p>
<p>As you get your feet wet, you’ll probably run into some (hopefully small) hiccups setting things up. When this tutorial is not enough, there are other resources on <a href="https://github.com/bitterblossomio/one-spa" target="_blank" rel="noopener noreferrer" class="">Github</a> and here in the <a class="" href="https://one-spa.js.org/docs/building-applications">docs</a>.</p>
<p>One Spa is still a relatively new thing, and we’d love to hear your feedback and questions. We welcome contributions from everyone.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[A Case for SOA in the Browser]]></title>
        <id>https://one-spa.js.org/blog/2016/02/26/a-case-for-soa-in-the-browser</id>
        <link href="https://one-spa.js.org/blog/2016/02/26/a-case-for-soa-in-the-browser"/>
        <updated>2016-02-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[So you are a web-developer. You write a lot of JavaScript. You have a large single-page application (SPA) with features to add and bugs to maintain. Over time the application grows in size and complexity. It becomes more difficult to modify one portion of the SPA without breaking another portion.]]></summary>
        <content type="html"><![CDATA[<p>So you are a web-developer. You write a lot of JavaScript. You have a large single-page application (SPA) with features to add and bugs to maintain. Over time the application grows in size and complexity. It becomes more difficult to modify one portion of the SPA without breaking another portion.</p>
<p>The company is growing and you are looking for ways to scale the team and code-base. You add unit tests. You add a linter. You add continuous integration. You modularize the code with ES2015 modules, webpack, and npm. Eventually you even introduce new, independent SPAs with each SPA being owned and deployed by independent squads. Congratulations, you have successfully introduced service-oriented architecture on the front-end, or have you?</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-service-oriented-architecture">What is Service-oriented Architecture?<a href="https://one-spa.js.org/blog/2016/02/26/a-case-for-soa-in-the-browser#what-is-service-oriented-architecture" class="hash-link" aria-label="Direct link to What is Service-oriented Architecture?" title="Direct link to What is Service-oriented Architecture?" translate="no">​</a></h2>
<p>The fundamental concept behind service-oriented architecture is a service. A service is an isolated piece of code which can only be interacted with through its API. Unlike a shared library, a service itself can be deployed independently of its consumers. Think of a back-end API. The API is the service and the browser is the consumer. The API is deployed independently of the front-end application. There is also only one deployed version of the API available at a URL.</p>
<p>Contrast a service to a shared library. A shared library is a piece of code that is bundled and deployed with your code. For example, libraries such as Express, Lodash, and React are all shared libraries included in your application’s distributable. Upgrading a version of a shared library requires a new deployment of that distributable.</p>
<p>Service-oriented architecture is an approach to building software where the application is composed of many independent and isolated services. Those services are independently deployable, generally non-versioned, and auto discoverable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-service-oriented-architecture-on-the-front-end">Why Service-oriented Architecture on the Front-end?<a href="https://one-spa.js.org/blog/2016/02/26/a-case-for-soa-in-the-browser#why-service-oriented-architecture-on-the-front-end" class="hash-link" aria-label="Direct link to Why Service-oriented Architecture on the Front-end?" title="Direct link to Why Service-oriented Architecture on the Front-end?" translate="no">​</a></h2>
<p>The benefits of SOA can be illustrated with a real life example. Consider an organization with multiple single page applications. The first application is external to the customers and the second is internal, yet both applications share common functionality. That functionality includes among other things, authentication and error logging.</p>
<img src="https://cdn-images-1.medium.com/max/1600/1*itLASVdD-5a3fm56hfltYQ.png" alt="cdn-images-1">
<p style="color:gray;font-size:15px;font-style:italic">Shared libraries between two separate applications. <strong>App 1</strong> depends upon shared libs <strong>a</strong>, <strong>b</strong>, and <strong>c</strong>. <strong>App 2</strong> depends upon only shared libs <strong>a</strong> and <strong>b</strong>.</p>
<p>Overall the design looks good. The code is modularized and shared. The complexities arrive when we start to upgrade the code to different versions. For example, after a short period of time, <strong>App 2</strong> (being internal only) is upgraded to a new beta version of the shared lib <strong>b</strong>. Because the shared <strong>a</strong> also depends upon <strong>b</strong> (and we don’t want multiple versions of <strong>b</strong> bundled) we also create a new version of <strong>a</strong>. This one change causes a rebuild and deploy of three separate pieces of code: <strong>App 2</strong> and shared libs <strong>a</strong> and <strong>b</strong>. Our dependency structure is no longer quite so simple.</p>
<img src="https://cdn-images-1.medium.com/max/1600/1*T5YHqkoZApSvC32jVS0osw.png" alt="cdn-images-2">
<p style="color:gray;font-size:15px;font-style:italic">In reality, a duplicate instance of lib <strong>a</strong> and <strong>b</strong> exist in both apps. Each app does not point to the same instance of the shared libraries, even when they are the same version. This is more noticeable when the shared libraries have separate versions.</p>
<p>Now imagine a bug in both versions of shared lib <strong>b</strong>. In order to fix the problem, you will have to republish both versions of <strong>a</strong> and <strong>b</strong> as well as <strong>c</strong>. Also <strong>App 1</strong> and <strong>App 2</strong> will have to be re-deployed. That is five new versions to publish and two apps to redeploy, all to fix one bug. All downstream dependencies have to be redeployed when a single library is changed. This is deploy dependency hell.</p>
<p>Service oriented architecture avoids these problems in a couple ways. Instead of bundling common dependencies, common code is shared through independent services. Services are not bundled, but rather loaded at run time. This also means that front-end services are not versioned (just like a back-end API). Both <strong>App 1</strong> and <strong>App 2</strong> load the exact same code for a front-end service.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introducing-sofe">Introducing sofe<a href="https://one-spa.js.org/blog/2016/02/26/a-case-for-soa-in-the-browser#introducing-sofe" class="hash-link" aria-label="Direct link to Introducing sofe" title="Direct link to Introducing sofe" translate="no">​</a></h2>
<p>Built upon the new ECMAScript module specification, sofe is a JavaScript library that enables independently deployable JavaScript services to be retrieved at run-time in the browser. Because the new module specification isn’t available within today’s browsers, sofe relies upon <a href="https://github.com/systemjs/systemjs" target="_blank" rel="noopener noreferrer" class="">System.js</a> to load services at run-time.</p>
<p>You can load a sofe service either with static or asynchronous imports.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Static imports</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports">auth</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"auth-service!sofe"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> user </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> auth</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">getLoggedInUser</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Asynchronous imports</span><span class="token plain"></span><br></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token maybe-class-name">System</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword module" style="font-style:italic">import</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"auth-service!sofe"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">then</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">auth</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> auth</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">getLoggedInUser</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></div></code></pre></div></div>
<p>The real power behind sofe is that services are resolved at run-time, making them unversioned. If <strong>auth-service</strong> is redeployed, it is immediately made available to all upstream dependencies. The above scenario becomes much easier to resolve because there is only one version of each shared library as services. This is powerful because it allows you to deploy once, update everywhere. Also because the code is loaded at run-time, we can also enable developer tools to override what service is loaded into your application. Or in other words, you can test code on production without actually deploying to production.</p>
<img src="https://cdn-images-1.medium.com/max/1600/1*o7IS8yKgYKSDc2w7VpyZFw.png" alt="cdn-images-2">
<p style="color:gray;font-size:15px;font-style:italic">The common dependencies are now services that are independent from the application code. Because services are unversioned, the dependency structure is again flat. Each service can individually be deployed and be available to every upstream dependency.</p>
<p>Obviously not all front-end code should be a service. Services have their own challenges. Specifically your code has to stay backwards compatible. But code can’t always be backwards compatible. Sometimes there needs to be breaking changes. The same problem exists for back-end services. A back-end API has to stay backwards compatible. Breaking changes on the back-end are generally solved by either creating an entirely new (versioned) API or implementing feature toggles within the API itself. The same solution applies to sofe services. An entirely new sofe service can be deployed or feature toggles can exist inside the front-end service. However it is solved, the key point is that services exist outside your application within their own distributable.</p>
<p>Another potential problem for sofe services is performance. Because they are loaded at run-time, performance can become a concern if you synchronously load too many services during bootstrap. Performance degradation can be mitigated by asynchronously loading larger services after the application bootstraps. Despite these challenges, there are many benefits to services on the front-end. The most exciting thing about sofe is there is now an option for services in the browser. You can decide what should and shouldn’t be a service.</p>
<p>Getting started with sofe requires only System.js. But to help you get started we have built sofe to work with a variety of technologies, including webpack, Babel, jspm, and the Chrome Developer Tools. Sofe is also actively used in production. We would love feedback on sofe and a number of open source projects that have been built around it. As you approach your next front-end project or look to improve your existing app, consider how it might benefit from service oriented architecture.</p>
<p>Read more about how to get started with sofe <a href="https://github.com/CanopyTax/sofe" target="_blank" rel="noopener noreferrer" class="">here</a>.</p>]]></content>
    </entry>
</feed>