单页Web应用(single page web application,SPA)会一次性载入页面资源,利用本地计算能力渲染页面,提高页面切换速度与用户体验。由此带来了首屏加载缓慢耗时的诟病,这也是困扰前端开发工程师的一重大难题。
最近查阅了一些帖子,发现了一个极其强大的方法,其兼容性有待提高~~(但已有相关的的Polyfill方式)
按需加载
可以减小组件加载的大小,节省网络带宽,从而提高响应速度!
异步加载组件
首先我们可以将应用拆成多个模块组件,然后异步加载组件。配合webpack代码分割使用,达到按需加载的效果(下述只简单陈述,不做详细讲解)。
补充,webpack有三种常用的代码分割方式:
- 入口起点:使用 entry 配置手动地分离代码。
- 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
- 动态导入:通过模块的内联函数调用来分离代码。
注意,webpack中需要配置相关信息
注意,
filename
决定了bundle的名称。但是此选项不会影响那些「按需加载 chunk」的输出文件。对于这些文件,请使用 output.chunkFilename选项来控制输出。通过 loader 创建的文件也不受影响。在这种情况下,你必须尝试 loader 特定的可用选项。
懒加载
通过监听滚动条来判断是否在可视区域进行加载处理,document.documentElement.clientHeight > dom.getBoundingClientRect().top
注意:要对已加载的资源进行标识,防止重复加载!
该方式通过监听到scroll
事件后,调用目标元素(绿色方块)的getBoundingClientRect()方法,得到它对应于视口信息,再判断是否在视口之内。这种方法的缺点是,由于scroll
事件密集发生(当然可以使用节流函数进行相应处理),计算量很大,容易造成性能问题!
IntersectionObserver
IntersectionObserver接口为开发者提供了一种可以异步监听目标元素与其祖先或视窗(viewport)交叉状态的手段。该API 是异步的(降低了昂贵的DOM和样式查询开销、以及CPU、GPU能源成本),不随着目标元素的滚动同步触发,对于理解元素的可见性以及实现DOM内容的预加载和延迟加载非常有用。
entries为IntersectionObserverEntry对象,包含如下属性:
- time:可见性发生变化的时间,毫秒;
- target:被观察的目标元素,DOM节点对象;
- rootBounds:根元素的矩形区域的信息,
getBoundingClientRect()
方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
;- boundingClientRect:目标元素的矩形区域的信息;
- intersectionRect:目标元素与视口(或根元素)的交叉区域的信息;
- intersecttionRatio:目标元素的可见比例;
options为IntersectionObserverInit 对象,包含如下属性:
- root:指定目标元素所在的容器节点(即根元素);
- rootMargin:用来扩展或缩小
rootBounds
这个矩形的大小,从而影响intersectionRect
交叉区域的大小;- threshold:决定了什么时候触发回调函数
class名称为‘target’的元素,在可见比例为[0, 0.25, 0.5, 0.75, 1]均会执行相关回调函数!
实现懒加载:
实例地址:https://github.com/381510688/practice/blob/master/javascript_test/lazyLoad.html
兼容性
Github上提供了相关的Polyfill方式:IntersectionObserver polyfill
参考地址:
- https://www.w3.org/TR/intersection-observer/
- http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
- https://github.com/xunleif2e/vue-lazy-component