From 87bab8662cea05fd3ec040518cacc19864598e03 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Wed, 7 Aug 2019 09:11:34 -0700 Subject: [PATCH] perf: use requestPostAnimationFrame to reduce layout thrashing (#1376) --- .../_components/compose/ComposeInput.html | 3 +- .../virtualList/VirtualListItem.html | 3 +- src/routes/_utils/RealmStore.js | 3 +- .../_utils/requestPostAnimationFrame.js | 36 +++++++++++++++---- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/routes/_components/compose/ComposeInput.html b/src/routes/_components/compose/ComposeInput.html index 4bb079fe..27e62091 100644 --- a/src/routes/_components/compose/ComposeInput.html +++ b/src/routes/_components/compose/ComposeInput.html @@ -69,6 +69,7 @@ import { observe } from 'svelte-extras' import { get } from '../../_utils/lodash-lite' import { on } from '../../_utils/eventBus' + import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame' export default { oncreate () { @@ -117,7 +118,7 @@ }, setupAutosize () { const textarea = this.refs.textarea - requestAnimationFrame(() => { + requestPostAnimationFrame(() => { mark('autosize()') autosize(textarea) stop('autosize()') diff --git a/src/routes/_components/virtualList/VirtualListItem.html b/src/routes/_components/virtualList/VirtualListItem.html index fae5f02e..50fc61c8 100644 --- a/src/routes/_components/virtualList/VirtualListItem.html +++ b/src/routes/_components/virtualList/VirtualListItem.html @@ -28,12 +28,13 @@ import { virtualListStore } from './virtualListStore' import { registerResizeListener, unregisterResizeListener } from '../../_utils/resize' import { mark, stop } from '../../_utils/marks' + import { requestPostAnimationFrame } from '../../_utils/requestPostAnimationFrame' export default { oncreate () { const { key } = this.get() const node = this.refs.node - requestAnimationFrame(() => { + requestPostAnimationFrame(() => { if (!node || !key) { return } diff --git a/src/routes/_utils/RealmStore.js b/src/routes/_utils/RealmStore.js index de3318d0..39c7312c 100644 --- a/src/routes/_utils/RealmStore.js +++ b/src/routes/_utils/RealmStore.js @@ -4,6 +4,7 @@ import { Store } from 'svelte/store.js' import QuickLRU from 'quick-lru' import { mark, stop } from './marks' +import { requestPostAnimationFrame } from './requestPostAnimationFrame' export class RealmStore extends Store { constructor (init, maxSize) { @@ -47,7 +48,7 @@ export class RealmStore extends Store { } batch[subKey] = value - requestAnimationFrame(() => { + requestPostAnimationFrame(() => { const batch = this._batches[currentRealm] && this._batches[currentRealm][key] if (!batch) { return diff --git a/src/routes/_utils/requestPostAnimationFrame.js b/src/routes/_utils/requestPostAnimationFrame.js index d218d27f..f6d37248 100644 --- a/src/routes/_utils/requestPostAnimationFrame.js +++ b/src/routes/_utils/requestPostAnimationFrame.js @@ -1,9 +1,33 @@ // modeled after https://github.com/andrewiggins/afterframe // see also https://github.com/WICG/requestPostAnimationFrame -export const requestPostAnimationFrame = cb => { - requestAnimationFrame(() => { - const channel = new MessageChannel() - channel.port1.onmessage = cb - channel.port2.postMessage(undefined) - }) +const channel = process.browser && new MessageChannel() +const callbacks = [] + +if (process.browser) { + channel.port1.onmessage = onMessage +} + +function runCallback (callback) { + try { + callback() + } catch (e) { + console.error(e) + } +} + +function onMessage () { + for (const callback of callbacks) { + runCallback(callback) + } + callbacks.length = 0 +} + +function postMessage () { + channel.port2.postMessage(undefined) +} + +export const requestPostAnimationFrame = callback => { + if (callbacks.push(callback) === 1) { + requestAnimationFrame(postMessage) + } }