Version: 5.x

配置 single-spa

The single-spa root config consists of the following:

这两个根目录下的配置用于启动single-spa应用。

  • 所有微前端应用共享的根 HTML 页面
  • 调用 singleSpa.registerApplication() 的 JavaScript

Index.html文件

内容可参考该示例。注意该文件不包含html元素(div, buttons等),只是为了调用registerApplication()方法。

See this example root config for what a root HTML file looks like.

在使用single-spa时,不必使用SystemJS,不过为了能够独立部署各应用,很多示例和教程会推荐使用SystemJS。

注册应用

你需要先注册应用,这样single-spa才知道在什么时机,如何去初始化、下载、挂载和卸载各应用。我们一般情况下在single-spa的配置文件中进行注册,当然也可以有其他方式(不推荐)。如果在某个应用中注册其他应用,这两个应用不会存在嵌套关系,他们还是同级关系,应用的挂载和下载也还是会依赖各自的触发条件(activity functions)。

我们通过调用registerApplication方法来注册应用。例如:

// single-spa-config.js
import { registerApplication, start } from 'single-spa';
// Simple usage
registerApplication(
'app2',
() => import('src/app2/main.js'),
(location) => location.pathname.startsWith('/app2'),
{ some: 'value' }
);
// Config with more expressive API
registerApplication({
name: 'app1',
app: () => import('src/app1/main.js'),
activeWhen: '/app1',
customProps: {
some: 'value',
}
);
start();

参数

name

registerApplication的第一个参数表示应用名称,name必须是string类型

Loading Function or Application

registerApplication的第二个参数可以是一个Promise类型的 加载函数,也可以是一个已经被解析的应用。

Application as second argument

你可以选择将一个已经被解析过的应用作为registerApplication的第二个参数,这个应用其实是一个包含各个生命周期函数的对象。我们既可以从另外一个文件中引入该对象,也可以在single-spa的配置文件中定义这个对象。

const application = {
bootstrap: () => Promise.resolve(), //bootstrap function
mount: () => Promise.resolve(), //mount function
unmount: () => Promise.resolve(), //unmount function
}
registerApplication('applicationName', application, activityFunction)
加载函数{#loading funtion}

registerApplication的第二个参数必须是返回promise的函数(或"async function"方法)。这个函数没有入参,会在应用第一次被下载时调用。返回的Promise resolve之后的结果必须是一个可以被解析的应用。常见的实现方法是使用import加载:() => import('/path/to/application.js')

激活函数

registerApplication的第三个参数需要是一个纯函数,window.location会作为第一个参数被调用,当函数返回的值为真(truthy)值时,应用会被激活。通常情况下,Activity function会根据window.location/后面的path来决定该应用是否需要被激活。

另外一种场景是single-spa根据顶级路由查找应用,而每个应用会处理自身的子路由。 在以下场景,single-spa会调用应用的activity function

在以下情况下,single-spa将调用每个应用的活动函数:

  • hashchange or popstate事件触发时
  • pushState or replaceState被调用时
  • 在single-spa上手动调用[triggerAppChange] 方法
  • checkActivityFunctions方法被调用时

自定义属性

registerApplication函数可选的第四个参数是 custom props。这个参数会传递给 single-spa 的 lifecycle 函数。自定义属性可以是一个对象,也可以是一个返回Object的函数。如果自定属性是一个函数,函数的参数是应用的名字(application name)和当前window.location

使用对象参数

singleSpa.registerApplication({
name: 'myApp',
app: () => import('src/myApp/main.js'),
activeWhen: ['/myApp', (location) => location.pathname.startsWith('/some/other/path')],
customProps: {
some: 'value',
},
});
singleSpa.registerApplication({
name: 'myApp',
app: () => import('src/myApp/main.js'),
activeWhen: ['/myApp', (location) => location.pathname.startsWith('/some/other/path')],
customProps: (name, location) => ({
some: 'value',
}),
});

config.name

必须是字符串。

config.app

应用的定义,它可以是一个单spa生命周期的对象,加载函数或者与第二个参数相同。

config.activeWhen

可以是激活函数,比如参数API、路径前缀或两者的数组。因为最常见的用例是使用window.location 将其URL前缀进行匹配,所以我们帮你实现了这个方法。

Path prefix

路径前缀会匹配url,允许以下每一种前缀:

'/app1'
✅ https://app.com/app1
✅ https://app.com/app1/anything/everything
🚫 https://app.com/app2
'/users/:userId/profile'
✅ https://app.com/users/123/profile
✅ https://app.com/users/123/profile/sub-profile/
🚫 https://app.com/users//profile/sub-profile/
🚫 https://app.com/users/profile/sub-profile/
'/pathname/#/hash'
✅ https://app.com/pathname/#/hash
✅ https://app.com/pathname/#/hash/route/nested
🚫 https://app.com/pathname#/hash/route/nested
🚫 https://app.com/pathname#/another-hash
['/pathname/#/hash', '/app1']
✅ https://app.com/pathname/#/hash/route/nested
✅ https://app.com/app1/anything/everything
🚫 https://app.com/pathname/app1
🚫 https://app.com/app2

config.customProps

The optional customProps property provides custom props that are passed to the application's single-spa lifecycle functions. The custom props may be either an object or a function that returns an object. Custom prop functions are called with the application name and current window.location as arguments.

Calling singleSpa.start()

start()方法 必须被single-spa配置文件的js调用,这时应用才会被真正挂载。在start被调用之前,应用先被下载,但不会初始化/挂载/卸载。start方法可以协助我们更好提升应用的性能。举个例子,我们可能会马上注册一个应用(为了立刻下载代码),但不能马上就在DOM节点上挂载该应用,而是需要等一个AJAX请求(可能会获取用户的登录信息)完成后,再根据结果进行挂载。这种情况下,最佳实践是先调用registerApplication,等AJAX请求完成后再调用start

//single-spa-config.js
import { start } from 'single-spa';
/*在注册应用之前调用start意味着single-spa可以立即安装应用,无需等待单页应用的任何初始设置。*/
start();
// 注册应用。。。。

同时注册两个路由??

emm...也是可以的。 如果你能用正确的方式来实现,这件事并不可怕。一旦你正确实现了,这将非常非常厉害。一种实现方式是为每个app创建一个<div id="app name"></div>,这样这两个应用就不会同时修改相同的DOM节点了。[考虑一个path变动,同时有两个应用被激活的场景,译者注]

<div>需要一个id,这个id的以single-spa-application前缀开头,后面接着你的应用的名字。比如,如果你的应用名字叫做app-name,就创建一个id为 single-spa-application:app-namediv

一个多应用的的例子看着就像这样:

<div id="single-spa-application:app-name"></div>
<div id="single-spa-application:other-app"></div>