微前端架構實戰中-single-spa 篇

第3章 微前端框架 single-spa

https://zh-hans。single-spa。js。org/

single-spa:https://single-spa。js。org/ 是一個實現微前端架構的框架。

在 single-spa 框架中有三種類型的微前端應用:

single-spa-application / parcel:微前端架構中的微應用,可以使用 vue、react、angular 等框架。

single-spa root config:建立微前端容器應用。

utility modules:公共模組應用,非渲染元件,用於跨應用共享 javascript 邏輯的微應用。

3-1 建立容器應用

安裝 single-spa 腳手架工具:

npm install create-single-spa@2。0。3 -g

建立微前端容器應用:

create-single-spa

應用資料夾填寫 container

應用選擇 single-spa root config

組織名稱填寫 study組織名稱可以理解為團隊名稱,微前端架構允許多團隊共同開發應用,組織名稱可以標識應用由哪個團隊開發。應用名稱的命名規則為

@組織名稱/應用名稱

,比如

@study/todos

微前端架構實戰中-single-spa 篇

4。 啟動應用:

cd 。/singletest && npm start

5。 訪問應用:

localhost:9000

微前端架構實戰中-single-spa 篇

3-2 容器預設程式碼解析

src/xx-root-config。js

// 從框架中引入 兩個 方法,下面呼叫import { registerApplication, start } from “single-spa”;/* 註冊微前端應用 1。 name: 字串型別, 微前端應用名稱 “@組織名稱/應用名稱”   2。 app: 函式型別, 返回 Promise, 透過 systemjs 引用打包好的微前端應用模組程式碼 (umd) 3。 activeWhen: 路由匹配時啟用應用*/registerApplication({  name: “@single-spa/welcome”,  app: () =>    System。import(      “https://unpkg。com/single-spa-welcome/dist/single-spa-welcome。js”   ),  activeWhen: [“/”],});

// 當前組織的微應用引入示例// registerApplication({//   name: “@xl/navbar”,//   app: () => System。import(“@xl/navbar”),//   activeWhen: [“/”]// });// start 方法必須在 single spa 的配置檔案中呼叫// 在呼叫 start 之前, 應用會被載入, 但不會初始化, 掛載或解除安裝。start({  // 是否可以透過 history。pushState() 和 history。replaceState() 更改觸發 single-spa 路由  // true 不允許 false 允許 (先了解,有印象)  urlRerouteOnly: true,});

index。ejs

 

 <!—— 匯入微前端容器應用 ——>    <!—— import-map-overrides 可以覆蓋匯入對映 當前專案中用於配合 single-spa Inspector 除錯工具使用。 可以手動覆蓋專案中的 JavaScript 模組載入地址, 用於除錯。——>  

<!—— 用於支援 Angular 應用 ——>  <!—— ——>  <!—— 用於覆蓋透過 import-map 設定的 JavaScript 模組下載地址 ——>    <!—— 判斷是否是本地 ——>  <% if (isLocal) { %>  <!—— 模組載入器 ——>    <!—— systemjs 用來解析 AMD 模組的外掛 ——>    <% } else { %>      <% } %>

 <!—— single-spa 預載入 ——>    <!—— Add your organization‘s prod import map URL to this script’s src ——>  <!—— ——><!—— JavaScript 模組下載地址 此處可放置微前端專案中的公共模組 ——>  <% if (isLocal) { %>    <% } %>

3-3 建立基於 React 的微應用

3-3-1 建立 React 微應用

建立應用:

create-single-spa

,注意組織及專案名字,後面註冊微應用是會用到

應用目錄輸入 todos

框架選擇 react

修改應用埠 && 啟動應用

{  “scripts”: {     “start”: “webpack serve ——port 9002”, }}

啟動應用:

npm start

3-3-2 註冊應用

將 React 專案的入口檔案註冊到基座應用 (容器應用) 中

\container\src\study-root-config。js :

// React —— todos registerApplication({  name: “@study/todos”,  app: () => System。import(“@study/todos”),  activeWhen: [“/todos”]});

指定微前端應用模組的引用地址:

(可以直接訪問對應應用伺服器,有提示 URL 載入地址)

<% if (isLocal) { %>    <% } %>

指定公共庫的訪問地址,預設情況下,應用中的 react 和 react-dom 沒有被 webpack 打包, single-spa 認為它是公共庫,不應該單獨打包。

修改預設應用程式碼,已獨立頁面展示應用內容

container\src\study-root-config。js

// registerApplication({//   name: “@single-spa/welcome”,//   app: () =>//     System。import(//       “https://unpkg。com/single-spa-welcome/dist/single-spa-welcome。js”//     ),//   activeWhen: [“/”],// });// 修改預設應用註冊方式,獨立頁面展示應用內容registerApplication(  “@single-spa/welcome”, () => System。import(    “https://unpkg。com/single-spa-welcome/dist/single-spa-welcome。js” ),  location=>location。pathname === ‘/’);

3-3-3 指定應用渲染位置

micro\container\src\index。ejs

 

 

   <!—— 指定應用展示位置 ——>    
 

   

micro\todos\src\study-todos。js

