一种高效的网页预读方法

2019-08-29 23:03:23 +08:00
 autoxbc

预读网页的做法,一般是提前获取下一页引用的资源,在进入下一页时可以缩短加载时间

获取资源有以下一些方法

  1. 读取 html,分析其中的资源,再预读资源
    缺点:前后端分离使得现代网页的 DOM 大多是动态生成,其中的资源无法简单的静态分析出来

  2. 为下一页生成隐形 iframe,因为其中有完整的网页渲染,资源全部可见
    缺点:即便读到了资源,进入下一页时仍然需要重新渲染 DOM,有时有性能问题

  3. 对个别网站单独分析,得到下一页引用的资源地址,在本页更新 DOM(比如图集的无限滚动)
    缺点:需要对每个网站单独编写规则,URL 的标记位置功能弱化

方法 1 基本是落后的做法,已没有实际意义;
方法 3 对每个网站编写规则过于繁琐;
对方法 2,只要稍加改动,就能极大改善效率,即:用 iframe 中渲染完成的 DOM 直接替换上层页面的 DOM,瞬间完成切换

document.body.replaceWith( iframe.contentWindow.document.body );

以下是以豆瓣图集为例子的油猴代码
https://gist.github.com/autoxbc/badda87b6867b377a834b664d7f735d1

测试页
https://movie.douban.com/subject/27010768/photos

页面载入完毕后,点击下一页按钮,可以看到过渡是瞬间完成的,没有延迟和抖动

同时,豆瓣图集脚本里实现了一个简单的暗黑主题模式。
一般来说,暗黑主题经常出现进入下一页时显示一个瞬间白屏,破坏了暗黑状态。 这是因为不管暗黑主题的加载代码性能多好,都会有个瞬间露出 html 的纯白底色 而上面的 DOM 替换法,没有过渡过程,使得暗黑主题不会漏白

虽然上面的代码稍长,其中预读的部分仅有一句代码

preLoadURL( target ,'.paginator .next a');

对任意网站,只需要找出翻页按钮的选择器,不需要分析页面结构和资源地址。 进一步的,用一段代码去查找翻页按钮的位置,甚至可以省略选择器,达到完全网站无关

4734 次点击
所在节点    JavaScript
20 条回复
bin1024
2019-08-29 23:07:38 +08:00
好东西,谢谢分享
momocraft
2019-08-29 23:08:45 +08:00
可能不容易完全无关

纯 html 网页应该 OK, 有 js 的网页只替换 body 可能有问题, 全 js 的网页可能有更大问题
love
2019-08-29 23:26:58 +08:00
这种有什么用?

就为了快速显示下一页?那不如在 iframe 里加载下一页,然后切页面时直接把 iframe 全屏
misaka19000
2019-08-30 00:20:26 +08:00
instantClick 了解一下?
autoxbc
2019-08-30 00:46:50 +08:00
@momocraft #2 就我个人而言,不破坏网站原有功能并不是预设。我只对资源感兴趣,拿到资源就够了
autoxbc
2019-08-30 00:58:21 +08:00
@love #3 那种切换的快速不是语言能形容的,建议用一下试试

另外,iframe 全屏并不可行
autoxbc
2019-08-30 01:05:16 +08:00
@misaka19000 #4 谢谢,第一次听说这个项目。粗略看了下源码,和我的思路基本是一致的

不过 InstantClick 获取下一页 DOM 的方法是 XHR,并不是真的渲染,过于保守的策略决定了效果一般
jinliming2
2019-08-30 01:08:40 +08:00
逻辑上有点问题。
如果是纯 html 页面,那么第一种方案足够。
如果是 js 渲染的页面,除非做了路由,不然你是拿不到下一页的 URL 的,因为本身就没有,所以也就没办法创建 ifream 了。
再者,即便是拿到了 URL,可以在 iframe 中渲染出了下一页,然后采取 DOM 替换的形式去更新页面,这对于正常的 html 页面可能没什么,但是对于 js 渲染的页面来说就彻底破坏了整个页面当前的状态,原本由 js 创建并管理的 DOM 全部丢失,轻一点可能会抛各种异常,严重一点可能会带来内存侧漏。
如果像楼上说的直接把 iframe 全屏的方式,分页浏览得到的结果就是一万层 iframe 嵌套?
binux
2019-08-30 01:18:40 +08:00
你确定这样不会重新 layout ?
Yourshell
2019-08-30 01:44:03 +08:00
瓶颈不是网络 IO 吗?
msg7086
2019-08-30 01:58:45 +08:00
好像就是一个能预读的 turbolinks ?
imdong
2019-08-30 02:26:34 +08:00
曾经,某些浏览器自动预读下一页加速...
后来,听说预读了删除按钮,就没怎么见过这个功能了...
autoxbc
2019-08-30 02:27:42 +08:00
@jinliming2 #8 逻辑是这样的:
1. 并不存在纯 html 页面
对网站开发者来说的纯 html 页面,对浏览者来说可能需要用脚本修改 DOM(比如我脚本里把豆瓣缩略图导航页改成了高清图滚动浏览页)。这个修改后的 DOM 就是动态得到的,如果这个修改过程引用了新的资源,那么这个页面必须在 iframe 里渲染才能预读这个新资源

2. js 渲染的页面,渲染后也是 html,可以拿到下一页 URL。整个路由全在代码里,在 DOM 里根本不体现,这样的网站凤毛麟角

3. 油猴开发就是 hack,破坏是难免的。这种预读,不是浏览器级的基础设施,不需要绝对兼容,得到想要的结果就够了
autoxbc
2019-08-30 02:31:18 +08:00
@binux #9 重新 layout 足够快就像用原生代码读本地资源
autoxbc
2019-08-30 02:36:11 +08:00
@Yourshell #10 网络 IO 的瓶颈消除后,DOM 渲染就是新的瓶颈。100ms 变成 0ms,是可以感知到的
codehz
2019-08-30 07:33:00 +08:00
其实 google 还推出了 portal 这种东西来辅助预载,可以说有异曲同工之处了 https://web.dev/hands-on-portals
lc1450
2019-08-30 09:52:42 +08:00
记得当年山寨手机流行时,一些浏览器就有这个功能,那时候主要是网速慢,现在网速快了,好像不是很需要了
cuzfinal
2019-08-30 14:37:11 +08:00
弄个 serviceWorker,用 cache,啥都能缓存。
autoxbc
2019-08-30 15:43:45 +08:00
@codehz #16 多谢介绍,portal 这个东西完美了,确实需要在浏览器级做这个事情
autoxbc
2019-08-30 15:48:04 +08:00
@lc1450 #17 现在也需要的。如果下一页有几百兆(图集类),就算本地是千兆对等网也没用,因为网站不会跟你千兆对传

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/596370

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX