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


    问题现状

    • 后端采用 多服务 + nginx 的技术架构 根据业务拆分成不同的项目,具体服务通过location由nginx转发代理到不同的机器(端口)上。
    • 前端采用的是 dva + roadhog 的 SPA 页面。在前期路由少,页面小的情况下,开发顺畅无压力。
    • 随着开发的不断进行,前端开发的瓶颈渐显,前端代码量不断增加,引入的第三方包不断扩大,每次动态编译花费时间不断加大,最终打包文件不断变大。
    • 每次发布版本必须全量发布,即使是改动一点点的功能,无法按模块发布前端代码。
    • 开发人员在开发阶段必须通过--max_old_space_size命令强制分配内存来避免node进程 out of memory

    项目前端相关指标:

    业务代码大小 打包后代码总量 路由数量 编译总时长 热加载时长
    总量 5.26 MB 35.5MB 近100个 20分 45 s

    可以看到前端编译的时间已经极大的影响了开发人员的开发时间和开发效率

    改进目标

    1. 功能模块为第一维度分割大项目。
    2. 尽量不影响用户体验。
    3. 切换到新页面同步左侧菜单栏的状态。
    4. 子项目可以分开独立发布上线。

    解决思路

    1. 将旧项目的部分功能拉出来,独立成多个单独可正常运行的子项目。
    2. 借鉴后端 nginx 的分发思想,通过location分发到不同静态目录。
    3. 将子项目前端代码部署到多个路径(甚至是机器),每个子项目独立发布,互不影响。

    实现步骤

    1. 前端项目拆分

    • 更新前端路由模式,从hash模式改为history模式

    /src/index.js:

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

    2. nginx分发

    • 增加子路径的分发,有多个增加多个

    nginx.conf:

    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:

    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缓存(例如菜单栏),防止项目切换重复调用接口造成浪费。
  • 相关阅读:
    解决任务计划程序未启动任务,因为相同任务的实例正在运行的问题
    推荐.Net、C# 逆向反编译四大工具利器
    The Win32 Rundll and Rundll32 Interface Related Topics
    delphi版本修改PE头源码
    排序算法总结
    Delphi XE中String、ANSIString、TBytes之间的转换
    得到WAV文件的长度
    在VC中使用SendInput函数实现中文的自动输入
    SendInput模拟键盘输入的问题
    delphi XE的字符串处理
  • 原文地址:https://www.cnblogs.com/shenshangzz/p/10035197.html
Copyright © 2020-2023  润新知