首屏优化方案
1、JavaScript外联文件引用放在html文档底部;CSS外联文件引用在html文档头部,位于head内;对首屏页面用到的 css内容,可以style 的形式写在首页
2、首屏不需要展示的较大尺寸图片,请使用lazyload;
3、避免404错误:尽量减少外联js;
4、减少cookies的大小:尽量减少cookies的体积对减少用户获得响应的时间十分重要;
5、减少DOM Elements的数量;
6、Webpack开启gzip压缩
7、服务端渲染SSR
8、Skeleton Screen (骨架屏)
9、路由懒加载
10、图片懒加载(vue-lazyload)
11、Promise优化
12、减少http请求
13、精灵图可以大大地减少CSS背景图片的HTTP请求次数;
14、压缩图片
15、CDN优化
16、少用location.reload()
17、正确使用display的属性
18、采用按需加载
19、压缩图片优化
20、合理使用缓存
21、预加载
几种常见web页面渲染方式对比
FP: ”首次绘制“(First Paint)不包括默认背景绘制(例如浏览器默认的白色背景),但是包含非默认的背景绘制,与iframe。
FCP:”首次内容绘制“(First Contentful Paint)包含文本,图片(包含背景图),非白色canvas与SVG。
iframe:父级浏览上下文不应该知道子浏览上下文的绘制事件,反之亦然。这就意味着如果一个浏览上下文只包含一个iframe,那么将只有“首次绘制”,但没有“首次内容绘制”。
1.CSR(客户端渲染)
1.最近几年流行的SPA,web app都是CSR模式,页面只有一个空div
2.优点:
(1)不依赖数据
(2)FP时间最块;就是留了一个div挂载组件嘛
(3)客户端用户体验好
(4)内存数据共享
3.缺点:
(1)SEO不友好
(2)FCP(首次有内容的渲染)、FMP( 首次有意义的绘制)慢;要各种发请求;
2.预渲染
使用puppeteer或者 rize.js 提前渲染一遍,另存起来;这种方式太傻了,就不详细介绍了;具体可以看他们的官方文档;
3.SSR和同构(服务端渲染)
1.服务端渲染,服务器把内容全都拼好直接输出,服务端用一套模板引擎
2.服务器和客户端使用一套代码就是同构
3.优点:
(1)SEO友好
(2)首屏性能高,FMP比CSR和预渲染都要快
4.缺点:
(1)客户端数据共享成本高
(2)模板维护成本高
4.最优的渲染方式
1.SSR和CSR共存的模式,发挥两者的优势
(1)刷新页面是SSR渲染,nodejs配合bigpipe
(2)站内点击是CSR,不用vue router、react router等等,直接用原生的a链接
Skeleton Screen (骨架屏)
简单来说,骨架屏就是在页面内容未加载完成的时候,先使用一些图形进行占位,待内容加载完成之后再把它替换掉。体验的效果就是,在页面完全渲染完成之前,用户会看到一个样式简单,描绘了当前页面的大致框架,能够感知到页面正在逐步加载,最终骨架屏中各个占位部分被完全替换。
Vue-Router路由懒加载(利用Webpack的代码切割)
把不同路由对应的组件分割为不同的代码块,当路由被访问的时候,再加载对应的组件,对中大型项目来说,会显得很高效,对开发者而言,也方便维护。不过这里要对生产环境和开发环境做区分,因为如果项目很大的话,每次更改代码触发的热更新时间都会很长,所以只在生产环境中使用路由懒加载。
// 生产环境 _import_production.js
module.exports = file => () => import('@/pages/' + file + '.vue');
// 开发环境 _import_development.js
module.exports = file => require('@/pages/' + file + '.vue').default; // vue-loader at least v13.0.0+
// router.js中引用
const _import = require('./_import_' + process.env.NODE_ENV);
{
path: 'course',
component: _import('course/index'),
name: 'course'
}
复制代码
图片懒加载(vue-lazyload)
在图片没有进入可视区域时先不给img的src赋值,优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能
// 安装
npm install vue-lazyload --save-dev
// 使用 main.js
import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
Vue.use(VueLazyload, {
preLoad: 1.8,
error: require('@/assets/lazy/error.png'),
loading: require('@/assets/lazy/loading.png'),
attempt: 1,
listenEvents: ['scroll']
});
new Vue({
el: 'body',
components: {
App
}
});
// 在使用图片的地方加上v-lazy即可
<img v-lazy="img.src" >
复制代码
更多使用方式可参考vue-lazyload 这里呈现的效果就是,请求完成数据,再去请求阿里云存放的图片,这个阶段中,图片资源加载过程中,显示loading的状态,加载完毕,显示图片,如果图片加载失败,显示失败的图片。
Promise
课程首页的请求数为8,请求都为异步请求,而我们的浏览器对同一域下的请求数量是有限制的,超过限制数目的请求会被阻塞,以谷歌浏览器的6个并发请求量为例,课程首页的数据请求和图片请求加起来成百上千个,上面,我们对图片请求已经做了处理,使用懒加载的方式,另外,放在和数据请求不同的域下,我们需要考虑的就是数据请求,采用了promise的方式,如下:
return new Promise((resolve,reject) => {
})
采用这种方式的另一个原因是,如果所有异步请求同时触发的话,浏览器会为他们分配执行的优先级,而采用这种方式,请求的顺序会按照我们调用的顺序执行。而浏览器分配的话,可能页面底部的请求会先执行。在请求较少的情况下,这种差异是体现的不明显。
提到promise,我觉得最大的好处就是如它设计的初衷那样,解决了层层回调的问题(难以维护,且不优雅)--链式调用,还有Promise.all()的用法,对于组合数据很方便。
减少http请求
网页中的的图片、form、flash等等元素都会发出HTTP请求,尽可能的减少页面中非必要的元素,可以减少HTTP请求的次数。
CSS Sprites ——精灵(雪碧)图
图片是增加HTTP请求的最大可能者;把全站的图标都放在一个图像文件中,然后用CSS的background-image和background-position属性定位来显示其中的一小部分。
压缩图片
图片是最占流量的资源,因此尽量避免使用它,使用时选择最合适的格式(实现需求的前提下,以大小判断),合适的大小,然后使用智图压缩,同时在代码中用Srcset来按需显示。
PS:过度压缩图片大小影响图片显示效果
a) 使用智图( http://zhitu.tencent.com/ )
b) 使用其它方式代替图片(1. 使用CSS3 2. 使用SVG 3. 使用IconFont)
c) 使用Srcset
d) 选择合适的图片(1. webP优于JPG 2. PNG8优于GIF)
e) 选择合适的大小(1. 首次加载不大于1014KB 2. 不宽于640(基于手机屏幕一般宽度))
CDN内容分发网络
CDN优化原理
用户在通过浏览器访问未使用CDN加速的网站的大致过程如下:
- 用户在浏览器中输入要访问的域名。
- 浏览器向DNS服务器请求对该域名的解析。
- DNS服务器返回该域名的IP地址给浏览器。
- 浏览器使用该IP地址向服务器请求内容。
- 服务器将用户请求的内容返回给浏览器。
如果使用了CDN,则其过程会变成以下这样
- 用户在浏览器中输入要访问的域名。
- 浏览器向DNS服务器请求对域名进行解析。由于CDN对域名解析进行了调整,DNS服务器会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器。
- CDN的DNS服务器将CDN的负载均衡设备IP地址返回给用户。
- 用户向CDN的负载均衡设备发起内容URL访问请求。
- CDN负载均衡设备会为用户选择一台合适的缓存服务器提供服务。
选择的依据包括:
根据用户IP地址,判断哪一台服务器距离用户最近;
根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;
查询各个服务器的负载情况,判断哪一台服务器的负载较小。
基于以上这些依据的综合分析之后,负载均衡设置会把缓存服务器的IP地址返回给用户。 - 用户向缓存服务器发出请求。
- 缓存服务器响应用户请求,将用户所需内容传送到用户。
如果这台缓存服务器上并没有用户想要的内容,而负载均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉取到本地。
CDN优化总结
在网站和用户之间引入CDN之后,用户不会有任何与原来不同的感觉。
使用CDN服务的网站,只需将其域名的解析权交给CDN的负载均衡设备,CDN负载均衡设备将为用户选择一台合适的缓存服务器,用户通过访问这台缓存服务器来获取自己所需的数据。
由于缓存服务器部署在网络运营商的机房,而这些运营商又是用户的网络服务提供商,因此用户可以以最短的路径,最快的速度对网站进行访问。因此,CDN可以加速用户访问速度,减少源站中心负载压力。
少用location.reload()
使用location.reload() 会刷新页面,刷新页面时页面所有资源(css,js,img等)会重新请求服务器;建议使用location.href=“当前页url” 代替location.reload() ,使用location.href 浏览器会读取本地缓存资源。
正确使用display的属性
display属性会影响页面的渲染,需要合理使用。
a) display:inline后不应该再使用width、height、margin、padding以及float
b) display:inline-block后不应该再使用float
c) display:block后不应该再使用vertical-align
d) display:table-*后不应该再使用margin或者float
按需加载
将不影响首屏的资源和当前屏幕资源不用的资源放到用户需要时才加载,可以大大提升重要资源的显示速度和降低总体流量。
PS:按需加载会导致大量重绘,影响渲染性能
a) LazyLoad
b) 滚屏加载
c) 通过Media Query加载
合理使用缓存
使用缓存可以减少向服务器的请求数,节省加载时间,所以所有静态资源都要在服务器端设置缓存,并且尽量使用长Cache(长Cache资源的更新可使用时间戳
预加载
以下是几个通过浏览器特性来很容易提高资源加载速度的方法:
1:DNS prefetching
DNS解析的速度可用通过下面的标签来进行预解析
<link rel=”dns-prefetch” href=”//weibo.com”>
2:Preconnect
和DNS预解析差不多,Preconnect还会做TCP握手和TLS Negotiation:
<link rel=”preconnect” href=”http://css-tricks.com”>。
3:Prefetching
如果我们猜测用户接下来将要访问哪个具体的资源,那就可以用prefetching来预加载确定的资源了
<link rel=”prefetch” href=”image.png”>
4:Prerendering pages
预先渲染页面,这是更牛的预加载方式了,他的作用就类似打开一个隐藏的tab差不多
<link rel=”prerender” href=”http://css-tricks.com”>
5:新特性:Preloading
和prefetching不同的是,preloading会让浏览器无论如何都下载指定的资源
<link rel=”preload” href=”image.png”>
6:H5音乐预加载
<audio src=”music.mp3″ autoplay=”autoplay” loop preload=”auto” id=”sendid2″></audio>
参考资料:
最近做首屏优化学到的知识点
关于首屏优化
首屏加载优化有哪些方案?
网站首屏优化总结
web前端性能优化之CDN