From 25fd8466e07a6ffc1e1bf3765e90029c5e4047fc Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 10 Feb 2022 19:29:25 -0800 Subject: [PATCH] perf: Move to passive scroll listeners where supported --- app/components/Header.tsx | 7 ++++++- app/hooks/useWindowScrollPosition.ts | 19 ++--------------- .../Document/components/MultiplayerEditor.tsx | 9 ++++++-- app/utils/browser.ts | 21 +++++++++++++++++++ 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 299fb2d20..7866fc075 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -10,6 +10,7 @@ import Fade from "~/components/Fade"; import Flex from "~/components/Flex"; import useMobile from "~/hooks/useMobile"; import useStores from "~/hooks/useStores"; +import { supportsPassiveListener } from "~/utils/browser"; type Props = { breadcrumb?: React.ReactNode; @@ -33,7 +34,11 @@ function Header({ breadcrumb, title, actions, hasSidebar }: Props) { ); React.useEffect(() => { - window.addEventListener("scroll", handleScroll); + window.addEventListener( + "scroll", + handleScroll, + supportsPassiveListener ? { passive: true } : false + ); return () => window.removeEventListener("scroll", handleScroll); }, [handleScroll]); diff --git a/app/hooks/useWindowScrollPosition.ts b/app/hooks/useWindowScrollPosition.ts index 0e8bd5367..d48ef1149 100644 --- a/app/hooks/useWindowScrollPosition.ts +++ b/app/hooks/useWindowScrollPosition.ts @@ -2,22 +2,7 @@ // maintained. import { throttle } from "lodash"; import { useState, useEffect } from "react"; - -let supportsPassive = false; - -try { - const opts = Object.defineProperty({}, "passive", { - get: function () { - supportsPassive = true; - }, - }); - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - window.addEventListener("testPassive", null, opts); - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - window.removeEventListener("testPassive", null, opts); -} catch (e) { - // No-op -} +import { supportsPassiveListener } from "~/utils/browser"; const getPosition = () => ({ x: window.pageXOffset, @@ -44,7 +29,7 @@ export default function useWindowScrollPosition(options: { window.addEventListener( "scroll", handleScroll, - supportsPassive + supportsPassiveListener ? { passive: true, } diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 3834d668d..0c0da6d95 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -15,6 +15,7 @@ import usePageVisibility from "~/hooks/usePageVisibility"; import useStores from "~/hooks/useStores"; import useToasts from "~/hooks/useToasts"; import MultiplayerExtension from "~/multiplayer/MultiplayerExtension"; +import { supportsPassiveListener } from "~/utils/browser"; import { homePath } from "~/utils/routeHelpers"; type Props = EditorProps & { @@ -76,7 +77,7 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { "scrollY", window.scrollY / window.innerHeight ); - }, 200); + }, 250); const finishObserving = () => { if (ui.observingUserId) { @@ -86,7 +87,11 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { window.addEventListener("click", finishObserving); window.addEventListener("wheel", finishObserving); - window.addEventListener("scroll", syncScrollPosition); + window.addEventListener( + "scroll", + syncScrollPosition, + supportsPassiveListener ? { passive: true } : false + ); provider.on("authenticationFailed", () => { showToast( diff --git a/app/utils/browser.ts b/app/utils/browser.ts index a01dceaa7..2fc7fb098 100644 --- a/app/utils/browser.ts +++ b/app/utils/browser.ts @@ -15,3 +15,24 @@ export function isMac(): boolean { const SSR = typeof window === "undefined"; return !SSR && window.navigator.platform === "MacIntel"; } + +let supportsPassive = false; + +try { + const opts = Object.defineProperty({}, "passive", { + get: function () { + supportsPassive = true; + }, + }); + // @ts-expect-error ts-migrate(2769) testPassive is not a real event + window.addEventListener("testPassive", null, opts); + // @ts-expect-error ts-migrate(2769) testPassive is not a real event + window.removeEventListener("testPassive", null, opts); +} catch (e) { + // No-op +} + +/** + * Returns true if the client supports passive event listeners + */ +export const supportsPassiveListener = supportsPassive;