Inline PDF 预览在浏览主题时重置到第 1 页

摘要

内联 PDF 预览在滚动浏览长篇主题时,其滚动位置(返回第 1 页)会持续重置。这发生的原因是,当帖子滚动出视图时,PDF 嵌入被销毁并重新插入,这很可能是由于 Discourse 的帖子流回收/虚拟化机制导致的。

这会影响所有浏览器、所有 PDF,即使禁用所有插件和主题也会发生。

重现步骤

  1. 创建一个带有 PDF 附件的主题。
  2. 确保“内联 PDF 预览”组件处于激活状态。
  3. 向下滚动主题,直到包含 PDF 的帖子离开视口。
  4. 滚动回同一个 PDF 预览。
  5. 结果:
    • PDF 从头开始重新加载。
    • 预览的滚动位置丢失。
    • PDF 像刚加载时一样被重新渲染。

没有发生对 PDF 的网络请求,这表明 DOM 节点在本地被移除并重新创建。

预期行为

  • PDF 预览应保持其滚动位置,不应仅仅因为滚动主题而重新加载。
  • 其他嵌入式内容(图像、视频、Onebox)在滚动时不会重置状态;PDF 预览应保持一致的行为。

实际行为

  • 一旦帖子超出可见范围,Discourse 就会卸载 DOM 节点。
  • 当帖子滚动回视图时,嵌入被重建。
  • 这会强制浏览器的原生 PDF 渲染器从第 1 页重新开始。
  • 每当帖子离开视口(向上或向下)时,都会发生这种情况。

环境

  • 在所有测试过的浏览器中都会发生:Chrome、Firefox、Safari、Edge
  • 禁用所有插件时发生(安全模式)
  • 禁用所有主题组件时发生
  • 使用多个不同大小和格式的 PDF 文件时发生
  • 在 Discourse (tests-passed) 最新分支上发生(截至发布之日)

技术说明

Discourse 似乎正在作为流虚拟化的一部分卸载屏幕外的帖子组件。由于 PDF 预览使用简单的 \<embed\> / \<iframe\>,它没有持久化机制,因此每当发生以下情况时,它就会完全重置:

  • 触发 willDestroyElement()
  • 帖子容器被重新渲染
  • DOM 节点在重新进入视口时被重建

这对于 PDF 来说是独有的,因为浏览器原生的 PDF 查看器在 DOM 重建过程中不会保留滚动状态。这使得带有 PDF 的长篇主题阅读起来很令人沮丧,特别是对于多页附件。

所需的解决方案

  • 防止“内联 PDF 预览”组件在帖子回收期间被销毁,或者
  • 提供一种方式让插件/主题组件声明“持久化状态”,以便 Discourse 不会卸载它们,或者
  • 暴露一个站点设置,为包含内联 PDF 查看器的帖子禁用帖子流回收。

即使是部分修复——例如,跳过对包含 PDF 嵌入的帖子的回收——也能解决问题。

附加背景

这不是一次性的环境问题:在干净的测试构建、多种浏览器和跨 PDF 的情况下都可靠地重现了此问题。

Meta(论坛)上没有描述此行为的主题,因此这可能是流虚拟化改进带来的未报告的回归或意外后果。

1 个赞