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
[labs/nextjs, labs/ssr-react, lit/react] Add support for Next.js v14 and App Router #4575
Conversation
🦋 Changeset detectedLatest commit: f4bf397 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
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 |
📊 Tachometer Benchmark ResultsSummarynop-update
render
update
update-reflect
Resultsthis-change
render
update
update-reflect
this-change, tip-of-tree, previous-release
render
update
nop-update
this-change, tip-of-tree, previous-release
render
update
this-change, tip-of-tree, previous-release
render
update
update-reflect
|
The size of lit-html.js and lit-core.min.js are as expected. |
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.
Absolutely awesome work!
// https://github.com/facebook/react/blob/v18.2.0/packages/react/src/ReactElement.js#L401-L417 | ||
if (children.length > 0) { | ||
newChildren.push(...children); | ||
} else if (Array.isArray(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.
When is props.children
an Array that hasn't be handled by the .length > 0
check above?
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.
the params come like this
function createElement(type, props, ...children) {}
If children are provided as 3rd+ arguments, children.length > 0
is true and we use that.
Else, only 2 arguments were supplied, and there is a possibility that the 2nd arg props
contains a children
property that is meant to be the children. The value of that props.children
could either be an array or non-array ReactNode
if it's just a single item.
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.
lgtm!
- Use `collectResultSync()` - Add jsdoc to exported functions - `||` to `??` - Some doc wording changes
Fixes #4410 and #3657
Apologies for the big PR. It'll be easier to review commit by commit.
Explanation of changes:
re: f10d7ee
Next.js v14 had some changes to how it bundles its copy of React so how we were hijacking imports of
react/jsx-runtime
andreact/jsx-dev-runtime
with the Webpack module replacement were not working described here vercel/next.js#46470 (comment)Since React is still all CommonJS, I've resorted to monkey-patching everything including the runtime JSX functions. Also, a workaround in how we access the module to patch was added to handle seemingly inconsistent es module interop behavior in webpack, e.g.
(React.default || React).createElement = ...
. This addresses errors like seen here #3657 (comment)This has a nice benefit that all the hijacking/patching is possible with just a single import of
@lit-labs/ssr-react/enable-lit-ssr.js
which allows the@lit-labs/nextjs
plugin to be a lot simpler (see next commit). Users can also choose not to use the plugin and just add this one line import themselves. It should also make integration with other React meta-framework, namely Remix, easier (need to test this).I also added a small check to make sure we don't wrapThis doesn't seem to actually be a problem.createElement
and the jsx functions if they're already wrapped. This is mainly useful for when both@lit-labs/ssr-react/enable-lit-ssr.js
is installed, and the"jsxImportSource": "@lit-labs/ssr-react"
is set, as it happens in our integration test suite.These changes only affect
@lit-labs/ssr-react
package.re: 9702f91
With the changes above, the plugin can become a lot simpler. I've removed all the hacky webpack externals modification to replace
react/runtime-jsx
at the module level since we're just monkey-patching it globally now.I've updated the peer dependencies to now support
next@13
andnext@14
, and droppednext@12
. I debated whether we should keep v12 support, but the changes here mainly apply to next v13 and v14 for the app router support and I haven't tested these changes in v12 (and we likely won't be going forward, see commit about adding example projects below). Users of v12 can stick with the current published version.re: d5dcabb
While manually testing the Next v14 example, I noticed server rendering of
@lit/react
wrapped components had incorrect initial props for production builds. We had coordination between@lit/react
and@lit-labs/ssr-react
based on the patchedcreateElement
function name, but that name check was failing perhaps as it got lost during production build minification. (I noticed this a while back when I was testing out@lit-labs/ssr-react
in Remix too.)@lit-labs/ssr-react
will now add a global flag which@lit/react
node build will check for.re: 02a0c05
I renamed the existing
examples/nextjs
package tonextjs-v13
and addednextjs-v14
andnextjs-v14-app
examples.nextjs-v14
is basically a direct copy of the existing v13 example just with the next version bumped. It still uses the pages router.nextjs-v14-app
was modified further from there to use the app router directory structure, usinglayout.tsx
instead of_app.tsx
, as well as moving the custom element and wrapped component behind the'use client';
boundary. The Lit SSR patching does not work within React Server Components. This note is added to the example README as well as in the changelog entry up above.Testing
Testing was done manually by running each example projects and inspecting the page source to confirm declarative shadow DOM was server rendered, there were no React hydration errors, and components became interactive.
Future work
It would be much better to have automated integration/e2e testing for these test nextjs projects.
While I updated the README for the
@lit-labs/nextjs
package, it would be good to have a fuller explanation of the caveats of app router support somewhere like on lit.dev's frameworks section.Notes for releasing
The
@lit-labs/ssr-react
dependency minimum version should be updated for the next release of@lit-labs/nextjs
. Both are getting "breaking" version bumps (minor for 0. package) so changesets might already do this but adding a note here as a reminder to check it.