Skip to content

Commit

Permalink
feat: use react-compiler to optimise render
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Oct 30, 2024
1 parent f6762dc commit 9fa3ad0
Show file tree
Hide file tree
Showing 20 changed files with 818 additions and 87 deletions.
18 changes: 18 additions & 0 deletions .github/eslint-compact.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"problemMatcher": [
{
"owner": "eslint-compact",
"pattern": [
{
"regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)\\.?$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5,
"code": 6
}
]
}
]
}
55 changes: 55 additions & 0 deletions .github/workflows/check-react-compiler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: check-react-compiler

on:
# Build on pushes branches that have a PR (including drafts)
pull_request:
# Build on commits pushed to branches without a PR if it's in the allowlist
push:
branches: [main]

jobs:
check-lint:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install
with:
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Cache node modules
id: cache-node-modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
v1-${{ runner.os }}-pnpm-store-${{ env.cache-name }}-
v1-${{ runner.os }}-pnpm-store-
v1-${{ runner.os }}-
- name: Install project dependencies
run: pnpm install

- name: Register Problem Matcher for ESLint that handles -f compact and shows warnings inline on PRs
run: echo "::add-matcher::.github/eslint-compact.json"

- name: Check react compiler on editor
working-directory: packages/editor
run: pnpm check:react-compiler -f compact

- name: Check react compiler on playground
working-directory: apps/playground
run: pnpm check:react-compiler -f compact
1 change: 1 addition & 0 deletions apps/playground/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.eslintcache
8 changes: 8 additions & 0 deletions apps/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"build": "tsc -b && vite build",
"check:lint": "biome lint .",
"check:types": "tsc --noEmit --pretty",
"check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --plugin react-hooks --rule 'react-compiler/react-compiler: [warn]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
"clean": "del .turbo && del dist && del node_modules",
"dev": "vite",
"lint:fix": "biome lint --write .",
Expand All @@ -23,6 +24,7 @@
"prettier": "^3.3.2",
"react": "^18.3.1",
"react-aria-components": "^1.2.1",
"react-compiler-runtime": "19.0.0-beta-6fc168f-20241025",
"react-dom": "^18.3.1",
"react-is": "^18.3.1",
"remeda": "^2.2.2",
Expand All @@ -40,8 +42,14 @@
"@types/react-dom": "^18.3.1",
"@types/react-is": "^18.3.0",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.12.2",
"@typescript-eslint/parser": "^8.12.2",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"babel-plugin-react-compiler": "beta",
"eslint": "8",
"eslint-plugin-react-compiler": "beta",
"eslint-plugin-react-hooks": "^5.0.0",
"postcss": "^8.4.47",
"tailwind-merge": "^2.5.4",
"tailwind-variants": "^0.2.1",
Expand Down
6 changes: 5 additions & 1 deletion apps/playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ import {defineConfig} from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
plugins: [
react({
babel: {plugins: [['babel-plugin-react-compiler', {target: '18'}]]},
}),
],
})
1 change: 1 addition & 0 deletions packages/editor/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
# Compiled code
/lib
/dist
.eslintcache
6 changes: 5 additions & 1 deletion packages/editor/e2e-tests/web-server/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import {defineConfig} from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [viteReact()],
plugins: [
viteReact({
babel: {plugins: [['babel-plugin-react-compiler', {target: '18'}]]},
}),
],
build: {
minify: false,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/editor/package.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ export default defineConfig({
noImplicitBrowsersList: 'off',
noImplicitSideEffects: 'error',
},
babel: {reactCompiler: true},
reactCompilerOptions: {target: '18'},
})
10 changes: 9 additions & 1 deletion packages/editor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@portabletext/editor",
"version": "1.1.11",
"version": "1.1.12-canary.0",
"description": "Portable Text Editor made in React",
"keywords": [
"sanity",
Expand Down Expand Up @@ -45,6 +45,7 @@
"build": "pkg-utils build --strict --check --clean",
"check:lint": "biome lint .",
"check:types": "tsc",
"check:react-compiler": "eslint --cache --no-inline-config --no-eslintrc --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --plugin react-hooks --rule 'react-compiler/react-compiler: [warn]' --rule 'react-hooks/rules-of-hooks: [error]' --rule 'react-hooks/exhaustive-deps: [error]' src",
"clean": "del .turbo && del lib && del node_modules",
"dev": "pkg-utils watch",
"lint:fix": "biome lint --write .",
Expand All @@ -59,6 +60,7 @@
"debug": "^4.3.4",
"is-hotkey-esm": "^1.0.0",
"lodash": "^4.17.21",
"react-compiler-runtime": "19.0.0-beta-6fc168f-20241025",
"slate": "0.110.2",
"slate-react": "0.110.3",
"xstate": "^5.18.2"
Expand Down Expand Up @@ -91,10 +93,16 @@
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/ws": "~8.5.12",
"@typescript-eslint/eslint-plugin": "^8.12.2",
"@typescript-eslint/parser": "^8.12.2",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/browser": "^2.1.4",
"@xstate/react": "^4.1.3",
"babel-plugin-react-compiler": "beta",
"dotenv": "^16.4.5",
"eslint": "8",
"eslint-plugin-react-compiler": "beta",
"eslint-plugin-react-hooks": "^5.0.0",
"express": "^4.21.1",
"express-ws": "^5.0.2",
"jest": "^29.7.0",
Expand Down
14 changes: 11 additions & 3 deletions packages/editor/src/editor/Editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ export const PortableTextEditable = forwardRef<
return lProps.children
},
[
editorActor,
readOnly,
renderAnnotation,
renderChild,
Expand Down Expand Up @@ -285,7 +286,7 @@ export const PortableTextEditable = forwardRef<
}
}
}
}, [editorActor, propsSelection, slateEditor])
}, [editorActor, blockTypeName, propsSelection, slateEditor])

