Miox帶你走進動態路由的世界

51信用卡大前端團隊發表於2017-11-17

最近,我們團隊開源了一套沉澱了2年的前端SPA架構框架,主要是用來解決動態路由的問題。我們的思路來源於後端,採用中介軟體的設計模式來架構整個框架。我們的原則是讓大家快速開發一個SPA單頁應用,只關心業務邏輯,其他的行為都可以幫助處理掉。

其實我們的開源比較匆忙,從很多方面看還是有些不標準的,但是之後我們會嚴格按照標準的規範和流程走下去,給大家一份穩定的架構。對於現在開始關注我們團隊的小夥伴,我表示非常的感謝。有大家的支援,我們會做的更好。

Miox到底要解決什麼問題?

這個問題從我們設計的初衷來說,就是解決所有路由的問題。在業界,其實大家都普遍認可一對一的路由模式,從而生產出了很多路由體系,比如vue-routerreact-router。他們都是非常不錯的架構,從某種意義上來說,引領了前端路由的前進。很多小夥伴都是直接使用他們的全家桶來開發專案,也得到了很好的效果。

我不確定大家是否考慮過一個問題,當一個使用者從登陸頁面A登陸後進入B,再回到A頁面的情況。一對一的靜態路由其實理論上最終會將A頁面顯示為未登入,這是完全正確的,但是邏輯上它應該是一個登入的頁面。靜態路由無法區分環境變數對頁面選擇的影響,只能通過hook等手段來將頁面內容替換掉。理論上,我們藉助後端的寫法應該是這樣的邏輯:

route.get('/a', ctx => {
    if (global.logined) {
        ctx.render(webveiwA);
    } else {
        ctx.render(webviewB);
    }
})複製程式碼

我們需要根據周邊的環境變數去自動選擇該渲染哪個頁面,如此的邏輯才是我們想要的。所以我們會根據這樣的思路來設計動態路由。在nodejs的世界中,這種模式已經非常常見,比如express-routerkoa-router,都是採用這種設計思路來實現動態話的路由體系。我觀察了前端的發展,都沒有提出在前端實現這樣的邏輯。於是,我們便開始研究如何將這種思路架設在前端使用,來獲得更理想的邏輯體驗。

Miox從來都不是依賴任何MVX框架來實現

為什麼這麼說呢?原因非常簡單。在公司裡面,我們大概有90%的H5業務都是採用Miox來實現的。我們的技術棧其實是Vue,因為Miox對Vue的結合太過深入,所以自然有部分小夥伴認為Miox是基於Vue來開發的,也就是說Miox是依賴著Vue?其實不是,Miox並不依賴任何框架實現。我來舉個列子:

我們的電腦,如果換了一個顯示卡,那麼必須要裝顯示卡驅動。根據不同的顯示卡驅動,表現也不同。如果我們將Vue當作一個顯示卡,而Miox當作我們的電腦,那麼我們需要一份顯示卡驅動來讓整臺電腦接受這塊顯示卡。

所以我提出一個概念,就是渲染驅動的概念。Vue僅僅是我們Miox的一個渲染引擎,用來渲染頁面的,可以理解為模板。我們還需要一份驅動告訴Miox,來說明Vue的渲染是如何在Miox實現的。這部分可以從這裡看明白。當然,不僅僅是Vue,我們還能夠將React接入到Miox中。理論上,只要能提供對應的渲染驅動,都可以將任意的渲染引擎接入到Miox中來使用。自然的,大家的書寫都將會變成那種引擎的書寫方式。這就是我們的插拔式設計。在公司裡面使用的時候,我們不必在意使用何種渲染引擎,Miox都可以支援,同時幫您管理好整個路由體系。

基於中介軟體實現

在前端,如果我們能夠用中介軟體來攔截整個邏輯過程的話,對開發是相當有利的,不僅僅在程式碼層面能夠提高可讀性,同時可以在具體業務層面提高效率。我們用後端路由邏輯來舉個例子:

當我們遇到一些API都是需要經過登入驗證的時候,我們可以將/authorize的路由字首都使用中介軟體統一處理。其他的都不走驗證邏輯。

const Authorize = require('./auth');
const AuthorizeApi = require('./auth/routes');
route.use(
    '/authorize', 
    Authorize.connect(), // Authorize.connect是統一的驗證邏輯程式碼
    AuthorizeApi.routes(), 
    AuthorizeApi.allowedMethods()
);複製程式碼

如此當通過/authorize的路由都需要經過Authorize.connect()來驗證是否具有許可權。這使得程式碼非常簡潔易懂。

Miox的設計便是如此,通過這種中介軟體的架構,使得我們在前端獲得了統一攔截處理的能力。在實際生產中,我們很多地方都用到了中介軟體來處理統一的校驗邏輯,使得程式碼維護性得到很大地提升。

那麼如果不使用呢?我們需要在進入頁面的時候,每個頁面中都要嵌入一段程式碼來處理許可權問題,不僅僅程式碼量增加,而且對於之後的維護,可能會產生漏改的問題。

具體想了解中介軟體的小夥伴,我推薦去看下koa-router

快取頁面得到更好的渲染效能

說到快取,這個話題過於龐大,對於Miox的快取機制,我只能簡單介紹一下,有興趣的小夥伴可以看下原始碼

在開發過程中,特別是對於開發移動端頁面,我們需要儲存前一個頁面滾動位置,那麼我們在切換到另一個頁面的時候是不能將前一個頁面銷燬的,原因是我們希望回到前一個頁面的時候還是停留在之前滾動的位置。那麼我們需要快取這個頁面來確保位置的不改動。Miox模擬了history的部分API,同時增加了一層頁面堆疊。我們需要維護這層頁面堆疊來確保頁面的可溯性。每次我們通過一種演算法來動態比較路由與頁面的關係,從而從這個堆疊中選出我們想要的快取頁面。當然,沒有這個對應關係的時候,我們自然是要建立的。我們基於盡最大可能限度複用頁面的宗旨,來快取這些頁面與路由的關係。

可能有人要問,如果快取過多,對於頁面的切換會有效能上的影響吧?是的,過多的頁面快取也是阻礙效能的關鍵。這裡我們進行了快取個數的優化。在啟動miox服務的時候,我們有一個配置的引數max,一般預設為一個,當然,大家也可以自己自由設定最大個數,來保障快取的效能問題。

歷史遺留問題:history方向問題的解決方案

在History中,我們都承認無法判斷出當前瀏覽器行為的方向性,所以無法給出我們想要的方向來自動做頁面切換的效果。為了解決這個問題,我們蒐集了業界的解決方案,採用sessionStorage來模擬history堆疊,從而解決這個問題(新history的API中已經增加了history.index動態屬性來告訴我們現在位於堆疊中的位置)。我們將此方案整合到了Miox中,並且對其加強,來告訴動畫引擎這次行為在瀏覽器中是如何表現的。自然,動畫引擎就能夠根據這個來自動切換頁面的動畫,達到自動處理的效果。

官方提供了一個簡單的模組來支援動畫,當然小夥伴想要自定義動畫也是非常簡單的,具體見這裡

獨立的頁面生命週期

在傳統的MVX框架中提供了元件的生命週期,我們在某種意義上也認為是頁面的生命週期,但是我們對比原生IOS的週期行為,還是有所欠缺的。比如說active生命週期。這個是什麼意思呢?我來舉例說明:

當一個頁面被推入後臺,又被喚起的時候,我們根本不知道它是不是再一次被啟用,我們只能知道頁面又一次被進入,第二次進入的概念是需要很多程式碼來輔助完成的。而在傳統框架中,很難觸發再一次的mounted生命週期,因為頁面已經被mounted過了。Miox提供了這樣的生命週期的定義。

// use vue.js
export default Vue.extend({
    mounted() {
        this.$on('webview:active', this.activeLife);
    },
    methods: {
        activeLife() {
            console.log('我被喚起了');
        }
    }
})複製程式碼

當然,我們也可以將這些生命週期直接拋到全域性去,用於全域性的監控。

app.on('webview:mounted', webview => {
    console.log(webview);
})複製程式碼

對於前置的生命週期,我們同樣提供了以下的生命週期來輔助:

  • webview:enter
  • webview:leave
  • webview:beforeEnter
  • webview:beforeLeave

這些週期能夠讓你很好地掌控整個過程,對於自動埋點什麼的功能非常實用。

服務端渲染

目前主流的架構都支援了服務端渲染來增強SEO的能力,那麼對於Miox而言,也需要支援他們的服務端渲染。考慮到Miox自身會給渲染出來的內容包裹一些程式碼,所以,我們需要自己實現SSR。當然,渲染引擎的SSR實現是交給自己來完成的。也就是說我們需要給他包裹一層SSR渲染。

Miox暫時支援Vue的SSR渲染,後續會逐步新增對於React的SSR渲染。還有比如百度的san.js其實也可以接入進來實現SSR渲染。服務端渲染並不是太麻煩,如果大家能夠掌握Miox的執行原理的話。

最後

對於開源,我們團隊內部做了很多努力,也諮詢了很多大牛,希望能夠給大家創造出一份簡易開發的架構來幫助大家完成業務。目前,團隊後續計劃如下:

  • 完善SSR的文件
  • 規範化Github上的git message
  • 維護Github上的Issues和PR
  • 單測和程式碼覆蓋率增強
  • 對路由架構更多思考來完善Miox
  • 提供Pc端的演示demo
  • 提供Miox實際開發場景下的開發程式碼示例

希望大家看到這篇文章後可以支援我們,給我們多提供一些意見和建議,讓我們共同將Miox完善下去。喜歡的小夥伴,幫忙點個Star

專案開源在 GitHub: 51nb/Miox

相關文章