1.什么是首屏和白屏,它们的区别?
1.首屏时间
指浏览器从响应用户输入网络地址到首屏内容全部渲染完成的时间,即 首屏时间 = 首屏内容渲染完成 - 开始请求时间
2.白屏时间
指用户输入内容,按下回车到浏览器开始出现的一个字符,即开始显示内容的时间 即:白屏时间 = 页面开始显示时间 - 页面发送请求的时间
首屏时间 > 白屏时间
2.首页白屏的原因
1.FP 首次绘制(First Paint)
指的是浏览器首次向屏幕传输数据的时间,相当于屏幕上首次出现视觉改变的时间(FP包含非默认的背景绘制,而不包含默认背景绘制)
2.FCP 首次内容绘制 (First Contentful Paint)
指的是浏览器首次向屏幕绘制来自DOM内容(只有首次绘制文本、图片 (包含背景图) 、非白色的 canvas 或SVG时才被算作FCP)生命周期中,mounted 对应的是 FCP,
3.FMP 首次有效绘制 (First Meaningful Paint)
指的是浏览器的页面快加载完了,就剩图片还没加载出来的时候。生命周期中,updated 对应的是 FMP
4.结合分析问题
1.浏览器渲染过程
浏览器渲染包含 HTML 解析、DOM 树构建、CSSOM 构建、JavaScript 解析、布局、绘制。
①等待 HTML 文档返回,此时处于白屏状态。
②对 HTML 文档解析完成后进行首屏渲染,如果代码中加了的背景色,因此呈现会先呈现出该背景颜色(比如灰色--->灰屏)。
③进行文件加载、JS 解析等过程,导致界面长时间出于灰屏中。
④当 Vue 实例触发了 mounted 后,界面显示出大体框架。
从FP到FMP的整个过程都是白屏显示,除非如果代码中header如果有某些背景色啊,相对于的背景色可能会显示出来,在通过 Ajax 获取数据之后,浏览器才会去解析并加载我们的数据。
Vue.js 文件加载失败,Vue.js 文件加载失败,页面上绑定的数据不存在,渲染顺序错误等等原因都会产生白屏现象
2.路由重复或者没有配置路由
①把路由模式mode设置成history了,默认是hash
解决方法:将模式改为hash模式,或者直接把模式配置删除,但是history需要后端配合
②做动态路由时,next()放行与next(...to, replace)区别造成的白屏,实质是路由重复
③第一次正常访问,刷新后白屏,vuex没有与本地存储结合,刷新后导致数据丢失
3.加载文件资源过大
单页面应用的 html 是靠 js 生成,因为首屏需要加载很大的js文件(app.js 和vendor.js),所以当网速差的时候会产生一定程度的白屏
4.浏览器兼容问题(不支持es6)
若在项目中使用了es6语法,而恰好一些浏览器不支持es6,造成编译错误不能解析而造成白屏
解决方法: 安装Babel ,Babel 会把这些新语法转译成较低版本的代码。
5.dist中文件引用路径错误(vue项目打包的路径问题)
打包后的dist目录下的文件引用路径不对,因找不到文件而报错导致白屏
解决的方法总和
1.预渲染
预渲染就是webpack打包时候渲染,通过无头浏览器。无头浏览器在打包的时候,可以把你index.html的内容放入你这个浏览器。
①一开始浏览器是空白的,然后当你进入页面时候直接加载这个index.html,并且还没ajax请求
②直接获取到预渲染的页面html内容,然后再放到index.html,再到CDN,直接请求html
(相当于FMP提前到了FP),其实更像另外一种骨架屏,少了aiax请求但是由于这样做,我们只能添加死数据,而为了能把ajax请求的数据渲染到首页上,我们可以用 document.querySelector(' ').html(' ') 来给它加载数据
2.同构渲染
何为同构渲染,(相当于 服务端渲染 + 客户端渲染 )就是一套代码多端使用 现在有一些框架
①客户端发起请求 服务端渲染首屏内容 + 生成客户端 SPA 相关资源
②服务端将生成的首屏资源发送给客户端
③客户端直接展示服务端渲染好的首屏内容
④首屏中的 SPA 相关资源执行之后会激活客户端 Vue
⑥之后客户端所有的交互都由客户端 SPA 处理
同构渲染框架:
React 生态中的 Next.js
Vue 生态中的 Nuxt.js
Angular 生态中的 Angular Universal
3.SSR 服务端渲染
服务端渲染也可以解决首屏加载慢这个问题,因为服务端会把所有数据全部渲染完成再返回给客户端(原来由客户端生成的html,现在由服务端渲染后,在交给浏览器)
ssr =>请求->node->解析 ->吐回给客户端(带请求数据)
问题:在 node层 需要解决高并发问题(本来是通过客户端完成渲染,现在统一到服务端node服务去做。尤其是高并发访问的情况,会大量占用服务端CPU资源)
4.路由懒加载
const app = () => import('')
5.使用Gzip压缩
可以减少文件体积,加快首屏页面打开速度,前提是服务器那边得开启 gzip 前端需要做的事
6.外链CSS,JS文件
就像我们在main.js中直接import所需要的ui库或者css文件,我们同样也可以在index.html,通过script外链引入,这样就不用通过webpack打包
7.webpack entry
这个就是将单页改成多页应用,比如一些组件中,vuejs vue-router等插件已经在某个页面使用了,然后给它缓存起来,下次就无需加载
8.骨架屏
骨架屏就是在进入项目的FP阶段,给它来一个类似轮廓的东西,当我们的页面加载完成之后就消失,这个也很好做的,很多ui库都有这个东西,可以参考一下
①在页面元素后面增加一个骨架div,当页面加载完成后就隐藏这个div
②在页面元素结构中先嵌入骨架div,当页面加载完成后就替换这个div
③通过伪元素实现骨架样式,通过操作样式实现骨架和页面的动态切换
9.loading
首页加一个loading或许是最原始的方法了,在index.html里加一个loading的css效果,当页面加载完成消失