Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raf aligned dom updates #604

Merged
merged 6 commits into from
Oct 8, 2024
Merged

Raf aligned dom updates #604

merged 6 commits into from
Oct 8, 2024

Conversation

JoviDeCroock
Copy link
Member

@JoviDeCroock JoviDeCroock commented Oct 3, 2024

This also converts our synchronous DOM updates to be animation-frame aligned, this will make them execute in parallel and when the browser is prepared for it.

Let's draw out the ideal scenario we want to create:

  • effects that end up in a setState get executed synchronously so these updates are immediately added in the render queue
  • signal-effects are deferred by an animation-frame
  • TextNodeUpdates are deferred by an animation-frame
  • AttributeNodeUpdates are deferred by an animation-frame

Now we can be sure that Preact updates take presedence over our normal DOM updates.

One thing I am unsure of is the following https://github.com/preactjs/signals/blob/main/packages/preact/src/index.ts#L92-L100 whether we can reliably make this also deferred as currently it's synchronous, we could just defer the s.data = s.peek() part? From the tests it looks to work as we expect with RAF though 😅

Fixes #315
Proof: https://codesandbox.io/p/sandbox/epic-wilbur-hhln8l

This could be considered a breaking change though 😅

Another thing to consider here would be the testing story, we could tie it into options.debounceRendering but that might lead to some odd behavior in terms of rendering. To align with how the user would see this behave it would need to execute Preact updates and then update the nodes directly.

In the latest version of this branch the above is fixed by leveraging options.requestAnimationFrame which now means that any signal update needs to be wrapped in act. In a way this was always the case as a signal update that resulted in a Preact state update would require it to be wrapped in act but now this is the norm.

Doing this investigation made me think about how we do useSignalEffect in React and maybe we should leverage the scheduler package rather than injecting an arbitrary animation frame as React would better work with its own scheduler.

@JoviDeCroock JoviDeCroock requested a review from developit October 3, 2024 07:19
Copy link

changeset-bot bot commented Oct 3, 2024

🦋 Changeset detected

Latest commit: 9804e9f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@preact/signals Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

netlify bot commented Oct 3, 2024

Deploy Preview for preact-signals-demo ready!

Name Link
🔨 Latest commit 9804e9f
🔍 Latest deploy log https://app.netlify.com/sites/preact-signals-demo/deploys/67042585dbf2410008b1c12a
😎 Deploy Preview https://deploy-preview-604--preact-signals-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

github-actions bot commented Oct 3, 2024

Size Change: -25 B (-0.03%)

Total Size: 83.3 kB

Filename Size Change
docs/dist/assets/bench.********.js 1.59 kB -3 B (-0.19%)
docs/dist/assets/index.********.js 835 B -3 B (-0.36%)
docs/dist/assets/signals-core.module.********.js 1.41 kB +19 B (+1.36%)
docs/dist/assets/signals.module.********.js 2.08 kB +62 B (+3.07%)
docs/dist/demos-********.js 3.44 kB -4 B (-0.12%)
docs/dist/nesting-********.js 1.13 kB +1 B (+0.09%)
docs/dist/react-********.js 243 B +1 B (+0.41%)
packages/preact/dist/signals.js 1.35 kB -42 B (-3.01%)
packages/preact/dist/signals.mjs 1.3 kB -56 B (-4.12%)
ℹ️ View Unchanged
Filename Size
docs/dist/assets/client.********.js 46.3 kB
docs/dist/assets/jsxRuntime.module.********.js 284 B
docs/dist/assets/preact.module.********.js 4.03 kB
docs/dist/assets/style.********.js 21 B
docs/dist/assets/style.********.css 1.24 kB
docs/dist/basic-********.js 243 B
packages/core/dist/signals-core.js 1.45 kB
packages/core/dist/signals-core.mjs 1.47 kB
packages/react-transform/dist/signals-*********.js 5.03 kB
packages/react-transform/dist/signals-transform.mjs 4.27 kB
packages/react-transform/dist/signals-transform.umd.js 5.15 kB
packages/react/dist/signals.js 188 B
packages/react/dist/signals.mjs 150 B

compressed-size-action

@JoviDeCroock JoviDeCroock force-pushed the raf-aligned-dom-updaters branch 8 times, most recently from 5692de5 to 8e85bdf Compare October 4, 2024 13:21
@JoviDeCroock JoviDeCroock marked this pull request as ready for review October 4, 2024 13:40
@JoviDeCroock JoviDeCroock force-pushed the raf-aligned-dom-updaters branch 6 times, most recently from a723274 to 3c4bd59 Compare October 5, 2024 07:49
Copy link
Member

@rschristian rschristian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

.changeset/ninety-beans-compare.md Outdated Show resolved Hide resolved
.changeset/ninety-beans-compare.md Outdated Show resolved Hide resolved
.changeset/ninety-beans-compare.md Outdated Show resolved Hide resolved
Copy link
Member

@marvinhagemeister marvinhagemeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! Only thought I have is if we should flag this update as "major" for the preact adapter or not. Because upgrading might break some tests.

@JoviDeCroock JoviDeCroock force-pushed the raf-aligned-dom-updaters branch 2 times, most recently from 33a3591 to dd992d4 Compare October 7, 2024 16:53
This all works fine, however it creates a discrepancy between
browser usage and test usage which we want to avoid. The discrepancy
is made clear in the failing tests.

What we want to happen is for Preact to be first allowed to perform
its render cycle, the effects that follow and only then should we
clean up stragglers by performing the direct DOM updates. Currently
what happens is that the ordering is "random" based on how the signals
were registered.
@JoviDeCroock JoviDeCroock force-pushed the raf-aligned-dom-updaters branch 6 times, most recently from 9d43b38 to ed0c3fd Compare October 7, 2024 18:15
@JoviDeCroock JoviDeCroock force-pushed the raf-aligned-dom-updaters branch from ed0c3fd to 9804e9f Compare October 7, 2024 18:16
@JoviDeCroock JoviDeCroock merged commit fea3e8d into main Oct 8, 2024
6 checks passed
@JoviDeCroock JoviDeCroock deleted the raf-aligned-dom-updaters branch October 8, 2024 07:09
@github-actions github-actions bot mentioned this pull request Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Timing issue with useComputed
3 participants