目前在公司負責多個產品的全端開發,這些產品導向為生產力工具,並可以獨立運行 Standalone mode,根據公司之前與客戶合作的經驗來看,許多客戶是想要同時使用這幾個產品的,那怎麼將這幾個產品整合至一個平台裡,但又不想要改到整個產品架構,這就是這篇文章的出發點。

微服務

把這些產品的後端拆開來看,他的功用很簡單

  • 跟DB進行CRUD
  • 與前端進行API溝通

各後端服務若需要與其他服務進行溝通,是直接call對方的api,不會直接與對方DB對接,讓微服務保有最小運作單位,各團隊的職責很明確。

微前端

當一個產品的頁面會用到其他產品的 component 的時候,直接使用那個產品所開發出來的頁面,不用再重新開發,讓元件一次開發多次使用。但其實reusing component 這觀念在monorepo環境下開發的工程師一定都有,假設今天有個頁面是由四個 services 組合起來,分別為不同團隊開發,不同repositories,要怎麼去使用到其他repository的元件就值得討論了。

demo-page.png

第一種直接硬幹作法:clone對方 repository 當作submodule,不過你要先確保對方使用一樣的框架(React.js, Vue.js, Angular, Svelte…),並且你的repo可能會多很多你用不到的code, package…,並且很難做版控,等等的…。

第二種,使用iframe嵌入他的元件,但你只是要一個元件,沒必要弄成頁面嵌入進來,並且只能透過postMessage做溝通。

第三種就是使用Webpack module federation或Single-SPA等微前端工具將元件分享出來,而你可以直接像是

import { ComponentA } from "your-org/another-service";

的方式直接使用其他產品的元件,並且可以直接傳props進去component,達到很直觀地使用其他團隊已開發過的元件,此外,也可以分享 utilities 出來,例如API requests,並且每個產品都可以使用不同框架開發,而 Webpack 或 Single-SPA 會負責去識別 your-org/another-service,並不會進行 npm install your-org/another-service 的動作。

微服務跟微前端合作起來就會像:

architecture.png

微服務透過API互相溝通,前端元件或是 utils 透過微前端工具分享且使用,不會出現service A的前端直接去與service B後端溝通的事,都透過service B前端分享出來的工具去達到。而我們公司的客戶想要在一個平台(service E)內使用所有已被開發過的產品,就可以直接用微前端整合進service E。

微前端優點

  • 將團隊合作分得更清楚
  • 避免重複開發一樣的東西
  • 不同團隊可以使用不同框架
  • 很簡單就能整合、引入
  • 版本控制,可以選擇你要引入的元件是第幾版的

Webpack module federation

https://webpack.js.org/concepts/module-federation/

透過Webpack 5 提供的 container.ModuleFederationPlugin 將元件分享出來及引入。

Single-SPA

https://single-spa.js.org/

透過Systemjs 的 import maps 去做微前端 bundles 的管理,使用起來會比Webpack module federation 還方便入手,只不過目前瀏覽器支援程度還沒那麼高,並且還要更上層的app (root-config)去管理 import maps。

支援度.webp

Webpack module federation v.s. Single-SPA (import maps)

Webpack module federation 比較適合low level 元件的分享,import maps 比較適合 high level service 的分享,像是頁面。

comparison.webp

總結

雖然一個人要負責這麼多產品開發,又再加上要整合在一起,實在很累XD,但也讓我接觸到怎麼設計這樣服務層級的架構。

若有錯請不吝讓我知道!