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

Support shared signals in Preact islands #4763

Merged
merged 5 commits into from Sep 21, 2022
Merged

Conversation

matthewp
Copy link
Contributor

Changes

  • This makes it possible to share state between Preact components rendered to islands. Signals can be created in your Astro componnents and passed to islands. They will be serialized to HTML and in the client recreated as shared signals.

Testing

  • Test added. Key thing about this test is checking that the keys made for the signals are the same between the islands.

Docs

N/A

@changeset-bot
Copy link

changeset-bot bot commented Sep 14, 2022

🦋 Changeset detected

Latest commit: 8ecb0bc

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

This PR includes changesets to release 17 packages
Name Type
@astrojs/preact Minor
astro Patch
@e2e/error-cyclic Patch
@e2e/errors Patch
@e2e/hydration-race Patch
@e2e/preact-component Patch
@e2e/astro-component Patch
@e2e/error-react-spectrum Patch
@e2e/error-sass Patch
@e2e/lit-component Patch
@e2e/react-component Patch
@e2e/solid-component Patch
@e2e/solid-recurse Patch
@e2e/svelte-component Patch
@e2e/e2e-tailwindcss Patch
@e2e/ts-resolution Patch
@e2e/third-party-astro Patch

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

@github-actions github-actions bot added pkg: astro Related to the core `astro` package (scope) pkg: example Related to an example package (scope) pkg: preact Related to Preact (scope) pkg: integration Related to any renderer integration (scope) labels Sep 14, 2022
@@ -35,7 +35,8 @@
"@babel/core": ">=7.0.0-0 <8.0.0",
"@babel/plugin-transform-react-jsx": "^7.17.12",
"babel-plugin-module-resolver": "^4.1.0",
"preact-render-to-string": "^5.2.0"
"preact-render-to-string": "^5.2.0",
"@preact/signals": "1.0.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a dep and not a peerDep so that it doesn't require users to use preact/signals.

Copy link
Member

@natemoo-re natemoo-re left a comment

Choose a reason for hiding this comment

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

Interesting! Looks really cool, would love to think about this a bit more before pulling the trigger.

Do you know if anyone from the Preact team might want to vet this as well?

@matthewp
Copy link
Contributor Author

Sure, can pull some people in, what specific questions would you ask of them? Whether this is a good idea or something about implementation?

@matthewp matthewp added the semver: minor Change triggers a `minor` release label Sep 16, 2022
Copy link
Member

@natemoo-re natemoo-re left a comment

Choose a reason for hiding this comment

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

I thought about it and I'm convinced this is a great idea! Could be super useful. Definitely fine with getting this out and we can circle back if the Preact team has any feedback.

@matthewp
Copy link
Contributor Author

I'm not trying to rush this out or anything, happy to wait on it for a while to gather feedback.

I'll ping @marvinhagemeister and @developit to see if they have any thoughts on the design.

Basically the idea is to create signals in Astro components and then pass them into islands. On the client we recreate that by creating an id for each signal and then ensure that all islands get the same value.

  • Does this seem like a reasonable way to share state between Preact islands?
  • Any thoughts on the design? We are using signal.peek() to serialize the value into HTML and then using the signal in a WeakMap to generate a distinct id per signal to recreate in the client.
  • We have @preact/signals as a regular dependency. I was unsure if this was the right call. Putting it as a peerDependency would require everyone to use signals, which seemed wrong.

@@ -1,3 +1,4 @@
// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Q: Was the preact/debug import erroring? If we're lacking type definitions we can easily PR that to preact.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, preact/debug doesn't have types at the moment: https://unpkg.com/browse/preact@10.11.0/debug/

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh no, filed a PR. Next version will have typings for that: preactjs/preact#3732

@marvinhagemeister
Copy link
Contributor

Basically the idea is to create signals in Astro components and then pass them into islands. On the client we recreate that by creating an id for each signal and then ensure that all islands get the same value.

Does this seem like a reasonable way to share state between Preact islands?

Yup, that's one of the exact use cases they were designed for. Since they're not bound to components it makes perfect sense to instantiate them outside of that and pass the signals to the islands directly.

Any thoughts on the design? We are using signal.peek() to serialize the value into HTML and then using the signal in a WeakMap to generate a distinct id per signal to recreate in the client.

Sounds good! You can hardly go wrong with the serialization approach. The little more tricky bit is probably restoring the state graph on the client. It's something we had in mind when building signals, but didn't have the time to explore yet. That said it should be rather straightforward for as long as you can identify each signal.

We have @preact/signals as a regular dependency. I was unsure if this was the right call. Putting it as a peerDependency would require everyone to use signals, which seemed wrong.

Good point. I think you made the best choice for Astro. Much easier when folks don't have to worry about peerDependencies.

Really excited about the things you're doing here! That's awesome stuff 👍

@matthewp matthewp merged commit 5e46be5 into main Sep 21, 2022
@matthewp matthewp deleted the preact-shared-signals2 branch September 21, 2022 19:21
@astrobot-houston astrobot-houston mentioned this pull request Sep 21, 2022
matthewp added a commit that referenced this pull request Sep 22, 2022
matthewp added a commit that referenced this pull request Sep 22, 2022
* Revert "Update preact example to match @astrojs/preact ranges (#4840)"

This reverts commit d650a11.

* Revert "[ci] format"

This reverts commit e3c78c5.

* Revert "Support shared signals in Preact islands (#4763)"

This reverts commit 5e46be5.
@matthewp
Copy link
Contributor Author

@marvinhagemeister we had to revert this for the time being due to preactjs/signals#197. Will release this another day though.

@merlindru
Copy link

merlindru commented Sep 23, 2022

preactjs/signals#197 is fixed, could we get this back pretty please?! 😄

Thank you for your work on astro @matthewp!

@matthewp
Copy link
Contributor Author

Thanks for the reminder @merlindru, do you want to submit a PR that reverts #4843 and updates the library version? If not I'll get around to it eventually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope) pkg: example Related to an example package (scope) pkg: integration Related to any renderer integration (scope) pkg: preact Related to Preact (scope) semver: minor Change triggers a `minor` release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants