Web 项目上线后,开始开门迎客,等待着来自大江南北、有着各式各样网络状态的用户莅临。在千差万别的网络状态中,访问页面难免会遇到前端资源加载失败的情况,占比或许不高,但一遇到,轻则页面样式错乱,重则白屏打不开,影响用户体验感受,紧急情况下甚至影响了用户的工作,属于非常严重的问题。本文将从如何监控加载失败、加载失败如何优化、始终加载失败又该如何处理等问题逐一分析。

如何监控资源加载失败

方案一:script onerror

我们可以给 script 标签添加上 onerror 属性,这样在加载失败时触发事件回调,从而捕捉到异常。

1

并且,借助构建工具 ( 如 webpack 的 script-ext-html-webpack-plugin 插件) ,我们可以轻易地完成对所有 script 标签自动化注入 onerror 标签属性,不费吹灰之力。

1

2

3

4

5

6

7

newScriptExtHtmlWebpackPlugin({

custom:{

test:/\.js$/,

attribute:'onerror',

value:'onError(this)'

}

})

方案二:window.addEventListener

上述方案已然不错,但我们也试想是否可以减少 onerrror 标签大量注入呢?类比脚本错误 onerror 的全局监控方式(详见:脚本错误量极致优化-监控上报与 Script error),是否也可以通过 window.onerror 去全局监听加载失败呢?

答案否定的,因为 onerror 的事件并不会向上冒泡,window.onerror 接收不到加载失败的错误。冒泡虽不行,但捕获可以!我们可以通过捕获的方式全局监控加载失败的错误,虽然这也监控到了脚本错误,但通过 !(event instanceof ErrorEvent) 判断便可以筛选出加载失败的错误。

1

2

3

4

5

window.addEventListener('error',(event)=>{

if(!(eventinstanceofErrorEvent)){

// todo

}

},true);

通过监控数据分析,我们发现现实情况不容乐观。访问页面时存在资源加载失败的情况超过了 10000 例/天,且随着页面访问量的上升而增加。

另外,监控资源加载失败的方式不止这些,上述两种方式都属于较好的方案,其他的方式就不再展开。

优化资源加载失败

方案一:加载失败时,刷新页面 (reload)

有了监控数据后,便可着手优化。当资源加载失败时,刷新页面可能是最简单直接的尝试恢复方式。于是当监控到资源加载失败时,我们通过 location.reload(true) 强制浏览器刷新重新加载资源,并且为了防止出现一直刷新的情况,结合了 SessionStorage 限制自动刷新次数。

通过监控数据发现,通过自动刷新页面,最终能恢复正常加载占异常总量 30%,优化比例不高,且刷新页面导致了出现多次的页面全白,用户体验不好。

方案二:针对加载失败的文件进行重加载

替换域名动态重加载

只对加载失败的文件进行重加载。并且,为了防止域名劫持等导致加载失败的原因,对加载失败文件采用替换域名的方式进行重加载。替换域名的方式可以采用重试多个 cdn 域名,并最终重试到页面主域名的静态服务器上(主域名被劫持的可能性小)

然而,失败资源重加载成功后,页面原有的加载顺序可能发生变化,最终执行顺序发现变化也将导致执行异常。

保证 JS 按顺序执行

在不需要考虑兼容性的情况下,资源加载失败时通过 document.write 写入新的 script 标签,可以阻塞后续 script 脚本的执行,直到新标签加载并执行完毕,从而保证原来的顺序。但它在 IE、Edge 却无法正常工作,满足不了我们项目的兼容性。

于是我们需要增加 “管理 JS 执行顺序” 的逻辑。使 JS 文件加载完成后,先检查所依赖的文件是否都加载完成,再执行业务逻辑。当存在加载失败时,则会等待文件加载完成后再执行,从而保证正常执行。

手动管理模块文件之间的依赖和执行时机存在着较大的维护成本。而实际上现代的模块打包工具,如 webpack ,已经天然的处理好这个问题。通过分析构建后的代码可以发现,构建生成的代码不仅支持模块间的依赖管理,也支持了上述的等待加载完成后再统一执行的逻辑。

1

2

3

4

5

6

7

8

// 检查是否都加载完成,如是,则开始执行业务逻辑

functioncheckDeferredModules(){

// ...

if(fulfilled){

// 所有都加载,开始执行

result=__webpack_require__(__webpack_require__.s=deferredModule[0]);

}

}

然而,在默认情况下,业务代码的执行不会判断配置的 external 模块是否存在。所以当 external 文件未加载完成或加载失败时,使用对应模块将会导致报错。

1

2

3

"react":(function(module,exports){

eval("(function() { module.exports = window[\"React\"]; }());");

})

所以我们需要在业务逻辑执行前,保证所依赖的 external 都加载完成。最终通过开发 wait-external-webpack-plugin webpack 插件,在构建时分析所依赖的 external,并注入监控代码,等待所有依赖的文件都加载完成后再统一顺序执行。(详见:Webpack 打包后代码执行时机分析与优化)

至此,针对加载失败资源重试的逻辑最终都通过构建工具自动完成,对开发者透明。重试后存在加载失败的情况优化了 99%。减少了大部分原先加载失败导致异常的情况。

始终加载失败该怎么办

用户网络千变万化,或临时断网、或浏览器突然异常,那些始终加载失败的情况,我们又该如何应对呢?