const syncRangeDecorations = useCallback(
(operation?: Operation) => {
Expand Down Expand Up @@ -346,7 +347,13 @@ export const PortableTextEditable = forwardRef<
setRangeDecorationsState([])
}
},
[portableTextEditor, rangeDecorations, schemaTypes, slateEditor],
[
portableTextEditor,
rangeDecorations,
rangeDecorationState.length,
schemaTypes,
slateEditor,
],
)

// Restore selection from props when the editor has been initialized properly with it's value
Expand Down Expand Up @@ -477,7 +484,7 @@ export const PortableTextEditable = forwardRef<
})
}
},
[onPaste, portableTextEditor, schemaTypes, slateEditor],
[editorActor, onPaste, portableTextEditor, schemaTypes, slateEditor],
)

const handleOnFocus: FocusEventHandler<HTMLDivElement> = useCallback(
Expand Down Expand Up @@ -745,3 +752,4 @@ export const PortableTextEditable = forwardRef<
/>
)
})
PortableTextEditable.displayName = 'ForwardRef(PortableTextEditable)'
1 change: 1 addition & 0 deletions packages/editor/src/editor/PortableTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type PortableTextEditorProps = PropsWithChildren<{
* @public
*/
export class PortableTextEditor extends Component<PortableTextEditorProps> {
public static displayName = 'PortableTextEditor'
/**
* An observable of all the editor changes.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/editor/src/editor/components/DraggableBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,5 @@ export const DraggableBlock = ({
</div>
)
}

DraggableBlock.displayName = 'DraggableBlock'
2 changes: 2 additions & 0 deletions packages/editor/src/editor/components/Element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,5 @@ export const Element: FunctionComponent<ElementProps> = ({
</div>
)
}

Element.displayName = 'Element'
3 changes: 3 additions & 0 deletions packages/editor/src/editor/components/Leaf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ export const Leaf = (props: LeafProps) => {
onSelection.unsubscribe()
}
}, [
editorActor,
path,
portableTextEditor,
setSelectedFromRange,
Expand Down Expand Up @@ -329,3 +330,5 @@ export const Leaf = (props: LeafProps) => {
[leaf, attributes, content],
)
}

Leaf.displayName = 'Leaf'
10 changes: 9 additions & 1 deletion packages/editor/src/editor/components/SlateContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ export function SlateContainer(props: SlateContainerProps) {
portableTextEditor,
readOnly,
})
}, [portableTextEditor, maxBlocks, readOnly, patches$, slateEditor])
}, [
editorActor,
portableTextEditor,
maxBlocks,
readOnly,
patches$,
slateEditor,
])

const initialValue = useMemo(() => {
return [slateEditor.pteCreateTextBlock({decorators: []})]
Expand All @@ -79,3 +86,4 @@ export function SlateContainer(props: SlateContainerProps) {
</Slate>
)
}
SlateContainer.displayName = 'SlateContainer'
33 changes: 17 additions & 16 deletions packages/editor/src/editor/components/Synchronizer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {Patch} from '@portabletext/patches'
import type {PortableTextBlock} from '@sanity/types'
import {throttle} from 'lodash'
import {useCallback, useEffect, useMemo, useRef} from 'react'
import {useCallback, useEffect, useRef} from 'react'
import {Editor} from 'slate'
import {useSlate} from 'slate-react'
import type {EditorChange} from '../../types/editor'
Expand Down Expand Up @@ -68,8 +68,18 @@ export function Synchronizer(props: SynchronizerProps) {
IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, false)
}, [editorActor, slateEditor, getValue])

const onFlushPendingPatchesThrottled = useMemo(() => {
return throttle(
// Flush pending patches immediately on unmount
useEffect(() => {
return () => {
onFlushPendingPatches()
}
}, [onFlushPendingPatches])

// Subscribe to, and handle changes from the editor
useEffect(() => {
debug('Subscribing to editor changes')

const onFlushPendingPatchesThrottled = throttle(
() => {
// If the editor is normalizing (each operation) it means that it's not in the middle of a bigger transform,
// and we can flush these changes immediately.
Expand All @@ -86,18 +96,7 @@ export function Synchronizer(props: SynchronizerProps) {
trailing: true,
},
)
}, [onFlushPendingPatches, slateEditor])

// Flush pending patches immediately on unmount
useEffect(() => {
return () => {
onFlushPendingPatches()
}
}, [onFlushPendingPatches])

// Subscribe to, and handle changes from the editor
useEffect(() => {
debug('Subscribing to editor changes')
const sub = editorActor.on('*', (event) => {
switch (event.type) {
case 'patch':
Expand Down Expand Up @@ -149,7 +148,7 @@ export function Synchronizer(props: SynchronizerProps) {
debug('Unsubscribing to changes')
sub.unsubscribe()
}
}, [editorActor, onFlushPendingPatchesThrottled, slateEditor])
}, [editorActor, onChange, onFlushPendingPatches, slateEditor])

// Sync the value when going online
const handleOnline = useCallback(() => {
Expand All @@ -168,7 +167,7 @@ export function Synchronizer(props: SynchronizerProps) {
return () => {
subscription.unsubscribe()
}
}, [editorActor])
}, [editorActor, handleOnline, portableTextEditor.props.patches$])

// This hook must be set up after setting up the subscription above, or it will not pick up validation errors from the useSyncValue hook.
// This will cause the editor to not be able to signal a validation error and offer invalid value resolution of the initial value.
Expand All @@ -185,3 +184,5 @@ export function Synchronizer(props: SynchronizerProps) {

return null
}

Synchronizer.displayName = 'Synchronizer'
2 changes: 2 additions & 0 deletions packages/editor/src/editor/nodes/DefaultAnnotation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export function DefaultAnnotation(props: Props) {
</span>
)
}

DefaultAnnotation.displayName = 'DefaultAnnotation'
2 changes: 2 additions & 0 deletions packages/editor/src/editor/nodes/DefaultObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ const DefaultObject = (props: Props): JSX.Element => {
)
}

DefaultObject.displayName = 'DefaultObject'

export default DefaultObject
Loading

0 comments on commit 9fa3ad0

Please sign in to comment.