From 3299a282cb417dcc8a58f9632dd417705148bfb7 Mon Sep 17 00:00:00 2001 From: Cody Olsen Date: Mon, 8 Jul 2024 18:03:01 +0200 Subject: [PATCH] feat: testing multiple experimental perf boosting strategies --- dev/test-next-studio/next.config.mjs | 6 +- .../components/debugStyledComponents.tsx | 421 + .../LanguageFilterMenuButton.tsx | 17 +- dev/test-studio/sanity.config.ts | 2 + package.json | 8 +- .../package.bundle/src/package.bundle.ts | 12 +- packages/@repo/package.config/package.json | 3 + .../package.config/src/package.config.ts | 14 + .../src/components/PerspectivePopover.tsx | 16 +- packages/sanity/.eslintignore | 1 + packages/sanity/.gitignore | 3 + packages/sanity/package.json | 2 + packages/sanity/package.worker.ts | 32 + .../src/_internal/cli/server/getViteConfig.ts | 3 + .../list/CommentsListItemLayout.tsx | 19 +- .../components/pte/comment-input/Editable.tsx | 21 +- .../reactions/CommentReactionsMenuButton.tsx | 16 +- .../plugin/field/CommentsFieldButton.tsx | 17 +- .../components/FloatingButtonPopover.tsx | 10 +- .../components/InlineCommentInputPopover.tsx | 27 +- .../plugin/inspector/CommentsInspector.tsx | 8 +- .../commandList/__workshop__/PopoverStory.tsx | 16 +- .../hookCollection/GetHookCollectionState.tsx | 109 - .../hookCollection/HookCollection.tsx | 157 + .../hookCollection/HookStateContainer.ts | 43 - .../core/components/hookCollection/index.ts | 2 +- .../core/field/diff/components/ChangeList.tsx | 15 +- .../field/diff/components/FieldChange.tsx | 13 +- .../field/diff/components/GroupChange.tsx | 11 +- .../diff/components/Annotation.tsx | 20 +- .../diff/components/InlineObject.tsx | 8 +- .../formField/FormFieldBaseHeader.tsx | 34 +- .../__tests__/useOnClickOutside.test.tsx | 7 +- .../src/core/form/hooks/useOnClickOutside.ts | 28 - .../CrossDatasetReferenceInput.tsx | 11 +- .../utils/useOnClickOutside.ts | 22 - .../inputs/DateInputs/base/DateTimeInput.tsx | 9 +- .../form/inputs/PortableText/toolbar/hooks.ts | 61 +- .../inputs/ReferenceInput/ReferenceInput.tsx | 19 +- .../Grid/IncompatibleItemType.tsx | 11 +- .../ArrayOfObjectsInput/InsertMenuPopover.tsx | 12 +- .../List/IncompatibleItemType.tsx | 11 +- .../files/FileInput/FileActionsMenu.tsx | 25 +- .../files/ImageInput/ImageActionsMenu.tsx | 13 +- .../members/array/IncompatibleItemType.tsx | 11 +- .../members/object/fields/PrimitiveField.tsx | 29 +- .../src/core/form/studio/FormProvider.tsx | 2 +- .../TreeEditingBreadcrumbsMenuButton.tsx | 26 +- .../core/hooks/useUserListWithPermissions.ts | 25 +- .../overlay/RegionsWithIntersections.tsx | 13 +- .../core/presence/overlay/StickyOverlay.tsx | 2 +- .../src/core/preview/documentPreviewStore.ts | 8 - .../sanity/src/core/preview/observeFields.ts | 17 +- .../dateInputs/base/DateTimeInput.tsx | 9 +- .../buffered-doc/createBufferedDocument.ts | 2 + .../createObservableBufferedDocument.ts | 1 + .../document/document-pair/checkoutPair.ts | 2 + .../document-pair/checkoutPairWithWorker.ts | 214 + .../document-pair/checkoutPairWorker.ts | 147 + .../document/document-pair/documentEvents.ts | 1 + .../document/document-pair/memoizedPair.ts | 2 +- .../document-pair/operations/helpers.ts | 1 + .../document/document-pair/remoteSnapshots.ts | 1 + .../document/document-pair/snapshotPair.ts | 1 + .../store/_legacy/document/document-store.ts | 7 +- .../store/_legacy/document/getPairListener.ts | 5 +- .../core/store/_legacy/grants/grantsStore.ts | 1 + .../_legacy/presence/useGlobalPresence.tsx | 20 +- .../navbar/new-document/NewDocumentButton.tsx | 31 +- .../search/components/SearchPopover.tsx | 17 +- .../filters/addFilter/AddFilterButton.tsx | 8 +- .../documentTypes/DocumentTypesButton.tsx | 8 +- .../filters/filter/FilterButton.tsx | 8 +- .../filters/filter/inputs/asset/Asset.tsx | 9 +- .../definitions/operators/assetOperators.ts | 10 +- .../operators/referenceOperators.ts | 6 +- .../form/fields/DateEditFormField.tsx | 9 +- .../form/tasksFormBuilder/FormCreate.tsx | 57 +- .../src/core/tasks/hooks/useActivityLog.ts | 11 +- .../RenderActionCollectionState.tsx | 11 +- .../components/RenderBadgeCollectionState.tsx | 9 +- .../panes/document/DocumentPaneProvider.tsx | 2 + .../document-layout/DocumentLayout.tsx | 9 +- .../document/documentPanel/DocumentPanel.tsx | 9 +- .../documentPanel/documentViews/FormView.tsx | 18 - .../header/DocumentPanelHeader.tsx | 72 +- .../DocumentActionShortcuts.tsx | 30 +- .../document/statusBar/DocumentBadges.tsx | 7 +- .../statusBar/DocumentStatusBarActions.tsx | 49 +- .../statusBar/dialogs/ConfirmDialog.tsx | 17 +- .../statusBar/dialogs/PopoverDialog.tsx | 17 +- .../panes/document/timeline/timelineMenu.tsx | 29 +- .../documentList/DocumentListPaneContent.tsx | 8 +- .../panes/userComponent/UserComponentPane.tsx | 1 + packages/sanity/turbo.json | 5 + packages/sanity/web-workers/checkoutPair.mjs | 11460 ++++++++++++++++ pnpm-lock.yaml | 609 +- turbo.json | 8 +- 98 files changed, 13395 insertions(+), 1011 deletions(-) create mode 100644 dev/test-studio/components/debugStyledComponents.tsx create mode 100644 packages/sanity/package.worker.ts delete mode 100644 packages/sanity/src/core/components/hookCollection/GetHookCollectionState.tsx create mode 100644 packages/sanity/src/core/components/hookCollection/HookCollection.tsx delete mode 100644 packages/sanity/src/core/components/hookCollection/HookStateContainer.ts delete mode 100644 packages/sanity/src/core/form/hooks/useOnClickOutside.ts delete mode 100644 packages/sanity/src/core/form/inputs/CrossDatasetReferenceInput/utils/useOnClickOutside.ts create mode 100644 packages/sanity/src/core/store/_legacy/document/document-pair/checkoutPairWithWorker.ts create mode 100644 packages/sanity/src/core/store/_legacy/document/document-pair/checkoutPairWorker.ts create mode 100644 packages/sanity/web-workers/checkoutPair.mjs diff --git a/dev/test-next-studio/next.config.mjs b/dev/test-next-studio/next.config.mjs index 9c8bd47ff68d..63a3da94ae97 100644 --- a/dev/test-next-studio/next.config.mjs +++ b/dev/test-next-studio/next.config.mjs @@ -77,9 +77,11 @@ const config = { }, // Makes it much easier to see which component got memoized by the react compiler // when testing on https://test-next-studio.sanity.build - productionBrowserSourceMaps: true, + productionBrowserSourceMaps: process.env.REACT_COMPILER !== 'true', + // Only enable the react profiler when the compiler is disabled, to better use native browser profiling without the react profiler overhead + reactProductionProfiling: process.env.REACT_COMPILER !== 'true', experimental: { - reactCompiler: process.env.REACT_COMPILER === 'true' ? true : false, + reactCompiler: process.env.REACT_COMPILER === 'true', turbo: { resolveAlias: { '@sanity/block-tools': '@sanity/block-tools/src/index.ts', diff --git a/dev/test-studio/components/debugStyledComponents.tsx b/dev/test-studio/components/debugStyledComponents.tsx new file mode 100644 index 000000000000..985fea467328 --- /dev/null +++ b/dev/test-studio/components/debugStyledComponents.tsx @@ -0,0 +1,421 @@ +import {Button, Card, Flex, Text} from '@sanity/ui' +import { + // useCallback, + useEffect, + // useRef, + useState, + // useSyncExternalStore, +} from 'react' +import {definePlugin, type LayoutProps} from 'sanity' +import {__PRIVATE__, StyleSheetManager} from 'styled-components' + +const IS_BROWSER = typeof window !== 'undefined' && 'HTMLElement' in window + +export const debugStyledComponents = definePlugin({ + name: 'debug-styled-components', + studio: { + components: { + layout: DebugLayout, + }, + }, +}) + +const DEFAULT_OPTIONS = { + // Reconstruct default options + // https://github.com/styled-components/styled-components/blob/770d1fa2bc1a4bfe3eea1b14a0357671ba9407a4/packages/styled-components/src/sheet/Sheet.ts#L23-L26 + isServer: !IS_BROWSER, + useCSSOMInjection: true, +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars +function DebugLayout(props: LayoutProps) { + const {renderDefault} = props + const [showToolbar, setShowToolbar] = useState(true) + const [[profiling, sheet], setState] = useState(() => [false, new StyleSheet(DEFAULT_OPTIONS)]) + const [paused, setPaused] = useState>(false) + // const [profiling, setProfiling] = useState(false) + // const [, setTick] = useState(1) + // const [onStoreChange, setOnStoreChange] = useState(() => () => {}) + // const onBufferRef = useRef(onStoreChange) + // useEffect(() => { + // onBufferRef.current = onStoreChange + // }, [onStoreChange]) + // const [blazingSheet] = useState( + // () => + // new BlazingStyleSheet({ + // // Schedule state updates when the buffer is queued + // onBuffer: () => { + // // console.log('onBuffer') + // setTick((prev) => prev + 1) + // }, + // // onBuffer: () => onBufferRef.current(), + // // Reconstruct default options + // // https://github.com/styled-components/styled-components/blob/770d1fa2bc1a4bfe3eea1b14a0357671ba9407a4/packages/styled-components/src/sheet/Sheet.ts#L23-L26 + // isServer: !IS_BROWSER, + // useCSSOMInjection: true, + // }), + // ) + // const shouldFlush = useSyncExternalStore( + // useCallback((_onStoreChange) => { + // setOnStoreChange(() => _onStoreChange) + // return () => setOnStoreChange(() => () => {}) + // }, []), + // () => blazingSheet.shouldFlush(), + // () => true, + // ) + // const [enabled, setEnabled] = useState(true) + // const [flush, setFlush] = useState(true) + // const [namespace, setNamespace] = useState() + // const [disableCSSOMInjection, setDisableCSSOMInjection] = useState() + // const [enableVendorPrefixes, setEnableVendorPrefixes] = useState() + + // useEffect(() => { + // // @ts-expect-error -- debug global + // window.cody = { + // setNamespace, + // setDisableCSSOMInjection, + // setEnableVendorPrefixes, + // setEnabled, + // toggle: () => setFlush((prev) => !prev), + // } + // return () => { + // // @ts-expect-error -- debug global + // delete window.cody + // } + // }, []) + + // useEffect(() => { + // console.log({ + // blazingSheet, + // namespace, + // disableCSSOMInjection, + // enableVendorPrefixes, + // enabled, + // // shouldFlush, + // }) + // }, [blazingSheet, disableCSSOMInjection, enableVendorPrefixes, enabled, namespace]) + + // Pause event emitter during render: + // https://github.com/final-form/react-final-form/issues/751#issuecomment-689431448 + // blazingSheet.pauseEvents() + + // Update CSSOM + // useInsertionEffect(() => { + // if (flush) { + // blazingSheet.flush() + // } + // }) + + // Check if CSSOM should update + // @TODO rewrite to use useState to buffer up changes that should flush + // useEffect(() => { + // if (flush) { + // if (blazingSheet.shouldFlush()) { + // // console.log('Flush in side-effect!') + // setTick((prev) => prev + 1) + // } + // blazingSheet.resumeEvents() + // } + // }) + + useEffect(() => { + if (!showToolbar) return undefined + // @ts-expect-error -- this is just debug stuff + delete window.__openDebugToolbar + return () => { + // @ts-expect-error -- this is just debug stuff + window.__openDebugToolbar = () => { + setShowToolbar(true) + } + // eslint-disable-next-line no-console + console.log( + 'You can re-open the toolbar by calling `window.__openDebugToolbar()` in your console', + ) + } + }, [showToolbar]) + + const children = renderDefault(props) + + return ( + <> + {showToolbar && ( + + + + Debug Styled Components CSS rendering + +