前端单页面拆分多个单页面

问题现状

  • 后端采用 ==多服务 + 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缓存(例如菜单栏),防止项目切换重复调用接口形成浪费。
相关文章
相关标签/搜索