前端單頁面拆分多個單頁面

問題現狀

  • 後端採用 ==多服務 + nginx== 的技術架構 根據業務拆分紅不一樣的項目,具體服務經過location由nginx轉發代理到不一樣的機器(端口)上。
  • 前端採用的是 ==dva + roadhog== 的 ==SPA== 頁面。在前期路由少,頁面小的狀況下,開發順暢無壓力。
  • 隨着開發的不斷進行,前端開發的瓶頸漸顯,前端代碼量不斷增長,引入的第三方包不斷擴大,每次動態編譯花費時間不斷加大,最終打包文件不斷變大。
  • 每次發佈版本必須全量發佈,即便是改動一點點的功能,沒法按模塊發佈前端代碼。
  • 開發人員在開發階段必須經過--max_old_space_size命令強制分配內存來避免node進程 out of memory

項目前端相關指標:html

\ 業務代碼大小 打包後代碼總量 路由數量 編譯總時長 熱加載時長
總量 5.26 MB 35.5MB 近100個 20分 45 s

==能夠看到前端編譯的時間已經極大的影響了開發人員的開發時間和開發效率==前端

改進目標

  1. 功能模塊爲第一維度分割大項目。
  2. 儘可能不影響用戶體驗。
  3. 切換到新頁面同步左側菜單欄的狀態。
  4. 子項目能夠分開獨立發佈上線。

解決思路

  1. 將舊項目的部分功能拉出來,獨立成多個單獨可正常運行的子項目。
  2. 借鑑後端 ==nginx== 的分發思想,經過location分發到不一樣靜態目錄。
  3. 將子項目前端代碼部署到多個路徑(甚至是機器),每一個子項目獨立發佈,互不影響。

實現步驟

1. 前端項目拆分

  • 更新前端路由模式,從hash模式改成history模式

/src/index.js:node

import browserHistory from 'history/createBrowserHistory';
const app = dva({
    history: browserHistory(),
});
  • 修改路由配置,刪除非本項目的路由
  • 從model、service、route刪除非本項目的文件
  • 刪除非本項目的依賴,並更新package.json
  • 刪除/src/index.ejs首頁文件中非本項目的文件引入

2. nginx分發

  • 增長子路徑的分發,有多個增長多個

nginx.conf:nginx

location /sub-path/ {
    alias /xxx/dist/;   #靜態文件路徑
    try_files $uri $uri/ /xxx/dist/index.html;  #404時從新定向到靜態文件目錄下的index.html下
}
  • 修改根目錄的處理方式,由root更新爲alias(防止root權重問題致使nginx不執行try_files)

nginx.conf:json

location / {
    alias /xxxx/dist/;  #靜態文件路徑
    try_files $uri $uri/ /xxxx/dist/index.html; #404時從新定向到靜態文件目錄下的index.html下
}

3. 404路徑優化

  • 前端404路由由渲染頁面優化爲重定向資源,把路由控制權轉交給nginx
  • 爲防止前端404路由nginx404路由同時存在致使無限刷新需緩存一個更新狀態在本地,防止死刷新
tryRefresh() {
    if (window.sessionStorage.getItem('refresh') === 'true') {
        window.sessionStorage.removeItem('refresh');
        this.show404 = true;
    } else {
        window.sessionStorage.refresh = 'true';
        this.show404 = false;
        window.location.href = window.location.href;
    }
}

4. 菜單狀態同步

  • 根據url路徑,同步更新左側菜單欄的狀態
setDefaultOpenKeys() {
    try {
        const { location: { pathname } } = this.props;
        let keys = [];
        const pathItems = pathname.replace('/', '', 1).split('/');
        const pathItemsWithoutLast = pathItems.slice(0, pathItems.length-1);
        this.setState({
            openKeys: pathItemsWithoutLast,
        });
    } catch (err) {
        // what you do
    }
}

5. 配置項目自動發佈

  • 配置發佈相關,自測,上線代碼

最終結果

將前端代碼拆分紅爲一個基礎模板和3個子項目。後端

  • 先後數據對比:
\ 業務代碼大小 打包後代碼總量 路由數量 編譯總時長 熱加載時長
==項目 - 舊== ==5.26 MB== ==35.5MB== ==近100個== ==20分== ==45 s==
項目模板 0.45 MB 2MB 2個 15s 1 s
子項目一 3.5 MB 28MB 近70個 12分 7 s
子項目二 4.2 MB 12MB 10個 4分 5 s
子項目三 2 MB 9.16MB 16個 1.5分 2 s

待優化點

  • 有些公共的文件沒有抽離出來,致使子項目總和是大於原項目的。抽離出公共文件和依賴,防止資源浪費。
  • 常量的公共接口能夠作sesionStorage緩存(例如菜單欄),防止項目切換重複調用接口形成浪費。
相關文章
相關標籤/搜索