Layout Definition
A layout is a combination of HTMLElements, routes, and single-spa applications. Layout is defined statically in your root config to handle your top level routes and dom elements. Single-spa-layout should not be used outside of the root config; instead, a UI framework (React, Angular, Vue) should handle layouts within the applications.
You may define layouts as either HTML templates or JSON objects. Defining in JSON is supported for organizations who prefer storing their layout definitions in a database instead of code. Both HTML and JSON layouts have the same feature set. However, storing layouts in code is generally preferred and encouraged by default. If you're just getting started with single-spa-layout, we encourage using an HTML template.
Once you define your layout, you should constructRoutes
, constructApplications
, and constructLayoutEngine
.
HTML Layouts
You may define HTML layouts either within your root config's index.html file, or within a javascript string that is parsed as HTML. We generally encourage defining the layout within your root config's index.html file.
To define a layout within your index.html file, create a <template id="single-spa-layout">
element that contains your layout. Within the template, add a <single-spa-router>
element, along with any routes, applications, and dom elements.
Note that HTMLElements defined in your layout are static - there is no way to forcibly re-render or change them.
<!-- index.ejs -->
<html>
<head>
<template>
<single-spa-router>
<div class="main-content">
<route path="settings">
<application name="settings"></application>
</route>
</div>
</single-spa-router>
</template>
</head>
</html>
// You can pass in an HTML string, too, in the browser
const routes = constructRoutes(`
<single-spa-router>
<div class="main-content">
<route path="settings">
<application name="settings"></application>
</route>
</div>
</single-spa-router>
`);
// With a properly configured bundler, you can import the html as a string from another file
import layout from "./microfrontends-layout.html";
const routes = constructRoutes(layout);
JSON Layouts
You may define your layout as JSON, including routes, applications, and arbitrary dom elements.
const routes = constructRoutes({
routes: [
{
type: "route",
path: "settings",
routes: [{ type: "application", name: "settings" }],
},
],
});
Layout Elements
A layout element is an HTMLElement or JSON object that represents either a dom node, route, or application.
<template>
The template
element is only used when defining the layout as HTML. Its purpose is to prevent its contents from being displayed by the browser, since the layout definition should not be visible to user.
<template>
<!-- Define your layout here -->
<single-spa-router></single-spa-router>
</template>
Note that <template>
elements are not fully supported in IE11. However, you do not need to polyfill template elements in order to use them in single-spa-layout. Instead, simply add style="display: none;"
to the template to prevent its contents from being displayed in IE11.
<template style="display: none;">
<!-- Define your layout here -->
<single-spa-router></single-spa-router>
</template>
<single-spa-router>
The single-spa-router
element is required as the top level container of your layout. All attributes are optional.
<single-spa-router
mode="hash|history"
base="/"
disableWarnings
></single-spa-router>
{
"mode": "hash|history",
"base": "/",
"disableWarnings": false,
"containerEl": "#container",
"routes": []
}
Attributes
mode
(optional): A string that must behash
orhistory
that defaults tohistory
. This indicates whether the routes should be matched against the Location pathname or hash.base
(optional): A string URL prefix that will be considered when matching route paths.disableWarnings
(optional): A boolean that turns of single-spa-layout's console warnings when the elements provided are incorrect.containerEl
(optional): A string CSS Selector or HTMLElement that is used as the container for all single-spa dom elements. Defaults tobody
.
<route>
The route
element is used to control which applications and dom elements are shown for a top-level URL route. It may contain HTMLElements, applications, or other routes. Note that the route path is a URL prefix, not an exact match.
<route path="clients">
<application name="clients"></application>
</route>
<route default>
<application name="clients"></application>
</route>
{
"type": "route",
"path": "clients",
"routes": [{ "type": "application", "name": "clients" }],
"default": false
}
Attributes
Routes must either have a path or be a default route.
routes
(required): An array of children elements that will be displayed when the route is activepath
(optional): A path that will be matched against the browser's URL. The path is relative to its parent route (or the base URL). Leading and trailing/
characters are unnecessary and are automatically applied. Paths may contain "dynamic segments" by using the:
character ("clients/:id/reports"
). Single-spa-layout uses single-spa'spathToActiveWhen
function to convert the path string to an activity function. By default, the path is a prefix because it will match when any subroutes of the path match. See theexact
attribute for exact matching.default
(optional): A boolean that determines whether this route will match all remaining URLs that have not been defined by sibling routes. This is useful for 404 Not Found pages. A sibling route is defined as any route with the same nearest-parent-route.exact
(optional, defaults tofalse
): A boolean that determines whether thepath
should be treated as a prefix or exact match. Whentrue
the route does not activate if there are trailing characters in the URL path that are not specified in thepath
attribute.props
: An object of single-spa custom props that will be provided to the application when it is mounted. Note that these can be defined differently for the same application on different routes. You can read more about defining props within your HTML in the docs below.
<application>
The application
element is used to render a single-spa application. Applications may be contained within route elements, or may exist at the top level as applications that will always be rendered. A container HTMLElement will be created by single-spa-layout when the application is rendered. The container HTMLElement is created with an id
attribute of single-spa-application:appName
such that your framework helpers will automatically use it when mounting the application.
The same application may appear multiple times in your layout, under different routes. However, each application can only be defined once per-route.
<!-- Basic usage -->
<application name="appName"></application>
<!-- Use a named loader that is defined in javascript -->
<application name="appName" loader="mainContentLoader"></application>
<!-- Add single-spa custom props to the application. The value of the prop is defined in javascript -->
<application name="appName" props="myProp,authToken"></application>
// Basic usage
{
"type": "application",
"name": "appName"
}
// Use a single-spa parcel as a loading UI
// You may also use Angular, Vue, etc.
const parcelConfig = singleSpaReact({...})
{
"type": "application",
"name": "appName",
"loader": parcelConfig
}
// Use an HTML string as a loading UI
{
"type": "application",
"name": "appName",
"loader": "<img src='loading.gif'>"
}
// Add single-spa custom props
{
"type": "application",
"name": "appName",
"props": {
"myProp": "some-value"
}
}
Attributes
name
(required): The string application name.loader
(optional): An HTML string or single-spa parcel config object. The loader will be mounted to the DOM while waiting for the application's loading function to resolve. You can read more about defining loaders in the docs belowprops
: An object of single-spa custom props that will be provided to the application when it is mounted. Note that these can be defined differently for the same application on different routes. You can read more about defining props within your HTML in the docs below.class
/className
: The CSS class to apply to the container HTML element for this single-spa application. In JSON layouts, useclassName
. In HTML layouts, useclass
.
<fragment>
The fragment
element is used to specify a dynamic server-rendered portion of the template. Fragments are commonly used to inline import maps, add dynamic CSS / fonts, or customize the HTML <head>
metadata. See sendLayoutHTTPResponse for more information about how fragments are rendered. Note that <fragment>
elements only have meaning in server templates, not browser-only templates.
<fragment name="importmap"></fragment>
<fragment name="head-metadata"></fragment>