一个友好的提醒弹框或是最后的稻草,避免用户的无效等待,缓解用户感受。

总结

以上,便是对资源加载失败优化的整体方案,从如何监控加载失败、加载失败时重试、重试失败后的提醒等方面。大幅优化修正了加载失败的问题,也缓解着实遇到异常的用户使用体验。

如有不妥,恳请斧正,谢谢。

html标签 资源加载失败,前端资源加载失败优化相关推荐

  1. Note | 前端资源预加载

    目录 - dns-prefetch - preconnect - subresource - prerender - prefetch - preload dns-prefetch 通过 DNS 预解 ...

  2. 前端资源预加载并展示进度条

    我们经常会看到,一些站点在首次进入的时候会先显示一个进度条,等资源加载完毕后再呈现页面,大概像这样: 然后整个页面的操作就会非常流畅,因为之后没必要再等待加载资源了.尤其是在移动端,或者是页游中,这样 ...

  3. html src加载外部静态资源,前端性能优化2:静态资源加载与优化

    css和js的装载与执行-HTML 页面加载渲染的过程 一个网站在浏览器端是如何进行渲染的呢? 流程示意图.png HTML渲染过程的一些特点 顺序执行.并发加载(单个域名的并发数量是有限的,所以多个 ...

  4. Webpack前端资源加载/打包工具

    文章目录 一.Webpack 1.什么是Webpack 2.Webpack安装 2.1全局安装 2.2安装后查看版本号 3.创建项目 3.1初始化项目 3.2创建src文件夹 3.3 src下创建co ...

  5. 前端资源(css,js,图片,接口等)加载过程

    查看前端各资源css,js,图片,接口等加载速度 前言 查看前端各资源加载速度 加载过程中各指标详解 前言 网页打开的速度快慢直接影响了用户体验.据统计,Google网站访问速度每慢400ms就导致用 ...

  6. Day239.RBAC模式、动态加载用户权限资源规则数据规则、【记住我】注销多次登录图片验证码session验证码验证功能 -springsecurity-jwt-oauth2

    1.RBAC权限管理模型 一.RBAC权限模型简介 RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制.模型中有几个关键的术语: 用户:系统接口及功能访问的操 ...

  7. prefetch 和preload_资源预加载preload和资源预读取prefetch简明学习

    前面的话 基于VUE的前端小站改造成SSR服务器端渲染后,HTML文档会自动使用preload和prefetch来预加载所需资源,本文将详细介绍preload和prefetch的使用 资源优先级 在介 ...

  8. egret白鹭引擎RES资源管理模块,资源动态加载失效BUG,加载卡死BUG,完整解决方案与超详细调试漏洞过程

    我是千里马,是一位软件工程师,最近几天完成了用户中心全套内容设计和游戏中大大小小的各种bug处理解决,准备开始游戏的正式填充,突然想起来还有两件抛之脑后的事情没有做.因为之前一直都是忙碌大方向内容设计 ...

  9. 页面加载速度-合并资源文件

    前言 一直觉得自己的博客站点页面加载很慢, 就想着去优化一下. 呐, 下图是一次文章页面的加载, 需要2.5s. 其中 js 文件就有18个. 众所周知, 浏览器对资源文件的并行下载数量是有限制的(不 ...

最新文章

  1. GIT:本地有更改,但强制作远程仓库里作更新
  2. Flask之WTForms验证
  3. 开源前后端分离在线考试系统
  4. http://blog.csdn.net/wemedia/details.html?id=40237
  5. 指针与数组关联导致的一些现象
  6. Fedora 11-Alpha试用手记
  7. AutoCAD VBA基于对象的分层
  8. [递归|迭代] leetcode 21 合并两个有序链表
  9. MySQL锁系列3 MDL锁
  10. DL-C1-week3-1(build a neural network with one hidden layer)多层感知机的简单实现
  11. 关于使用CAD文件预览的使用
  12. 无线电监测软件java_大牛干货:软件无线电的设计和测试
  13. excel制作特殊图表记录
  14. 前端网络基础-传输层UDP协议
  15. java+ElementUI前后端分离旅游项目第六天 移动端开发下
  16. 学习OpenCV3:在空白图片上画虚线
  17. 计算机考研高数试卷答案,考研数学试卷大全(全国各高校历年试卷)
  18. Confluence 你可以对编辑器中的表格进行什么样的操作
  19. OpenGL.Shader:志哥教你写一个滤镜直播客户端:仿3个抖音滤镜效果(4镜像/电击/灵魂出窍)
  20. 关于微信开放平台开发者资质认证的简单记录

热门文章

  1. 教师计算机网络知识培训内容,教师信息技术培训教案
  2. 全球及中国盾构机市场分析与发展格局展望报告2022版
  3. html5中怎么让文字旋转动画效果图,HTML5中实现的CSS 3D文字旋转动画
  4. Ubuntu Linux for Non-Geeks: A Pain-Free, Project-Based, Get-Things-Done Guidebook
  5. python3 json解析_Python3 JSON 数据解析
  6. editplus怎么写asp_个人网站建设策划书怎么写,有哪些格式和内容呢?
  7. 整合Tkinter GUI界面的古诗词词云生成
  8. VB(视频缓冲区)配置
  9. 【Revit闪退小技巧】Revit打开启动时候闪退完美解决
  10. WinForm控件使用文章收藏整理完成