XantreDev / preact-signals

Preact Signals: Supercharge your React/Preact development! Unleash the power of reactive programming with hooks, components, a TanStack query adapter, and more. Code smarter, not harder
https://preact-signals.netlify.app/#/
MIT License
61 stars 0 forks source link

Next.js swc plugin not working for react hooks #184

Closed kitajchuk closed 1 week ago

kitajchuk commented 2 weeks ago

I originally posted a comment here. I'll try to explain in more detail what I'm experiencing here. I really appreciate community work so up front I just want to say thanks for working on this stuff ❤️.

Basic info:

My understanding is the swc plugin in the safe react package is intended to have parity with the preact signals team official babel plugin. I've tested both, however we use swc and have no desire to switch back to babel—even for a short period of time. In my testing the babel plugin nearly works perfectly. The swc plugin works far less. To note there are no actual errors—just really buggy signal behavior which I believe stems from the plugin not wrapping everything up properly. Worth noting that your swc plugin does the best for me when I use the all mode but is still not sufficient.

Currently all of our routes are still in the pages router since we cannot move anything over with this issue of the signals. For my use case here I'm looking at ~500ish typescript files in which I'd need to manually add useSignals to lacking a viable plugin to do it for me.

I've tested across 3 scenarios: the babel plugin, your swc plugin and manually adding useSignals to necessary areas. So far the pattern that absolutely works is the manual pattern—when I test an area of the application and then manually add useSignals to the right spots I get full functionality as expected. The babel plugin is nearly perfect as an automated pattern but there are a few areas I'd need to address manually. The swc plugin is insufficient enough as an automated pattern that it's not worth using right now I don't think.

I am not sure exactly what differs between your swc plugin and the babel plugin but I definitely don't experience full parity in real world testing on a complex next application. A viable swc plugin is ideal at this stage so I'm just wondering if there's any possibility in debugging what is going wrong here 🤷‍♂️

XantreDev commented 2 weeks ago

Have you tried to use importSource option or use signals from @preact-signals/safe-react? Because, swc plugin imports it's own version of signals from @preact-signals/safe-react, not @preact/signals-react

kitajchuk commented 2 weeks ago

@XantreDev Alright I gave that a try and unfortunately, while it works to use that plugin option, I experience the exact same behavior with the buggy signals in the web app. So there is no difference in the runtime.

kitajchuk commented 2 weeks ago

My best guess would be that the plugin only addresses components, not hooks. We use signals a lot in custom hooks as well. Does that seem like it could be an underlying issue?

XantreDev commented 2 weeks ago

Yep. The plugin transforms only components. But if you use option 'all' every component will be transformed any way

XantreDev commented 2 weeks ago

I will try to implement hooks the transform, when I will have a free time. After this step my plugin can be moved to official repo

kitajchuk commented 2 weeks ago

Yep. The plugin transforms only components. But if you use option 'all' every component will be transformed any way

So the all mode seems slightly better with this swc plugin but still missing a lot (a la hooks).

kitajchuk commented 2 weeks ago

I will try to implement hooks the transform, when I will have a free time. After this step my plugin can be moved to official repo

Alright. It's a bit confusing because the official babel plugin doesn't clarify that it operates on hooks:

Fundamentally, this Babel transform needs to answer two questions in order to know whether to transform a function:

  1. Is a function a component?
  2. If so, does this component use signals?

Currently we use the following heuristics to answer these questions:

  1. A function is a component if it has a capitalized name (e.g. function MyComponent() {}) and contains JSX.
  2. If a function's body includes a member expression referencing .value (i.e. something.value), we assume it's a signal.

However when I use the babel plugin nearly all the signal usage appears to work which implies that it is maybe also operating on hooks as well as components 🤔. I suppose the 2nd heuristic implies they are looking at functions / components independently, though.

XantreDev commented 2 weeks ago

It seems like docs is obsolete. I've read the implementation, it also adds useSignals to hooks

XantreDev commented 2 weeks ago

You can check #187 version 0.7.0, it transforms hooks that reads signals as well

kitajchuk commented 2 weeks ago

Thanks I’ll check it out first thing next week!

kitajchuk commented 1 week ago

Alright so with the latest updates on version 0.7.0 this swc plugin seems to be working and viable for us to upgrade to @preact/signals-react major version 2. It didn't work with importSource set to @preact/signals-react/runtime but I noticed a comment in your PR that said that is still not supported. Not a big deal since it doesn't seem to be an issue by just using the default internal import for the plugin.

Thanks for tackling that update—really appreciate it!