記一次系統演變過程

Aaron發表於2020-05-18

對於大多數前端來說,無非就是寫寫簡單的頁面,我並不是歧視前端,筆者也是前端,因為前端確確實實對於公司的整體業務的認知沒有後端的瞭解的更加深刻(畢竟人家是玩資料庫的)。

筆者在剛剛做公司內部系統的時候也只是做做簡單的各個模組系統,現在大多數公司都是使用的微前端的系統架構,以達到各個業務依賴性沒有那麼大,同樣也不會因為專案的逐漸擴大,導致專案越來越大,首先載入慢,再其次就是難以維護。

但是所有專案都以微前端的形式分散開,就會遇到整合的問題,於是在我們進行瘋狂的討論,因為使用的技術棧是Vue這個因素也被考慮進去了,討論出來第一版最終解決方案。

初期實現-iframe

其實對於大多數人來說,一旦說到前端專案整合的話,第一個想到的就是iframe,這種是最簡單最的方法了,大多數公司都是使用的這這種方法對專案進行整合的。

廢話我們也就沒多說,就開始開發了,遇到的第一個問題就是跨域,因為整合所有子項的每個都有自己的域名,承載這些子專案的框架又有自己的域名。這裡就使用了,document.domain的解決了跨域問題。跨域的問題一般都會遇到,這也並不是難解決的。

除了跨域問題,還有就是各個子專案的鑑權,各個子專案需要登入之後的token其實這個問題也不是特別困難,但是後端在做這個地方為了保證許可權的安全性考慮,token會隨著一段時間進行變化,這樣一來就不是簡簡單單的把token傳給子專案就行了,首先考慮的是,各個子專案攜帶者著token向後端請求資料的時候,當token發生變化的時候,需要通知登入框架。

在最初考慮這個問題的時候,考慮使用postMessage進行通訊因為涉及的專案太多,而且使用postMessage方法雖然輕便,但是覺得這種方法有些臃腫,不太適用於我們現在的整體架構方案。經過討論之後,就放棄了這個方案。為什麼會放棄這個方案,因為當開啟多個子頁面的時候,其中一個子專案在請求資料過程中token發生變化了,其他子頁面需要知道token想要知道token發生變化,就必須通過登入框架通知,如果使用postMessage的話就實在太不方便了。

其實想要的無非是登入框架的token改變,子專案token隨著改變,這時機智的我想到了灰常優秀的VueVue是使用的是Object.defineproperty,通過該方法,各個子專案也好和登入框架也好,只需要監控一個物件上某個自定義屬性即可,這個使用我把矛頭指向了window,雖然這樣不太好,但是針對於目前的情況window是最好的選擇。

依賴實現結構圖:

image

解決了一些問題之後,也算是可以完成了第一版雖然存在很多的問題,但是確實是可以用了。於是第一個版本就這樣匆匆忙忙的上線了,使用者反映怎麼說呢,其實也沒有那麼好,畢竟是iframe需要載入的會比較慢。還在想辦法進一步優化一些。

結構優化

時間每天都在流失,登入平臺依舊有很多的問題,對iframe有所瞭解的同學都應該知道,每次iframe在開啟的時候都需要重新拉取資源,這個是真的是太頭疼了,然而這還不是最關鍵的問題,最關鍵的是什麼,各個子專案每個模組都在登入平臺裡面,很多模組完全在同一個專案裡面,很多時候需要拉取相同的資源,這個實在是太難受了,作為一個前端來講,如此大量的重複資源載入,有點無法容忍。

有的時候各個子專案業務太大的時候,頁面載入的實在是有點過於太慢了,在最初做專案時,那個時候單頁面應用火熱(現在也有大部分公司在使用),單頁面應用就會帶來這樣的問題。

為了解決這個問題曾經考慮過使用路由懶載入,雖然可以實現一些資源的節約,但是,舉個例子來講的話,如果當前模組只有一個只有表單,其他什麼都沒有,這個使用完全不需要使用routestroe,其他的在同一個專案裡面的應用仍然用到了routestroe,導致載入該模組的使用routestroe同時也被拉取下來了,實在是讓人頭痛,本身我不需要這些東西,為什麼還要載入這些東西。我想哭~~~

