页面白屏出现的原因

🤖 作者简介:水煮白菜王,一位前端劝退师 👻
👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。
感谢支持💕💕💕
目录
- 资源加载问题
- 1.可恢复的白屏
- 2.不可恢复的白屏
- 代码执行错误
- 白屏检测
- 检测根节点是否渲染
- Mutation Observer 监听 DOM 变化
- 页面截图
- 解决办法
白屏通常指的是页面打开后,浏览器上面的地址栏已经显示完整的 URL,但是页面内容无法渲染,只有白色的空白页面。
导致白屏的原因大致可分为两类:
- 资源加载问题
- 代码执行错误
从现代前端视角来看,这两种原因都跟当前SPA框架的广泛使用有关。
资源加载问题
这里的资源特指 JavaScript 脚本、样式表、图片等静态资源,不包括接口调用等动态资源。
资源加载问题导致的白屏可以分为可恢复的和不可恢复的两大类
1.可恢复的白屏
可恢复的白屏常见于第一次进人页面时,由于资源加载过慢或者接口请求未返回,所以浏览器无法执行下一步骤。
这种白屏通常是网络状况太差或者设备性能太差等原因导致的,一般在浏览器返回后,就能恢复页面渲染,可以通过监控首屏时间来发现。
如果生产环境的首屏时间呈异常上升趋势,那么一定是页面白屏时间过长导致的,开发人员应该及时关注并排查近期改动的代码
2.不可恢复的白屏
不可恢复的白屏大多是由于网络或缓存问题导致的。
常见的例子莫过于 React、Vue 等 SPA 框架构建的 Web 应用,一旦 [bundle|app].js 因为网络原因访问失败,便会引发页面白屏。
你可以访问任意SPA框架构建的Web应用,按照如下步骤复现:打开 DevTools > Network,找到 app.xxx.js,右键并选中 Block request URL,随后刷新页面。
另一个例子是SPA项目打包后,在非首次线上替换dist文件时,某些手机/浏览器在之后首次打开页面,可能出现白屏情况
在用户端会默认缓存index.html入口文件,而由于vue打包生成的css/js都是哈希值,跟上次的文件名都不同,因此会出现找不到css/js的情况,导致白屏的产生。在服务端更新包之后,由于旧的文件被删除,而index.html所链接的路径依然是旧文件路径,因此会找不到文件,从而白屏。
代码执行错误
代码执行错误导致的白屏一般伴随着功能流程的阻断出现,并且很难通过等待或者页面刷新等方法修复。
这类问题出现的原因通常是前端代码逻辑错误,或是后端接口的脏数据导致的前端数据解析逻辑错误,最终导致运行异常的前端代码触发了页面崩溃。
例如,如果 React 中的组件发生了异常,并且外部没有使用 componentDidCatch 或者getDerivedStateFromError 捕错误,那么 React 组件 render 挂载的目标节点下的 DOM 树会被移除、页面就会出现白屏。
自React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载。
白屏检测
检测根节点是否渲染
这种方法的原理是在当前主流 SPA 框架下,DOM 一般挂载在一个根节点之下(比如 < div id=“app” > ),发生白屏后通常是根节点下所有 DOM 被卸载。
我们可以通过在页面渲染完成后,检查页面根节点的子元素是否存在,如果不存在,则可以判断页面是白屏状态。
这种方案简洁明了,但缺点也很明显,项目有骨架屏渲染的情况下无法判断是否白屏。
如在 Vue.js 中可以使用钩子函数 mounted 或 created 在页面渲染完成后进行检测。
export default {created() {// 获取页面根节点const rootNode = document.querySelector('#app');// 检测根节点的子元素是否存在if (rootNode.children.length === 0) {// 页面是白屏状态console.error('页面白屏了!');} else {// 页面正常显示console.log('页面正常显示');}},
}
由于 SPA 应用通常使用异步加载方式加载组件和数据,因此需要确保在页面组件渲染完成后再进行白屏检测。如果在组件渲染之前进行检测,可能会误判为白屏。另外,SPA 应用可能会存在某些异步请求失败或加载超时等问题,也需要考虑这些因素对白屏检测的影响。
Mutation Observer 监听 DOM 变化
Mutation Observer 是一种在 DOM 树发生变化时进行回调的方式,可以用于监听页面元素的变化。可以通过 Mutation Observer 来监听 DOM 树变化,从而判断页面是否白屏。
但这个方式的缺点也很明显:
- 对性能的影响:使用 Mutation Observer 监听 DOM 变化会对浏览器性能造成一定影响,尤其是当 DOM
树变化频繁时,会导致回调函数频繁执行,影响页面的响应速度和用户体验。 - 兼容性问题:Mutation Observer 的兼容性不是很好,不同浏览器支持程度不同,需要进行兼容性处理。
- 误判问题:有些情况下,页面并不是真正的白屏,但是 Mutation Observer 仍然会误判为白屏,例如页面中有一个空白的 div元素占位,此时即使页面内容未加载,也不会被判定为白屏状态。
具体实现步骤如下:
- 创建一个 Mutation Observer 实例,并指定回调函数。
const observer = new MutationObserver((mutations) => {// mutations 表示 DOM 树的变化列表
});
- 将 Mutation Observer 实例与根节点进行绑定,并指定监测的选项。
const rootNode = document.documentElement;
const observerConfig = {childList: true, // 监听子节点的变化subtree: true, // 监听所有后代节点的变化attributes: true, // 监听节点属性的变化characterData: true, // 监听节点文本内容的变化attributeOldValue: true, // 记录节点属性变化前的值characterDataOldValue: true, // 记录节点文本内容变化前的值
};
observer.observe(rootNode, observerConfig);
- 在回调函数中检查 DOM 树的变化,如果发现根节点的子元素存在,则可以判断页面不是白屏状态。
const observer = new MutationObserver((mutations) => {// 检查根节点的子元素是否存在if (rootNode.children.length > 0) {console.log('页面正常显示');} else {console.error('页面白屏了!');}
});
页面截图
通过对网页进行截图,对截图进行像素点分析,判断页面是否白屏。一般情况下,可以统计截图中所有像素点的 RGB 值,如果所有像素点的 RGB 值都相同,且与白色(RGB(255, 255, 255))非常接近,那么就可以判断页面是白屏状态。
这个方式的缺点如下:
- 页面截图需要包含足够的像素点,以便能够准确地检测页面是否白屏。如果截图不够清晰,可能会导致误判。
- 有些情况下,页面并不是真正的白屏,但是由于一些外部原因(例如网络问题)导致页面未加载,此时页面截图也会被判定为白屏状态。
- 页面存在骨架屏的情况下,需要对比骨架屏
解决办法
思路:减小打包后的体积(sourceMap关掉,CDN引入, 路由懒加载,组件按需加载)
- 提高渲染速度
- 优化用户体验
- CDN资源优化
将依赖的第三方npm包全部改为通过CDN链接获取,在index.html里插入相应链接
<body><div id="app"></div><script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script><script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script><script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script><script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script><script src="https://cdn.bootcss.com/element-ui/2.6.1/index.js"></script>
</body>
在vue.config.js里配置externals属性
module.exports = {···externals: {'vue': 'Vue','vuex': 'Vuex','vue-router': 'VueRouter','axios':'axios','element-ui': 'ElementUI'}}
卸载相关依赖的npm包
npm uninstall xxx
使用gzip压缩
前端处理:
// npm i compression-webpack-plugin -S
const CompressionPlugin = require('compression-webpack-plugin');module.exports = {productionSourceMap: false,configureWebpack: config => {if (process.env.NODE_ENV === 'production') {return {plugins: [new CompressionPlugin({// 匹配规格test: /\.js$|\.html$|\.css$|\.png$/,// 文件超过多大进行压缩 单位Bytethreshold: 10240,// 是否删除源文件(建议不删除)deleteOriginalAssets: false})],}}},
}
还需要在 nginx开启gzip压缩, 例如:
gzip on;gzip_static on; //当存在.gzip格式的js文件时,优先使用静态文件gzip_min_length 10k; //开启gzip压缩的最小大小gzip_buffers 4 16k;gzip_http_version 1.1;gzip_comp_level 6;gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;gzip_vary on;gzip_proxied expired no-cache no-store private auth;gzip_disable "MSIE [1-6]\.";
注意:
当nginx开启gzip压缩的时候,无论前端打包出来的文件是否压缩,网站加载到的js文件都是经过nginx实时压缩过的 。
当gzip_static off的时候,前端上传的js压缩文件(gzip格式那些)并没有什么用。
当gzip_static on时,优先加载前端打包的gzip压缩文件,如果没有找到该文件,那么nginx将实时压缩之后传给浏览器。
如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀

相关文章:
页面白屏出现的原因
🤖 作者简介:水煮白菜王,一位前端劝退师 👻 👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。 感谢支持💕💕&#…...
【大模型统一集成项目】让 AI 聊天更丝滑:WebSocket 实现流式对话!
🌟 在这系列文章中,我们将一起探索如何搭建一个支持大模型集成项目 NexLM 的开发过程,从 架构设计 到 代码实战,逐步搭建一个支持 多种大模型(GPT-4、DeepSeek 等) 的 一站式大模型集成与管理平台ÿ…...
boarding_passes(登机牌)表的作用
boarding_passes(登机牌)表的作用 boarding_passes 这张表的主要作用是记录旅客的登机信息,包括: 票号 (ticket_no) - 关联到 tickets 表,表示这张票属于哪个旅客。航班 ID (flight_id) - 关联到 flights 表…...
【2025】Electron Git Desktop 实战一(上)(架构及首页设计开发)
源代码仓库: Github仓库【electron_git】 Commit : bb40040 Github Desktop 页面分析 本节目标: 1、实现类似Github Desktop的「空仓库」提示页 2、添加本地仓库逻辑编写从 Github Desktop 我们看到 他的 主要页面分为三个区域 Head头部区域…...
14 | fastgo 三层架构设计
提示: 所有体系课见专栏:Go 项目开发极速入门实战课; 在实现业务代码之前,还需要先设计一个合理的软件架构。一个好的软件架构不仅可以大大提高项目的迭代速度,还可以降低项目的阅读和维护难度。目前,行业中…...
【机器学习-基础知识】统计和贝叶斯推断
1. 概率论基本概念回顾 1. 概率分布 定义: 概率分布(Probability Distribution)指的是随机变量所有可能取值及其对应概率的集合。它描述了一个随机变量可能取的所有值以及每个值被取到的概率。 对于离散型随机变量,使用概率质量函数来描述。对于连续型随机变量,使用概率…...
面向对象Demo01
面向对象 什么是面向对象 回顾方法的定义 package oop; import java.io.IOException; public class Demo01 {public static void main(String[] args) {}//public String sayHello() {return "hello, world!";}public void sayHi() {return;}public int max(i…...
C++设计模式-抽象工厂模式:从原理、适用场景、使用方法,常见问题和解决方案深度解析
一、模式基本概念 1.1 定义与核心思想 抽象工厂模式(Abstract Factory Pattern)是创建型设计模式的集大成者,它通过提供统一的接口来创建多个相互关联或依赖的对象族,而无需指定具体类。其核心思想体现在两个维度: …...
solana区块链地址生成
solana官网地址:https://solana.com 先引入相关依赖solana/web3.js;bip39;ethereumjs/wallet 生成助记词 const mnemonic bip39.generateMnemonic(); 生成种子 const seed bip39.mnemonicToSeedSync(mnemonic); 生成密钥对 const root hdkey.EthereumHDKey.from…...
基于python的升级队列加速决策
a-f大等级是3级 a-c建筑每升1级分别需要8天 d-f建筑每升1级分别需要10天 目前以下建筑队列正在从0级升至1级 建筑A升级需要7天05:16:20 建筑b升级需要06:06:54 建筑c升级需要00:37:00 建筑d升级需要…...
Ragflow技术栈分析及二次开发指南
Ragflow是目前团队化部署大模型+RAG的优质方案,不过其仍不适合直接部署使用,本文将从实际使用的角度,对其进行二次开发。 1. Ragflow 存在问题 Ragflow 开源仓库地址:https://github.com/infiniflow/ragflow Ragflow 当前版本: v0.17.0 Ragflow 目前主要存在以下问题: …...
vue上传文件的请求头携带token校验、和携带另外的参数请求
拿element plus UI库举例,(不使用element plus的话js方法通用): <template><el-upload class"upload-demo":http-request"myUploadHttp" action"https://run.mocky.io/v3/9d059bf9-4660-45f2-…...
MySQL的 where 1=1会不会影响性能?
在MySQL中,WHERE 11 是一种常见的SQL编写技巧,通常用于动态生成SQL语句时简化条件拼接。虽然它看起来多余,但在实际使用中,WHERE 11 对性能的影响可以忽略不计。以下是详细分析: 1. WHERE 11 的作用 WHERE 11 是一个恒…...
MyBatis 中SQL 映射文件是如何与 Mapper 接口关联起来的? MyBatis 如何知道应该调用哪个 SQL 语句?
1. 命名空间 (Namespace): SQL 映射文件 (XML): 在 SQL 映射文件的 <mapper> 根元素中,有一个 namespace 属性。这个 namespace 属性的值必须是 Mapper 接口的全限定名(包名 接口名)。 <mapper namespace"com.example.mapper.…...
SICK Ranger3源码分析——断线重连
前言 本文可在https://paw5zx.github.io/SICK-Ranger3-source-code-analysis-01/中阅读,体验更佳 简单分析一下SICK Ranger3源码中断线重连的实现,这一块算是比较容易的,先择出来分析一下。 代码示例仅贴出关键部分以便分析 使用SDK版本为…...
1.7 双指针专题:三数之和(medium)
1.题目链接 15. 三数之和 - 力扣(LeetCode)https://leetcode.cn/problems/3sum/submissions/609626561/ 2.题目描述 给你⼀个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满⾜ i ! j、i ! k 且 j ! k ,同时…...
【JavaEE】Spring Boot配置文件
目录 一、Spring Boot配置文件简介二、properties 配置⽂件说明2.1 properties 基本语法2.2 value("${}")读取配置⽂件 三、yml 配置文件说明3.1 yml 基本格式3.2 yml 配置数据类型 及 读取3.3 yml配置对象及读取ConfigurationProperties(prefix "")3.4 配…...
行为模式---策略模式
概念 策略模式是一种行为设计摸是,它的核心思想是将一些列的算法封装成独立的对象,并使它们可以相互替换,通过上下文进行调用。 策略模式通过算法抽象为独立的策略类,客户端可以根据自身需求选择不同的策略类来完成任务、这种方…...
Word 小黑第15套
对应大猫16 修改样式集 导航 -查找 第一章标题不显示 再选中文字 点击标题一 修改标题格式 格式 -段落 -换行和分页 勾选与下段同页 添加脚注 (脚注默认位于底部 )在脚注插入文档属性: -插入 -文档部件 -域 类别选择文档信息,域…...
OSPF:虚链路
一、虚链路概念 在OSPF中,虚链路(Virtual Link) 是一种逻辑连接,用于解决因网络设计或扩展导致的区域无法直接连接到骨干区域(Area 0)的问题。它是通过中间区域(Transit Area)在两个…...
Ubuntu 22.04 安装配置 FTP服务器 教程
今天搞定在 Ubuntu 22.04 系统上安装和配置 VSFTPD ,还会涉及防火墙设置、SSL/TLS 设置,以及创建专门登录 FTP 服务器的账户。开始! 一、安装 VSFTPD 首先,咱得让系统知道有啥新软件包可以安装。打开终端,输入下面这…...
基于 Selenium 的软件测试方法研究
一、引言 在软件开发的漫长征程中,软件测试宛如一座坚实的堡垒,守护着软件质量的大门。随着互联网技术的飞速发展,Web 应用程序如雨后春笋般涌现,其功能的复杂性和用户交互的多样性不断增加。在这样的背景下,传统的手动…...
网络安全事件响应--应急响应(windows)
应用系统日志 Windows主要有以下三类日志记录系统事件:应用程序日志、系统日志和安全日志。 系统和应用程序日志存储着故障排除信息,对于系统管理员更为有用。安全日志记录着事件审计信息,包括用户验证(登录、远程访问等&#x…...
DataEase:一款国产开源数据可视化分析工具
DataEase 是由飞致云开发的一款基于 Web 的数据可视化 BI 工具,支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表,帮助用户快速分析业务数据并洞察其趋势,为企业的业务改进与优化提供支持。 DataEase 的优势在于:…...
RTK与RTD基础原理
(文中的部分图片是摘自其他博主的文章,由于比较久,忘记原本链接了,侵删) GPS定位原理 卫星自身有自己的星历与原子钟,因此卫星知道自身准确的空间坐标与时间。因为每个卫星都有原子钟,因此每颗卫星的时间基本上都是相…...
关于MCP SSE 服务器的工作原理
模型上下文协议(Model Context Protocol,简称MCP) 是一种全新的开放协议,专门用于标准化地为大语言模型(LLMs)提供应用场景和数据背景。 你可以把MCP想象成AI领域的“USB-C接口”,它能让不同的A…...
碳中和小程序:助力用户记录低碳行为,推动环保生活
碳中和小程序:助力用户记录低碳行为,推动环保生活 一、碳中和的全民化挑战与数字化机遇 中国承诺2030年前实现碳达峰,2060年前达成碳中和目标。在这一国家战略下,个人碳减排贡献率需从当前不足5%提升至25%。小程序开发技术正成为破解"公众参与度低"“行为量化难…...
Python读取显示Latex的公式文档,Python加载显示markdown文件。
平时用LLM大语言模型去解释文献里面的公式含义直接复制的格式word看不懂,基于这个web可以正常加载显示。 下面是读取的效果展示:下面程序保存为stl_read.py然后运行下面指令。 streamlit run stl_read.pyimport streamlit as st import base64 import …...
mapbox高阶,结合threejs(threebox)添加extrusion挤出几何体,并添加侧面窗户贴图和楼顶贴图
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️threebox extrusion挤出几何体二、🍀…...
mock的定义和使用场景
Python自动化中使用mock的示例 在Python自动化测试中,mock 用于模拟对象、函数或方法的行为,以便在隔离的环境中测试代码。以下是一个简单的示例: 假设你有一个 user.py 模块,其中包含一个 get_user_info 函数,用于从…...
