Lazy image loading never defers: IntersectionObserver runs before the placeholder is sized
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 76/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- javascript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Đọc src/nodes/ImageView.vue, đặc biệt là mounted() và loadAttachmentMetadata(). Issue xác định việc chờ tải siêu dữ liệu trước khi tạo IntersectionObserver là cách sửa được đề xuất. Tái hiện vấn đề với nhiều hình ảnh và xác minh rằng ban đầu chỉ những hình ảnh gần khung nhìn được tải. Sau đó cuộn trang để xác nhận các hình ảnh còn lại được tải.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
Every image in a document is downloaded as soon as the document opens, regardless of whether it is on screen. On a remote server this makes a document with a handful of images take many seconds to become usable.
Text already implements lazy loading (see #4519). This bug asked for the fix and was closed in May 2025. So the IntersectionObserver is there in ImageView.vue. But it never gets the chance to defer anything.
In src/nodes/ImageView.vue (line 303 on main), mounted() calls loadAttachmentMetadata() without awaiting it:
mounted() {
this.attachmentPromise = this.$attachmentResolver.resolve(this.src)
this.loadAttachmentMetadata() // not awaited
...
this.$nextTick(() => { /* IntersectionObserver created here */ })
The placeholder's height comes from the photos-size metadata that this call resolves and the observer judges visibility from that height. Because it is not awaited, the observer runs while every figure is still a 16px stub stacked inside the viewport. Because of this, all of them count as visible and every image is loaded.
The fix is to use async mounted() and await this.loadAttachmentMetadata(). How we measured it is below.
Related: without the Photos app there is no photos-size metadata at all, so no placeholder is sized and lazy loading cannot work regardless of this bug. The code anticipates this ("bump up to warn when the Photos dependency is gone"), but the degradation currently is silent.
To Reproduce
- Enable the Photos app, so images carry
photos-sizemetadata. Upload the images after enabling it. - Create a document containing ~6 images of a few MB each, tall enough that most are several screens below the fold.
- In devtools, throttle the network to roughly 150 ms RTT / 10 Mbps.
- Open the document with the Network tab recording.
- Every image is requested immediately, including ones far below the fold.
Expected behavior
The code requests only the images at or near the viewport when the note is opened. The rest load as they are scrolled into view. This is my understand of what IntersectionObserver in ImageView.vue is written to accomplish.
Screenshots
Not applicable because the useful evidence is the timing, in the Logs section below.
Server details:
- Nextcloud version: 35.0.0 (35.0.0.10)
- PHP Version: 8.4.26
- Database: PostgreSQL 18.6
- Text app version: 9.0.0 (the same
mounted()is present onmain) - Photos app version: 8.0.0
Client details:
- OS: macOS
- Browser: Chromium (headless, via Playwright, for reproducible timing)
- Browser version: 153.0.8010.12
- Device: desktop
Logs
Nextcloud log (data/nextcloud.log)
Nothing relevant — this is entirely client-side.
Browser log
Network tab, document with six 2.5 MB images, 150 ms RTT / 10 Mbps:
BEFORE (stock Text 9.0.0)
- 6 image requests, all starting together, 15.15 MB total
- document ready: 14,384 ms
AFTER (await the metadata before creating the observer)
- 2 image requests, 5.05 MB total
- document ready: 6,426 ms
- scrolling through the rest: all 6 fetched and rendered, 0 failures
Polling each figure's height against the request start times shows the race:
- 790 ms 6 figures, heights [16,16,16,16,16,16] <- all inside the viewport
- 792 ms all six image requests start <- observer fires for all
- 804 ms 6 figures, heights [513,513,513,513,513,513] <- 4 of 6 now below the fold
The sizes that would have deferred four of the six arrive 12 ms after the decision has been made and the observers disconnected.
Diagnosis and measurements were produced with the help of Claude Code.
- Ngôn ngữ chính
- JavaScript
- Star
- 665
- Fork
- 133
- Merge trung bình
- 1 ngày 17 giờ
- Pull request đã merge (30 ngày)
- 172
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của nextcloud/text
-
0. Needs triage bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
nextcloud/text#9482 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
folder description not shows when using folder tree to navigateCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mởbug feature: folder description
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
1. to develop design call discuss discussion ux
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 58/100
nextcloud/text#9334 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Deleting a file from the editor's own "⋯" menu fails with 423 Locked: Text's own lock blocks itĐang mởbug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 56/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của nextcloud/text
Issue tương tự
-
bug documentation
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
awslabs/visual-asset-management-system#880 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[BUG]: Workspace settings forms stay at 50% width on narrow screens and wrap text word by wordĐang mởpossible bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Mintplex-Labs/anything-llm#6889 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
swc-project/swc-next#1165 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nhsuk/nhsuk-prototype-kit-package#439 ·
Maintainer thường phản hồi trong vòng 1 ngày