perf(banner): smoother deep-link from banner to /browse post
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 27s

- MessageStream: drop the mount-time scroll lock and the 80ms-delayed
  custom rAF; engage the lock only while the smooth animation runs and
  use native scrollTo({behavior:'smooth'}) so the page never feels frozen
  during pagination and the easing is buttery.
- PublicLayout: fire the default /browse prefetch immediately on mount
  (banner / Home tile destination) so a fast tap hits a warm cache;
  popular / latest stay deferred to idle.
- FigmaBanner: prefetch the all-scope stream on mount and on pointerdown
  as safety nets, and ignore empty / '#' / javascript: link URLs so a
  contentless banner renders as a non-interactive image.
- usePostStream: dedupe in-flight prefetches by key so concurrent
  callers (layout + banner) collapse into a single network request.
This commit is contained in:
TerryM
2026-06-02 11:30:47 +08:00
parent fbb9d21f24
commit 7ed9f8c8bf
4 changed files with 75 additions and 53 deletions

View File

@@ -333,14 +333,16 @@ export function PublicLayout() {
// Current page name shown in the header brand slot (falls back to the brand).
const pageTitle = usePageTitle();
// Warm the common stream views (全部资料 / 热门资料 / 最新) in the background so
// tapping them shows content immediately. Run one at a time, spaced out and
// only while idle, so prefetching never competes with the current page or
// janks low-end phones. Prefetch is JSON-only (no images).
// Warm the common stream views (全部资料 / 热门资料 / 最新) so tapping them
// shows content immediately. The default "all" stream is the most common
// destination (banners, Home cards) and fires right on mount so a fast tap
// still hits a warm cache. Popular / latest stay deferred to idle time so
// they don't compete with the current page on low-end phones.
useEffect(() => {
const base = { scope: { kind: "all" as const }, type: "all", q: "", lang };
prefetchPostStream({ ...base, sort: "" });
const jobs = [
() => prefetchPostStream({ ...base, sort: "" }),
() => prefetchPostStream({ ...base, sort: "popular" }),
() => prefetchPostStream({ ...base, sort: "latest" }),
];
@@ -362,7 +364,7 @@ export function PublicLayout() {
else stepTimer = window.setTimeout(runNext, 200);
};
const startTimer = window.setTimeout(schedule, 600);
const startTimer = window.setTimeout(schedule, 300);
return () => {
window.clearTimeout(startTimer);
window.clearTimeout(stepTimer);