跳至正文
Wener Notes

Single SPA

约 2 分钟阅读
  • 建议使用单个版本框架
  • 适用于跨框架 - 如果不 跨框架,建议自行封装一个简单的挂载逻辑
Topic应用/applicationparcel工具/utility
路由✅无路由无路由
API定义式 API声明式 API➖
渲染 UI✅✅❌
生命周期single-spa 管理自行管理❌
使用场景核心构建组件多个框架的时候需要公共逻辑

create-single-spa

bash
# http://localhost:9000
# 默认 importmap 是在 html 中
# 开启 importmap 开发工具
# localStorage.setItem("devtools", true);
yarn create single-spa --framework react --moduleType root-config --dir root

yarn create single-spa --framework react --dir dash
# localhost:8500
# http://single-spa-playground.org/playground/instant-test?name=@wener-dash/spa&url=8500
# 默认位置 http://localhost:8500/<OrgName>-<ProjectName>.js
# 例如 http://localhost:8500/wener-spa-dash.js
yarn start --port 8500

yarn create single-spa --framework react --moduleType util-module --dir utils \
  --packageManager yarn --typescript

# react + ts 使用的配置
# yarn add --dev webpack-config-single-spa-react-ts webpack-merge

root-config

  • 单个 html
  • 由服务端生成即可

index

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Root Config</title>
    <!-- 用于不支持 async/await 的浏览器 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/runtime.min.js"></script> -->

    <!--
    This CSP allows any SSL-enabled host, but you should limit these directives further to increase your app's security.
    Learn more about CSP policies at https://content-security-policy.com/#directive
  -->
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self' https: localhost:*; script-src 'unsafe-inline' https: localhost:*; connect-src https: localhost:* ws://localhost:*; style-src 'unsafe-inline' https:; object-src 'none';"
    />
    <meta name="importmap-type" content="systemjs-importmap" />
    <!-- 全局样式 -->
    <link href="https://unpkg.com/antd/dist/antd.min.css" rel="stylesheet" />

    <!-- 公共依赖

    1. System.register (preferred when possible) - https://github.com/systemjs/systemjs/blob/master/docs/system-register.md
    2. UMD - https://github.com/umdjs/umd
    3. Global variable

    参考 https://single-spa.js.org/docs/recommended-setup#sharing-with-import-maps.
  -->
    <script type="systemjs-importmap">
      {
        "imports": {
          "single-spa": "https://cdn.jsdelivr.net/npm/[email protected]/lib/system/single-spa.min.js",
          "react": "https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js",
          "react-dom": "https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js",
          "antd": "https://unpkg.com/[email protected]/dist/antd-with-locales.min.js"
        }
      }
    </script>

    <!-- 使用外部导入映射  -->
    <!-- <script type="systemjs-importmap" src="/importmap.json"></script> -->

    <!-- 本地开发地址 -->
    <script type="systemjs-importmap">
      {
        "imports": {
          "@wener-spa/root-config": "//localhost:9000/wener-spa-root-config.js",
          "@wener-spa/dash": "//localhost:8081/wener-spa-dash.js"
        }
      }
    </script>

    <!-- 本地开发使用 -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/import-map-overrides.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/system.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extras/amd.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extras/named-exports.js"></script>

    <!-- 生产使用
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/import-map-overrides.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/system.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extras/amd.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/extras/named-exports.min.js"></script>
  --></head>
  <body>
    <main></main>
    <script>
      // 启动该模块
      System.import('@wener-spa/root-config');
    </script>
    <!-- 开发工具 - 测试 importmap -->
    <import-map-overrides-full show-when-local-storage="devtools" dev-libs></import-map-overrides-full>
  </body>
</html>

config

TypeScript
import { registerApplication, start } from 'single-spa';

// 注册应用
registerApplication({
  name: '@wener-spa/dash',
  app: () => System.import('@wener-spa/dash'),
  // 前缀匹配的激活路径
  activeWhen: ['/'],
});

// 启动应用
start({
  urlRerouteOnly: true,
});

parcel

entry

TypeScript
import React from 'react';
import ReactDOM from 'react-dom';
// 挂载根组件
import rootComponent from './path-to-root-component.js';
// Note that SingleSpaContext is a [email protected] (if available) context that provides the singleSpa props
import singleSpaReact, { SingleSpaContext } from 'single-spa-react';
const reactLifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent,
  errorBoundary(err, info, props) {
    // https://reactjs.org/docs/error-boundaries.html
    return <div>This renders when a catastrophic error occurs</div>;
  },
});
export const bootstrap = reactLifecycles.bootstrap;
export const mount = reactLifecycles.mount;
export const unmount = reactLifecycles.unmount;

webpack

JavaScript
const webpackMerge = require('webpack-merge');
const singleSpaDefaults = require('webpack-config-single-spa-react-ts');

module.exports = (webpackConfigEnv) => {
  const defaultConfig = singleSpaDefaults({
    orgName: 'wener-spa',
    projectName: 'dash',
    webpackConfigEnv,
  });

  const config = webpackMerge.smart(defaultConfig, {
    // modify the webpack config however you'd like to by adding to this object
  });
  // 添加额外的外部依赖 - 默认会添加 react、react-dom 等
  config.externals.push('antd');
  return config;
};

utility

  • 没有 entry

推荐设置

关联信息

反向链接、本文链接的其他页面和外部资料。

反向链接

  • 乾坤
    笔记 · single-spa

    umijs/qiankun · 微前端框架 · 基于 single-spa 修改 · JS隔离 - 快照、proxy · CSS 隔离 · HTML Entry · Config Entry · 按需加载 · 公共依赖 · 预加载 · 父子通讯

参考资料

GitHub7 条
其他外链6 条
最近更新commit 906e816编辑