帶著這些疑問,開始尋求解決方案,經過一段時間的調研,發現多頁面應用完全可以滿足我現在的需求,通過多頁面,只需要在對用的頁面的例項中掛載對應所需要的資源就可以了。當讀取到當前這個子專案中的某個模組的時候就可以做到這一點了。

這樣做的好處在於當前子業務模組,需要用到route就引入route,用到stroe就使用stroe,開啟頁面也只會拉取相對應的資源。再也用擔心當前子專案拉取一些沒有相關的資源了。

具體多頁面配置請參考:Vue-cli3多頁面配置

結構設想

雖然通過上面兩部操作,已經對效能解決了很大一部分問題,但是,身為一個優秀的前端(咳咳咳,不要打斷我。。。暫時不接受反駁,哈哈哈)來講得話,整個框架還是存在一些問題。

  1. 登入框架中已經存在了routestroe這些資源,為什麼子專案開啟的時候,還要重新拉取一次呢?
  2. 使用iframe始終不是那麼的優雅,會帶來一些不可預知的問題,或者以後一些需求甚至會導致無法滿足(雖然現在還沒有遇到,但是還是得為以後做打算)

以下內容沒有經過實踐,還無法知道是否可以實現。

這個想法來自於SSR,當調研Vue的服務端預渲染的時候我發現,當客戶端頁面啟動的時候是通過,讀取客戶端匯出的一個json檔案,並且讀取了裡面的內容,找到對應的.js檔案,既然在服務端渲染的時候可以通過讀取對應的js檔案做到頁面的渲染,那麼在前端渲染的時候是不是也可以來一波這樣的騷操作呢?。這樣一下靈感就來了,忽然就有了一個大膽的想法。

關於這裡還有一個小插曲想要說一下,我以前以為ssr是服務端解析了js檔案,但是被小夥伴給質疑了,其原因是Node根本就沒得辦法去解析js檔案。以前調研ssr的時候用到了renderToString的函式,但是,當時接收的是一個url引數,也就是前端路由,createBundleRenderer返回的物件中存在兩個函式分別是renderToStringrenderToStream,其中renderToString函式接收的就是頁面中所寫的template模板內容,最後把渲染好的頁面返回給客戶端。這是我自己後來理解的,再往下就要看原始碼,這裡我沒有詳細看,畢竟與該文章內容不符,這裡就不做多餘贅述了,有興趣的同學可以看下。這裡灰常感謝我的小夥伴指出了我的錯誤。

服務端渲染中節選的程式碼:

let render = vueRender.createBundleRenderer(serverBundle,{
    template,
    clientManifest:clientBundle.data,
    renInNewContext:false
}); 
//  重點就是這裡
render.renderToString({
    url:request.url
}).then((html) => {
    respones.end(html);
}).catch(error => console.log(error));

服務端渲染請參考:手把手教你搭建SSR(vue/vue-cli+express)

如果在Vue打包的使用,可以把各個頁面對應的css檔案js統一寫入到專案中的一個json檔案中,如果是這樣的話,登入框架可以通過域名獲取到該模組對應的元件,然後通過動態路由route.addRoute這個api把讀取到的元件註冊到登入頁面,這樣一來Vuestoreroute元件庫這些東西就完全可以使用,登入框架的了。豈不是一舉兩得的嗎?這樣的優化真的太大了。

image

上圖中完成了操作之後,獲取到對應的頁面元件之後,通過路由動態注入到登入框架中的,就行了。這些想法還在一步一步的調研過程中。。。

總結

所有的專案無論大小,都需要演變,但是其中需要作為開發人員的我們,進行不斷的思考和優化,以達到一個比較好的狀態,做前端也有一段時間了,個人覺得,沒有最好的選型,只有最適合選型,只有真正符合當前專案的需求的選型才是最正確的。

前端的路還有很長,還有太多太多的東西需要去考慮,前端所需要重視的是使用者體驗和資料互動,其實最最重要的還有就是效能。不能因為一個錯誤的想法,讓使用者覺得當前的系統變得很慢。

感謝大家閱讀這篇文章,文章中如果有什麼問題,大家在下方留言我會及時做出改正。

相關文章