const lifecycles = singleSpaReact({  React,  ReactDOM,  // 渲染根元件  rootComponent: Root,  // 錯誤邊界函式  errorBoundary(err, info, props) {    // Customize the root error boundary for your microfrontend here。    return null; },  // 指定根元件的渲染位置  domElementGetter:()=>document。getElementById(‘myreact’)});

3-3-4 React 應用程式碼解析

micro\todos\src\study-todos。js

import React from “react”;import ReactDOM from “react-dom”;// single-spa-react 用於建立使用 React 框架實現的微前端應用import singleSpaReact from “single-spa-react”;// 用於渲染在頁面中的根元件 就相當於傳統React應用的App。js檔案import Root from “。/root。component”;const lifecycles = singleSpaReact({  React,  ReactDOM,  // 渲染根元件  rootComponent: Root,  // 錯誤邊界函式  errorBoundary(err, info, props) {    // Customize the root error boundary for your microfrontend here。    // return null;    return ()=>

發生錯誤時此處內容將會被渲染
},  // 指定根元件的渲染位置  domElementGetter:()=>document。getElementById(‘myreact’)});// 暴露必要的生命週期函式export const { bootstrap, mount, unmount } = lifecycles;

3-3-5 React 微前端路由配置

準備好兩個路由元件

micro\todos\src\home。js && micro\todos\src\about。js

import React, { Component } from ‘react’export default class home extends Component {    render() {        return (            

               

什麼是快樂星球

           
      )   }}=========我是兩個元件之間的秀麗華美分割線=============import React from ‘react’function about() {    return (        
           

快樂星球就是學習微前端

       
  )}export default about

micro\todos\src\root。component。js

import React from “react”;// 引入路由相關元件import {BrowserRouter, Switch, Route, Redirect, Link} from “react-router-dom”// 引入元件import Home from ‘。/home’import About from ‘。/about’export default function Root(props) {  // return

{props。name} is mounted! && 拉勾大前端
;  return (    // 使用路由元件,設計基礎路由路徑          
{props。name}
    {/* 設定點選連結,跳轉路由 */}      
       Home |        About      
    {/* 路由展示 */}                                                                           {/* 路由重定向 */}                            
)}

路由檔案已公共模組引入,\micro\container\src\index。ejs

修改 webpack 配置檔案,排除路由模組打包,micro\todos\webpack。config。js

return merge(defaultConfig, {    // modify the webpack config however you‘d like to by adding to this object    externals: [“react-router-dom”]});

3-4 建立基於 Vue 的微應用

3-4-1 建立應用

建立應用:

create-single-spa

專案資料夾填寫 realworld

框架選擇 Vue

生成 Vue 2 專案

因為 vue && vue-router 需要透過公共模組打包,所以,在應用內部需要配置不打包

micro\realworld\vue。config。js

module。exports = {    chainWebpack:config=>{        // 配置不打包 Vue 及 vue-router        config。externals([“vue”,“vue-router”])   }}

修改專案啟動命令:micro\realworld\package。json

“scripts”: {    “serve”: “vue-cli-service serve”,    “start”: “vue-cli-service serve ——port 9003”,    “build”: “vue-cli-service build”,    “lint”: “vue-cli-service lint”,    “serve:standalone”: “vue-cli-service serve ——mode standalone” },

註冊應用:micro\container\src\study-root-config。js

// Vue —— todosregisterApplication({  name: “@study/realworld”,  app: () => System。import(“@study/realworld”),  activeWhen: [“/realworld”],});

micro\container\src\index。ejs

載入 vue && vue-router

匯入應用,應用地址可以直接訪問應用後,在瀏覽器的提示中獲取;

<% if (isLocal) { %>    <% } %>

3-4-2 應用路由配置

\micro\realworld\src\main。js

import Vue from ’vue‘;import singleSpaVue from ’single-spa-vue‘;import App from ’。/App。vue‘;import VueRouter from ’vue-router‘Vue。use(VueRouter)// 路由元件const Foo = { template: “

Foooooo
” }const Bar = { template: “
Barrrrr
” }// 路由規則const routes = [ { path: ’/foo‘, component: Foo }, { path: ’/bar‘, component: Bar },]// 路由例項const router = new VueRouter({ routes, mode: “history”, base: “/realworld” })Vue。config。productionTip = false;const vueLifecycles = singleSpaVue({  Vue,  appOptions: {    // 註冊路由    router,    render(h) {      return h(App, {        props: {          // 元件傳參       },     });   }, },});export const bootstrap = vueLifecycles。bootstrap;export const mount = vueLifecycles。mount;export const unmount = vueLifecycles。unmount;

micro\realworld\src\App。vue

3-5 建立 utility modules

3-5-1 utility 獨立應用建立

用於放置跨應用共享的 JavaScript 邏輯,它也是獨立的應用,需要單獨構建單獨啟動。

建立應用:

create-single-spa

資料夾填寫 tools應用選擇

in-browser utility module (styleguide, api cache, etc)

修改埠,啟動應用, \micro\tools\package。json

“scripts”

: {

“start”

“webpack serve ——port 9005”

}

匯出公共方法 : micro\tools\src\study-tools。js

export function happyStar(who){    console。log(`${who} hahahhahahhah`)    return ’happy star 之 快樂的源泉‘}

在模板檔案中宣告應用模組訪問地址 : micro\container\src\index。ejs

<% if (isLocal) { %>    <% } %>

3-5-2 在 React 應用中使用該方法

MicroFrontends\micro\todos\src\about。js

import React, { useEffect, useState } from “react”;// 自定義鉤子函式function useToolsModule() {  const [toolsModule, setToolsModule] = useState();  useEffect(() => {    // 匯入,非同步promise返回    System。import(“@study/tools”)。then(setToolsModule); }, []);  return toolsModule;}function about() {  var back = “”;  // 呼叫鉤子函式  const toolsModule = useToolsModule();  if (toolsModule) {    // 呼叫共享邏輯的方法    back = toolsModule。happyStar(“React todo”); }  return (    

     

快樂星球就是學習微前端——{back}

   
);}export default about;

3-5-3 在 Vue 應用中使用該方法

micro\realworld\src\main。js

// 路由元件// const Foo = { template: “

猜不到吧
” };import Foo from ’。/components/Foo‘const Bar = { template: “
還是快樂星球啊哈哈哈哈
” };

micro\realworld\src\components\Foo。vue