内容简介:谷歌团队在几个月前开源了一个项目,叫这里简单的介绍一下这个项目,并且说明一下为什么我需要fork这个项目~quicklink的源码很简洁,作用可以用一句话总结:
谷歌团队在几个月前开源了一个项目,叫
quicklink
。官方给出的介绍是
Faster subsequent page-loads by prefetching in-viewport links during idle time
这里简单的介绍一下这个项目,并且说明一下为什么我需要fork这个项目~
quicklink的源码很简洁,作用可以用一句话总结: 利用空闲时间来缓存界面上看到的链接,加快这些链接的访问速度。
所以quicklink的作用是在下一个链接快速打开,而不是当前链接,这一点和很多其他优化都不一样。
原理很简单:
- 获取页面上所有的A标签(注意,这里的a标签指的是调用函数的时候document下的a标签)
- 等待浏览器空闲 (requestIdleCallback 或者用 setTimeout 做兼容)
- 利用 IntersectionObserver 做监控,当监控的dom进入视图,就开始预加载
-
与获取视图内的URL(
<link rel="prefetch">
orXHR
orfetch
),以获得快速访问该链接的效果
代码真的很简洁,很棒,这边没必要再贴出来,有兴趣的直接github fork一个去看或修改,除去注释代码量加起来不到200行
forked
我fork该项目之后修改了一些东西
默认添加了polyfill,直接打到包里
为什么要加polyfill呢? 因为 IntersectionObserver
虽然好用,但是pc端 IE11
都不支持,移动端也要到了 IOS12 safari
才支持…支持面太窄了而且不用polyfill的话,直接报错….所以权衡之下,干脆直接全量引用 IntersectionObserver
的polyfill,gzip情况下整个包加起来才 3.5k
值了。
添加了quicklink全局配置
在包里写了 quicklinkOptions
对象,这样每次调用 quicklink
的时候就可以公用一些配置,而不需要每次调用都塞一样的配置进去,至于为什么提到每次调用…后面会解释到
添加了manualPreFetch方法: 手动绑定某些dom监听
manualPreFetch
方法,就是手动的意思,支持传入这些参数 {dom, isForce, link, priority}
。
为什么需要加多个方法呢? 因为我发现 quicklink 只支持扫 <a>
标签去获取link,但是很多情况可能我们不是用a标签,而是类似写一个 button
,点击之后js控制跳转。 虽然说我们可以在代码层用button包a链接等方式去实现,但是这样就太局限了,所以才加了个方法。
// html <button id="btn">跳转到xxx</button> manualPreFetch({ dom: document.getElementById('btn'), link: 'www.easyrentcars.com', });
该方法和 quicklink
一样,也是监听dom滚到当前位置才会发起预加载。这里会读取一部分的 quicklinkOptions
,这就是我加多个全局配置的原因了,不需要每次调用的时候都写一堆
增加了manualRemovePreFetch方法: 手动删除监听预加载
添加个移除的方法,只是简单的移除掉要监听的dom,虽然对性能不会造成影响…但是就是有点强迫症鸭
React demo
quicklink
是在执行的时候用 (el || document).getQuesySelectorAll('a')
去获取页面上的 <a>
,所以对于React就比较尴尬了,渲染是异步的,如果调用早的话,肯定是拿不到,那什么时候调用这个才是最佳时机?
比较通用的是 componentDidMount
或者是 UseEffect
。不过个人比较建议配合 manualPreFetch
、 manualRemovePreFetch
对一些比较重要的加就好了,因为很多都是异步之后再渲染,可能 componentDidMount
的时候,你需要预加载的链接还没出现。
这里简单给出两个关于React的通用demo。
import React, { useEffect, useRef } from 'react'; import quicklink, { manualPreFetch, manualRemovePreFetch} from '@jsonz/quicklink'; // class 类型 class QuicklinkComponent extends React.Component { constructor(props) { super(props); this.refRoot = React.createRef(); } componentDidMount() { // didMount 监听组件内所有的a链接 quicklink({ el: this.refRoot.current, }); } componentWillUnmount() { // willunmount 移除所有的a链接监听 batchManualRemove(this.refRoot.current); } render() { return <div ref={this.refRoot}>{this.props.children}</div> } } // hook 类型 function QuicklinkDemo() { const refRoot = useRef(null); useEffect(()=> { quicklink({ el: refRoot.current, }); return ()=> { batchManualRemove(refRoot.current); } }); return ( <div ref={refRoot}>{this.props.children}</div> ); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 结合自己的经历谈谈怎么更好地学习Go语言
- 隐私保护新突破:高斯差分隐私框架与深度学习结合
- 寒武纪CEO陈天石:深度学习处理一定要端云结合
- Marcus再怼深度学习:不和符号计算相结合,可能无法进步!
- SNDBOX:结合人工智能与机器学习的恶意软件分析平台
- 传统图像算法+深度学习方法结合会有什幺样的火花?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java 8函数式编程
[英] Richard Warburton / 王群锋 / 人民邮电出版社 / 2015-3 / 39.00元
通过每一章的练习快速掌握Java 8中的Lambda表达式 分析流、高级集合和其他Java 8类库的改进 利用多核CPU提高数据并发的性能 将现有代码库和库代码Lambda化 学习Lambda表达式单元测试和调试的实践解决方案 用Lambda表达式实现面向对象编程的SOLID原则 编写能有效执行消息传送和非阻塞I/O的并发应用一起来看看 《Java 8函数式编程》 这本书的介绍吧!