create-single-spa
Single-spa offers a CLI for those who prefer autogenerated and managed configurations for webpack, babel, jest, etc. You do not have to use the CLI in order to use single-spa.
The CLI is called create-single-spa
(Github link). It is primarily intended for the creation of new projects, but may also be useful for migrating existing projects (especially migrating CRA or frameworkless projects).
Installation and Usage
If you wish to have create-single-spa globally available, run the following in a terminal
npm install --global create-single-spa
# or
yarn global add create-single-spa
Then run the following:
create-single-spa
Alternatively, you may use create-single-spa without global installation:
npm init single-spa
# or
npx create-single-spa
# or
yarn create single-spa
This will open up a CLI prompt asking you what kind of project you want to create or update.
CLI arguments
You may pass arguments to create-single-spa like so:
# Different ways of doing the same thing
create-single-spa --framework react
npm init single-spa --framework react
npx create-single-spa --framework react
yarn create single-spa --framework react
Here are the available CLI options:
--dir
You may specify which directory create-single-spa runs in through either of the following ways:
# Two ways of doing the same thing
create-single-spa my-dir
create-single-spa --dir my-dir
--moduleType
You can specify which kind of microfrontend you are creating with the --moduleType
CLI argument:
create-single-spa --moduleType root-config
create-single-spa --moduleType app-parcel
create-single-spa --moduleType util-module
--framework
You can specify which framework you're using with the --framework
CLI argument. Note that if you specify a framework that you may omit the --moduleType
, as it is inferred to be app-parcel
.
create-single-spa --framework react
create-single-spa --framework vue
create-single-spa --framework angular
--layout
When generating a root config, the --layout
CLI argument indicates that you want to use single-spa-layout in your root config.
--skipInstall
This option skips npm/yarn/pnpm installation during project creation.
Project types
create-single-spa asks you if you'd like to create a single-spa application, a utility module, or a root-config. All three module types assume that you are using the recommended setup.
If you select that you'd like to create a single-spa application, you will be prompted for which framework you'd like to choose. React is implemented with premade configurations for babel + webpack + jest. Angular is implemented with Angular CLI and single-spa-angular. Vue is implemented with Vue CLI and vue-cli-plugin-single-spa.
NPM packages
Within the create-single-spa repo, there are several NPM packages. The following sections document each package:
create-single-spa
The core CLI, which invokes generator-single-spa.
generator-single-spa
A Yeoman generator that prompts the user and then creates files. This is primarily invoked via the create-single-spa CLI, but can also be composed if you'd like to customize it.
single-spa-web-server-utils
The single-spa-web-server-utils
package is a collection of functions that help when implementing a web server for an index.html file. This package can be used to inline import maps into an HTML, which helps with the performance of your application. Additionally, it can be used to modify a browser import map so that it's suitable for usage in NodeJS for dynamic module loading and server rendering (Dynamic Module Loading and Server Rendering)).
The web server utils poll the import map from a URL and generate a browserImportMap
and nodeImportMap
from the response.
Installation
npm install --save single-spa-web-server-utils
# alternatively
yarn add single-spa-web-server-utils
getImportMaps
The getImportMaps
function accepts an object parameter and returns a promise that resolves with an object with two import maps: browserImportMap
and nodeImportMap
. Note that import maps are polled at the specified interval forever until either reset()
or clearAllIntervals()
is called. Import Maps are stored in memory in a javascript variable that exists outside of the getImportMaps
function, so subsequent calls to getImportMaps
will all use the same cache.
const { getImportMaps } = require("single-spa-web-server-utils");
const http = require("http");
const ejs = require("ejs");
const fs = require("fs");
const path = require("path");
const htmlTemplate = ejs.compile(
fs.readFileSync(path.resolve(process.cwd(), "views/index.html"), "utf-8"),
);
http.createServer((req, res) => {
getImportMaps({
// required
// The URL at which the server
url: "https://my-cdn.com/live.importmap",
// optional - defaults to 30000
// The ms to wait when polling the import map
pollInterval: 30000,
// optional - defaults to false
// Whether to allow for import-map-overrides via cookies sent in the request.
// More details about overrides via cookies at
// https://github.com/joeldenning/import-map-overrides/blob/master/docs/api.md#node
allowOverrides: true,
// optional - only needed when allowOverrides is true
// The IncomingMessage from an http server. This is used to gather
// cookies for import-map-overrides
req,
// optional
// This allows you to remove entries from the downloaded import map
// from the returned `nodeImportMap`. This is useful for customizing
// an import map that is used in the browser so that it can be used
// for dynamic NodeJS module loading. Each key is a string import specifier.
// Keys that you return `true` for are preserved in the nodeImportMap.
nodeKeyFilter(key) {
return true;
},
}).then(({ browserImportMap, nodeImportMap }) => {
console.log(browserImportMap, nodeImportMap);
// Example of how to inline a browser import map
const htmlWithInlinedImportMap = htmlTemplate({
importMap: browserImportMap,
});
res.setResponseHeader("Content-Type", "text/html");
res.status(200).send(htmlWithInlinedImportMap);
// Example of how to apply a NodeJS import map
// More info at https://github.com/node-loader/node-loader-import-maps
global.nodeLoader.setImportMapPromise(Promise.resolve(nodeImportMap));
import("module-in-import-map");
});
});
clearAllIntervals
This clears all import map polling intervals that were created via setInterval()
inside of getImportMaps()
. This is useful for tests and for cleaning up memory.
import { clearAllIntervals } from "single-spa-web-server-utils";
clearAllIntervals();
reset
This clears all intervals (see clearAllIntervals), and also clears the in-memory cache of all import maps. In other words, after reset()
is called, getImportMaps()
will always result in a new network request to fetch the import map.
import { reset } from "single-spa-web-server-utils";
reset();