Skip to content

Commit fb87646

Browse files
authored
Experimental chunking optimisation and other performance improvements (#5871)
* Chunking optimization * Fix comments * Remove redundant `insertionsMinusRemovals` variable * Fix typo * Unblock Netlify builds * Add placeholder * Upgrade Playwright (fixes crash when debugging) * Fix `autoFocus` not working * Fix huge document test * Fix the previous issue without changing `useSlateSelector` * Retry `test:integration` * Re-implement `useSlateWithV` * Retry `test:integration` * Update docs * Update JS examples to match TS examples * Upload Playwright's `test-results` directory in CI to access traces * Change trace mode to `retain-on-first-failure` * Fix: `Locator.fill(text)` is flaky on Editable * Add changesets * Increase minimum `slate-dom` version * Update changeset * Update 09-performance.md * Deprecate the `useSlateWithV` hook * Fix errors and improve clarity in 09-performance.md * Minimum `slate-dom` version is now 0.116 * Update `yarn.lock`
1 parent 583d28f commit fb87646

65 files changed

Lines changed: 5223 additions & 865 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/chatty-flies-pay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'slate-dom': minor
3+
---
4+
5+
- Add `splitDecorationsByChild` to split an array of decorated ranges by child index.

.changeset/silly-crabs-sort.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'slate': patch
3+
---
4+
5+
- PERF: Use pure JS instead of Immer for applying operations and transforming points and ranges. Immer is now used only for producing fragments.

.changeset/tiny-scissors-yell.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'slate-react': minor
3+
---
4+
5+
- Implement experimental chunking optimization (disabled by default, see https://docs.slatejs.org/walkthroughs/09-performance).
6+
- Add `useElement` and `useElementIf` hooks to get the current element.
7+
- **BREAKING CHANGE:** Decorations are no longer recomputed when a node's parent re-renders, only when the node itself re-renders or when the `decorate` function is changed.
8+
- Ensure that `decorate` is a pure function of the node passed into it. Depending on the node's parent may result in decorations not being recomputed when you expect them to be.
9+
- If this change impacts you, consider changing your `decorate` function to work on the node's parent instead.
10+
- For example, if your `decorate` function decorates a `code-line` based on the parent `code-block`'s language, decorate the `code-block` instead.
11+
- This is unlikely to result in any performance detriment, since in previous versions of `slate-react`, the decorations of all siblings were recomputed when one sibling was modified.
12+
- Increase minimum `slate-dom` version to `0.116.0`.
13+
- Deprecate the `useSlateWithV` hook
14+
- PERF: Use subscribable pattern for `useSlate`, `useSelected` and decorations to reduce re-renders.

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,11 @@ jobs:
3434
run: yarn && yarn build && yarn ${{ matrix.command }}
3535
env:
3636
CI: true
37+
38+
- name: Upload Playwright test results
39+
if: ${{ !cancelled() && matrix.command == 'test:integration' }}
40+
uses: actions/upload-artifact@v4
41+
with:
42+
name: test-results
43+
path: test-results
44+
retention-days: 30

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ packages/*/yarn.lock
1010
site/out/
1111
tmp/
1212
test-results/
13+
coverage
1314
.DS_Store
1415

1516
# Recommendation from https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored (not using Zero-installs)

.yarn/sdks/integrations.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
# Manual changes might be lost!
33

44
integrations:
5+
- vim
56
- vscode

docs/Summary.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
- [Executing Commands](walkthroughs/05-executing-commands.md)
1212
- [Saving to a Database](walkthroughs/06-saving-to-a-database.md)
1313
- [Enabling Collaborative Editing](walkthroughs/07-enabling-collaborative-editing.md)
14-
- [Using the Bundled Source](walkthroughs/xx-using-the-bundled-source.md)
14+
- [Using the Bundled Source](walkthroughs/08-using-the-bundled-source.md)
15+
- [Improving Performance](walkthroughs/09-performance.md)
1516

1617
## Concepts
1718

docs/concepts/09-rendering.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,7 @@ It is also possible to apply custom styles with a stylesheet and `className`. Ho
192192
- Provide your styles using the `style` prop instead of a stylesheet, which overrides the default inline styles.
193193
- Pass the `disableDefaultStyles` prop to the `<Editable>` component.
194194
- Use `!important` in your stylesheet declarations to make them override the inline styles.
195+
196+
## Performance
197+
198+
See [Improving Performance](../walkthroughs/09-performance.md) for ways to improve the rendering performance of the editor.
633 KB
Loading

docs/libraries/slate-react/hooks.md

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# Slate React Hooks
22

3-
- [Check hooks](hooks.md#check-hooks)
4-
- [Editor hooks](hooks.md#editor-hooks)
5-
- [Selection hooks](hooks.md#selection-hooks)
6-
7-
### Check hooks
8-
9-
React hooks for Slate editors
10-
113
#### `useComposing(): boolean`
124

135
Get the current `composing` state of the editor. It deals with `compositionstart`, `compositionupdate`, `compositionend` events.
146

157
Composition events are triggered by typing (composing) with a language that uses a composition character (e.g. Chinese, Japanese, Korean, etc.) [example](https://en.wikipedia.org/wiki/Input_method#/media/File:Typing_%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4_in_Dubeolsik_keyboard_layout.gif).
168

9+
#### `useElement(): Element`
10+
11+
Get the current element object. Re-renders whenever the element or any of its descendants changes.
12+
13+
#### `useElementIf(): Element | null`
14+
15+
The same as `useElement()` but returns `null` instead of throwing an error when not inside an element.
16+
1717
#### `useFocused(): boolean`
1818

1919
Get the current `focused` state of the editor.
@@ -24,35 +24,27 @@ Get the current `readOnly` state of the editor.
2424

2525
#### `useSelected(): boolean`
2626

27-
Get the current `selected` state of an element.
28-
29-
### Editor hooks
27+
Get the current `selected` state of an element. An element is selected if `editor.selection` exists and overlaps any part of the element.
3028

3129
#### `useSlate(): Editor`
3230

33-
Get the current editor object from the React context. Re-renders the context whenever changes occur in the editor.
34-
35-
#### `useSlateWithV(): { editor: Editor, v: number }`
36-
37-
The same as `useSlate()` but includes a version counter which you can use to prevent re-renders.
31+
Get the current editor object. Re-renders whenever changes occur in the editor.
3832

3933
#### `useSlateStatic(): Editor`
4034

4135
Get the current editor object from the React context. A version of useSlate that does not re-render the context. Previously called `useEditor`.
4236

43-
### Selection hooks
44-
4537
#### `useSlateSelection(): (BaseRange & { placeholder?: string | undefined; onPlaceholderResize?: ((node: HTMLElement | null) => void) | undefined }) | null`
4638

47-
Get the current editor selection from the React context. Only re-renders when the selection changes.
39+
Get the current editor selection. Only re-renders when the selection changes.
4840

4941
#### `useSlateSelector<T>(selector: (editor: Editor) => T, equalityFn?: (a: T, b: T) => boolean): T`
5042

51-
Similar to `useSlateSelection` but uses redux style selectors to prevent rerendering on every keystroke.
43+
Use redux style selectors to prevent re-rendering on every keystroke.
5244

53-
Returns a subset of the full selection value based on the `selector`.
45+
Bear in mind re-rendering can only prevented if the returned value is a value type or for reference types (e.g. objects and arrays) add a custom equality function.
5446

55-
Bear in mind rerendering can only prevented if the returned value is a value type or for reference types (e.g. objects and arrays) add a custom equality function for the `equalityFn` argument.
47+
If `selector` is memoized using `useCallback`, then it will only be called when it or the editor state changes. Otherwise, `selector` will be called every time the component renders.
5648

5749
Example:
5850

0 commit comments

Comments
 (0)