-
Notifications
You must be signed in to change notification settings - Fork 398
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
[Idea] Disable read-only proxy in SSR v2 #5126
Comments
Keep me honest @nolanlawson, as far as I know, LWC is the only framework enforcing 1-way dataflow using guardrails. I haven't seen any issues related to read-only proxy since LWC's inception. Is it because developers never run into those issues or is it because the guardrails are effective, it's hard to say. IMO, the CPU and memory overhead aren't worth it in production. I would suggest only enabling it in dev mode. |
Looking at the client code, it appears that readonly membrane is applied in both dev and production. I was always under the assumption that this check was only enforced in dev mode only (code). @nolanlawson Is it possible to re-run the same test in the browser to determine what is the runtime overhead with |
@pmdartus This topic actually came up when we did a similar optimization for Basically:
|
Update on Vue: they claim to have one-way data flow, but they don't enforce this deeply. I managed to get a child to mutate its parent, same as in Svelte.
For the
... then you get about a 8-17% improvement in the We can certainly consider relaxing this for both client and server, given the potential perf gains. I'm concerned, though, that it would cause some backwards incompatibilities to do so. Code that was a no-op before now causes the child to mutate its parent's state. We could also make this an error/warning only in dev mode, but in my experience people ignore whatever we do in dev mode. Many LWC component authors only test in prod mode. |
I personally ran into this as a component author before I joined the LWC team, and I found I had to do |
You are right. This goes back to a larger conversation on how to make warnings more visible to developers. I made piece with the fact that developers don't know/care about console warnings in dev mode. |
SSR v2 (and v1, for that matter) makes use of
getReadOnlyProxy
fromobservable-membrane
to ensure that child components do not try to mutate their parent components' props.Note
Note this is not exactly how
engine-dom
works – in that world, a child trying to modify its parent's props ends up doing a no-op. (This is why component authors often doJSON.parse(JSON.stringify())
to clone their props.) The original intention was to avoid two-way data flow – e.g. a parent rendering<div>{props.foo}</div>
, whereprops.foo
could have been mutated by a child.In SSR, the read-only proxy is a nice guardrail. However, it comes with a fairly substantial perf cost: ~44% in one benchmark (PoC: ab3e2f9):
To be fair: there is less risk in SSR of a child truly mutating its parent, since rendering is one-time and top-down. There is still, however, potential for mischief if a child ends up modifying its siblings (e.g. because the parent passes in a prop and that prop is shared among siblings).
Thoughts:
process.env.NODE_ENV !== 'production'
?The downside of removing it entirely is that we would potentially be looser on the server than on the client. This could actually matter for SSR-only cases, where we don't have the extra validation of running components client-side (where children-mutating-parents is already disallowed). But maybe it's still worth it?
The text was updated successfully, but these errors were encountered: