-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Fixed component rerendering if there's only one renderer (framework components) #12131
base: next
Are you sure you want to change the base?
Fixed component rerendering if there's only one renderer (framework components) #12131
Conversation
|
993f55b
to
d9fba90
Compare
// If there's only one renderer in the project (solid-js) | ||
// we can skip the `check` calls and use that renderer (to not render solid component twice) | ||
if (renderers.length === 1 && renderers[0].name === '@astrojs/solid') { | ||
renderer = renderers[0]; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the only change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, accidentally approved.
break; | ||
// If there's only one renderer in the project (solid-js) | ||
// we can skip the `check` calls and use that renderer (to not render solid component twice) | ||
if (renderers.length === 1 && renderers[0].name === '@astrojs/solid') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why only Solid.js?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because for some reason the tests fail for other frameworks. Moreover for solid it's critical to be rendered once, because solid doesn't have this "rerender" paradigm as react, preact or others.
More common solution could require much more efforts, so it should be carefully implemented. This is really easy fix which can help many people (because solid-start it's not that production-ready yet, so many people use astro+solid to get SSR), so we can do improvements step by step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to apply the solution suggested here, but looks like it doesn't work anymore for all the frameworks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What tests fail? It's likely something we can fix. I don't think we should special-case one particular renderer in this case. There's nothing about this suggestion that shouldn't work everywhere.
If you could post the errors that occur when this is enabled for all renderers that would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would appreciate if you help to understand why the tests are failing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pushed a commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, will take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe here we need to check not renderers
but validRenderers
? I see that there can be a renderer with astro:jsx
name, maybe this is the point...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the problem is that some renderers (Preact in particular), expect both check
and renderToStaticMarkup
to be called because they store state in check
. We can probably make it a breaking change in 5.0 that check
is not guaranteed to always be called.
Easy fix though, pushed a change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well there must be another issue too, will look into that.
@@ -132,6 +132,9 @@ async function renderFrameworkComponent( | |||
// we can skip the `check` calls and use that renderer | |||
if (renderers.length === 1) { | |||
renderer = renderers[0]; | |||
|
|||
// Still call `check` because some renderers store state during the check phase that they expect when `renderToStaticMarkup` is called. | |||
await renderer.ssr.check.call({ result }, Component, props, children) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do this you render solid-js component twice (but that was the case we want to fix), so... you can just remove this if
statement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess, it's possible to extend renderer
interface with boolean flag shouldRun
in order to explicitly say that this renderer should be called because it has some state which depends on the initial call?
You discovered that:
some renderers (Preact in particular), expect both check and renderToStaticMarkup to be called because they store state in check
Looks like it's not really obvious from the renderer interface, so that's why I suggest to extend it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it's a bit strange that function check
(which should be pure) has some store in it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to resubmit against next
we could make this a breaking change that check
is not guaranteed to run. In that case it would be on the renderer to not rely on it running. We'd also need to update Preact to account for that, I could do that part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by "resubmit" against next
? next
is a function which is called inside check
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elite174 sorry for not explaining. We can't change the expectation that both check
and renderToStaticMarkup
both get called in 4.x. We already know it breaks out built-in renderers. That means it might also break external renderers.
We can make that a breaking change in 5.0 though, which is currently in beta. We are using the next
branch for 5.0. If this PR was for 5.0 we could make this a breaking change, update the Preact renderer, document the change, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes, that would be awesome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just rebased the PR
And removed check
call if there's only one renderer.
Any news about this one? Will it be added to 5.0? |
The tests aren't fixed yet. From what I understand above, Matthew will look into it, but might be a bit tight to take a look. Personally I don't know if this is the right fix. Once you add another renderer, like MDX or Svelte, you'd get the double rendering behaviour again. It's patching things and makes the DX unpredictable. It's also risky that if you used a component but forgot to add the integration or renderer, you'd get a cryptic error about rendering issues, rather than "couldn't find matching renderer for this component" type of errors. (I guess the test fails could be related to this) |
It doesn't fix the situation with multiple renderers, however this easy fix helps if there's only one. Looks like to fix this problem it should be done more work, so I suggest doing it at least step by step. |
I don't think it helps if there's no plan for the next steps, it'll only add upon the technical debt that we have to maintain. This easy fix is also going to impact DX as I mentioned above and isn't as harmless as it seems. |
Yeah, but... there's already a tech debt. And this debt is a bug. It should be fixed anyways. |
Changes
In this PR multiple server rerendering of the solid component is skipped if there's only one renderer in the project (solid-js).
I used only part of the solution for this issue.
If there're multiple rerenders, it should be processed in another way I suppose, but this little change can help if there's only one solid-js renderer.
Testing
Test was also added.
Docs
No need to update docs