V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
autoxbc
V2EX  ›  JavaScript

一种高效的网页预读方法

  •  1
     
  •   autoxbc · 2019-08-29 23:03:23 +08:00 · 4504 次点击
    这是一个创建于 1694 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    获取资源有以下一些方法

    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');
    

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

    20 条回复    2019-08-30 15:48:04 +08:00
    bin1024
        1
    bin1024  
       2019-08-29 23:07:38 +08:00 via Android   ❤️ 1
    好东西,谢谢分享
    momocraft
        2
    momocraft  
       2019-08-29 23:08:45 +08:00
    可能不容易完全无关

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

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

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

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

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

    3. 油猴开发就是 hack,破坏是难免的。这种预读,不是浏览器级的基础设施,不需要绝对兼容,得到想要的结果就够了
    autoxbc
        14
    autoxbc  
    OP
       2019-08-30 02:31:18 +08:00
    @binux #9 重新 layout 足够快就像用原生代码读本地资源
    autoxbc
        15
    autoxbc  
    OP
       2019-08-30 02:36:11 +08:00
    @Yourshell #10 网络 IO 的瓶颈消除后,DOM 渲染就是新的瓶颈。100ms 变成 0ms,是可以感知到的
    codehz
        16
    codehz  
       2019-08-30 07:33:00 +08:00 via Android   ❤️ 2
    其实 google 还推出了 portal 这种东西来辅助预载,可以说有异曲同工之处了 https://web.dev/hands-on-portals
    lc1450
        17
    lc1450  
       2019-08-30 09:52:42 +08:00
    记得当年山寨手机流行时,一些浏览器就有这个功能,那时候主要是网速慢,现在网速快了,好像不是很需要了
    cuzfinal
        18
    cuzfinal  
       2019-08-30 14:37:11 +08:00
    弄个 serviceWorker,用 cache,啥都能缓存。
    autoxbc
        19
    autoxbc  
    OP
       2019-08-30 15:43:45 +08:00
    @codehz #16 多谢介绍,portal 这个东西完美了,确实需要在浏览器级做这个事情
    autoxbc
        20
    autoxbc  
    OP
       2019-08-30 15:48:04 +08:00
    @lc1450 #17 现在也需要的。如果下一页有几百兆(图集类),就算本地是千兆对等网也没用,因为网站不会跟你千兆对传
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5280 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 999ms · UTC 05:57 · PVG 13:57 · LAX 22:57 · JFK 01:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.