vue-router如何去中心化

Woo不想說話發表於2019-03-25

vue-router作為Vue官方三大套件之一,在日常開發中成為了不可或缺的存在,但是不管多麼niubility的框架或元件,在業務場景不斷髮生改變的同時,不可避免的會出現一些適用性上的問題,這就需要我們去擴充套件不同的使用場景,以達到業務上的最佳實踐。

vue-router使用姿勢

按照vue-router官方的使用文件中,我們在配置和使用vue-router的姿勢如下:

  • 元件與路由的對映匹配
// router/index.js
const routes = [
    { path: '/home', component: Home },
    { path: '/about', component: About }
]

export default routes
複製程式碼
  • 掛載router
// main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

import routes from './router/index.js'
const router = new VueRouter({
    routes
});

new Vue({
    el: '#app',
    //讓vue知道我們的路由規則
    router: router,
    render: c => c(App),
})
複製程式碼

ok,現在我們就可以在我們的元件中通過this.$route來操作路由相關屬性及方法了。簡直so easy!

vue-router的中心化問題

何為中心化?

談到中心化,我們想到比較多的可能就是區塊鏈。那廣義上的中心化如何理解?簡單點說,就是在一個體系中某個節點要和另外的節點產生聯絡,就一定要通過特定的某個節點,這個節點就是一箇中心。

vue-router的中心化

剛講到中心化的概念,那我們可以拿上面vue-router實踐的例子來對照一下。 我們在router/index.js中定義或載入所有的路由配置,那這個檔案就是這個專案當中唯一的引用路由的節點(中心)。那中心節點會存在什麼問題呢?

  1. 檔案衝突:尤其是在使用svn這種集中式版本控制服務,沒有分支的概念,全部依賴一個遠端中心倉庫。
  2. 釋出故障:試想多人同時修改同一個檔案,在釋出流程不是非常完善,且相互溝通不順暢的情況下,容易出現某個正在開發的需求被另一個同樣釋出中的需求帶上線了,但另一個需求的相關依賴並沒有上線。導致生產環境編譯錯誤從而引發線上故障。

下面我們用一個比較簡單的釋出模型來說明。

模擬開發場景:

  1. 2人同時開發一個專案。
  2. 2個需求分別新建了2個router配置。
  3. 現在2個需求都開發完了,準備繼續後續的測試->釋出流程。

vue-router如何去中心化

PS: 上述的場景不一定發生,跟對應開發團隊的釋出流程相關。在開發流程比較完善的情況下是可以避免該問題的。

如何解決

  • 模組化
  • require.context

1. 模組化

可以將路由按業務模組劃分場景,對應模組下有一個獨立的入口檔案,儘可能保證相同業務需求不會出現路由檔案衝突的情況。

vue-router如何去中心化

對應的載入路由的配置可以修改為

// moduleA/index.js
import routeA from './moduleA-xx'
import routeA2 from './moduleA-xx2'
// 在這裡擴充套件moduleA的路由配置
const routes = [].concat(routeA, routeA2)

export default routes
複製程式碼
// router/index.js
import moduleA from './moduleA/index'
import moduleB from './moduleB/index'

const routes = [].concat(moduleA, moduleB)
複製程式碼

2. require.context

官方文件的說明是require.context使用 directory 路徑、includeSubdirs 選項和 filter 來指定一系列完整的依賴關係,便於更細粒度的控制模組引入。

文件地址:webpack.js.org/guides/depe…

簡單來說,通過require.context我們可以通過正則動態匹配並引入我們的依賴檔案,這樣我們不需要顯示的去載入我們的路由檔案,從而解耦router的入口檔案和對應route配置的依賴關係。在這裡我們通過它來實現我們的路由去中心化。

我們約定router目錄下所有的.js檔案預設都為route的配置檔案,通過require.context載入的程式碼如下。

// 載入router目錄下所有js檔案作為路由配置
let routes
let matches = require.context('./', true, /^\.\/[^/]+\/.+\.js$/)
matches.keys().forEach(key => {
	routes = routes.concat(matches(key).default)
})
複製程式碼

這樣,以後新增或修改路由只需要按照約定在router目錄新建js檔案或修改其中的配置即可,router/index.js不需要任何改動即可完成路由配置。

總結

在這裡我們總結下對於上述問題的一個解決思路,我們可以把中心化問題看成是一個依賴解耦的問題。那我們便可以用解耦的思路來解決中心化的問題,在上述解決方案中,我們用到了以下手段:

  • 單一職責:模組化拆分路由配置。
  • 依賴倒置:通過約定大於配置的方式將入口檔案與路由配置細節解耦,將路由配置的顯式載入過程抽象為通過require.context方式載入,具體的執行過程交由webpack在編譯構建時去分析,從而解除依賴。

關於解耦的問題,我覺得也是一個可以好好討論的點,有時間再和大家一起分享分享啦!感謝各位百忙之中抽出時間觀看!!!

相關文章