把 Focus Island 抽成一個可以塞進其他網站的 iframe widget
與其在每個網站裡重做一次同樣的功能,不如把 Focus Island 包成一個可以嵌進其他網站的浮動 widget。記錄 iframe 跟 Web Component 的取捨,以及選 iframe 之後的架構草圖與還沒解決的問題。
動機
手上已經有一個 Focus Island,Golang + Gorilla WebSocket 做的即時互動小工具。問題是: 在開發其他網站的過程中,也會想要順手用一下同樣這個功能,但它現在是一個獨立網站, 要用就得切分頁、開新網址,體驗上很打斷節奏。
最直覺的解法是「在每個網站裡都重做一次同樣的功能」,但這樣核心邏輯、資料庫、 WebSocket 連線管理全部要複製一份,之後改一個地方要記得改好幾個地方,維護成本會 隨著網站數量線性增加。更合理的方向是反過來:核心邏輯只留一份在 Focus Island, 其他網站只嵌入一個薄薄的入口,像許多網站右下角那顆客服聊天按鈕一樣——點開浮動 視窗、用完就收起來,真的要用到複雜功能才整個跳轉過去。
兩種包裝方式的取捨
把一個既有網站包成「可以嵌進別的網站」的元件,常見做法有兩種:
| iframe | Web Component(Shadow DOM) | |
|---|---|---|
| 隔離性 | 樣式、JS 執行環境天生隔離,host 網站的 CSS 不會滲進來,反之亦然 | 要靠 Shadow DOM 手動做隔離,仍有邊界情況會漏 |
| 視覺整合度 | 很難跟 host 網站的排版無縫融合,有明顯的「一塊嵌入內容」的邊界感 | 可以做到跟 host 網站幾乎無縫,字體、間距都能對齊 |
| 實作複雜度 | 低——本質上就是一個 <iframe src="..."> | 高——要處理打包、跨網站的 CSP、每個 host 環境的相容性 |
| 跨站溝通 | 只能透過 postMessage,明確但囉唆 | 可以直接用 JS API,彈性大很多 |
| 認證 | Focus Island 自己的 session/cookie 邏輯完全不受影響 | 容易不小心跟 host 網站的認證環境混在一起 |
Web Component 的最大賣點是「視覺整合度」,但這個賣點的前提是:host 網站跟被嵌入的 內容風格差很多,才需要花力氣去對齊。而我自己維護的這幾個網站剛好都是同一套深色 系風格——iframe 帶著自己的深色樣式,基本上直接就融得進去,不會有明顯的外掛感。 這麼一來 Web Component 的核心優勢在這裡的收益很小,卻要多背它的複雜度(跨站 CSP、認證邊界模糊)。
決定:往 iframe 方向做。
大致的架構草圖
- Host 網站:一顆固定在角落的浮動觸發按鈕(跟 chat widget 同樣的位置習慣),
預設只顯示這顆按鈕,
<iframe>本身收合/隱藏 - iframe 內容:不是直接指向 Focus Island 現有的完整頁面,而是另外開一個專門
給嵌入用的路由(例如
/widget),拿掉 Focus Island 自己的 header/nav,只留 「快速能用到」的那一小塊互動,複雜功能一律不做在 widget 裡,用連結導去完整站 - Host 與 iframe 的溝通走
postMessage:- iframe → host:內容實際高度變化時通知 host,讓外層容器能 auto-resize, 不然預設 iframe 高度是固定的,內容一多就會被裁掉
- host → iframe:目前只需要開/關這個狀態,不需要傳遞太多資訊——這也是選 iframe 後少掉的麻煩之一,如果各站風格差很多,還得傳 theme/token 之類的東西進去
- 一個共用的 embed script:之後要嵌進新網站時,貼一段
<script src="...">加一行初始化呼叫就好,不用每次手刻按鈕 + iframe 的 HTML/CSS
還沒解決、故意先誠實列出來的問題
- 跨站的登入狀態怎麼同步:如果 Focus Island 需要登入才能用,而每個 host 網站 都要求使用者重新登入一次,就違背了「隨手打開就能用」的初衷。這塊需要先確認 Focus Island 現有的認證方式能不能支援跨站共用 session,或至少做到輕量的 SSO,這是目前最大的未知數
- CSP / X-Frame-Options:host 網站要允許嵌入 Focus Island 的網域,Focus Island
那邊也要明確設定允許被哪些 origin embed(
frame-ancestors),不能兩邊都用預設值 /widget路由要拿掉多少東西:目前只有「感覺上應該拿掉 header/nav」這個 直覺,實際上要嵌入的是哪個功能子集,還沒有定案
小結
與其把 Focus Island 的邏輯複製到每個網站裡各養一份,不如把「入口」做成一個可以 到處貼的小工具——核心邏輯永遠只維護一份,其他網站要用的話就是加一顆按鈕的成本。 iframe 在我這幾個網站風格接近的前提下,付出的視覺代價很小,卻換到最簡單的隔離性 跟最不需要動腦的認證邊界,先往這個方向設計。