diff --git a/.changeset/eight-elephants-sparkle.md b/.changeset/eight-elephants-sparkle.md new file mode 100644 index 0000000000..f931f1d451 --- /dev/null +++ b/.changeset/eight-elephants-sparkle.md @@ -0,0 +1,5 @@ +--- +'@lit-labs/react': minor +--- + +Add Node build for server rendering. This will allow wrapped components to be added to SSR React frameworks like Next.js. diff --git a/.eslintignore b/.eslintignore index d876a31201..f0da458260 100644 --- a/.eslintignore +++ b/.eslintignore @@ -241,6 +241,7 @@ packages/labs/observers/performance_controller.* packages/labs/observers/resize_controller.* packages/labs/observers/intersection_controller.* packages/labs/react/development/ +packages/labs/react/node/ packages/labs/react/test/ packages/labs/react/node_modules/ packages/labs/react/index.* diff --git a/.prettierignore b/.prettierignore index 5d597b371c..1a006c1203 100644 --- a/.prettierignore +++ b/.prettierignore @@ -227,6 +227,7 @@ packages/labs/observers/performance_controller.* packages/labs/observers/resize_controller.* packages/labs/observers/intersection_controller.* packages/labs/react/development/ +packages/labs/react/node/ packages/labs/react/test/ packages/labs/react/node_modules/ packages/labs/react/index.* diff --git a/packages/labs/react/.gitignore b/packages/labs/react/.gitignore index 3db826b636..9631861522 100644 --- a/packages/labs/react/.gitignore +++ b/packages/labs/react/.gitignore @@ -1,4 +1,5 @@ /development/ +/node/ /test/ /node_modules/ /index.* diff --git a/packages/labs/react/package.json b/packages/labs/react/package.json index 5e3f4faebc..44f0a6ff20 100644 --- a/packages/labs/react/package.json +++ b/packages/labs/react/package.json @@ -20,17 +20,20 @@ ".": { "types": "./development/index.d.ts", "development": "./development/index.js", + "node": "./node/index.js", "default": "./index.js" }, "./use-controller.js": { "types": "./development/use-controller.d.ts", "development": "./development/use-controller.js", + "node": "./node/use-controller.js", "default": "./use-controller.js" } }, "files": [ "/development/", "!/development/test/", + "/node/", "/index.{d.ts,d.ts.map,js,js.map}", "/create-component.{d.ts,d.ts.map,js,js.map}", "/use-controller.{d.ts,d.ts.map,js,js.map}" @@ -43,6 +46,7 @@ "test": "wireit", "test:dev": "wireit", "test:prod": "wireit", + "test:node": "wireit", "checksize": "wireit" }, "wireit": { @@ -111,7 +115,8 @@ "test": { "dependencies": [ "test:dev", - "test:prod" + "test:prod", + "test:node" ] }, "test:dev": { @@ -133,6 +138,13 @@ ], "files": [], "output": [] + }, + "test:node": { + "command": "node development/test/node-render.js", + "dependencies": [ + "build:ts", + "build:rollup" + ] } }, "author": "Google LLC", diff --git a/packages/labs/react/rollup.config.js b/packages/labs/react/rollup.config.js index 57aeba4691..f842d0af20 100644 --- a/packages/labs/react/rollup.config.js +++ b/packages/labs/react/rollup.config.js @@ -10,4 +10,5 @@ import {createRequire} from 'module'; export default litProdConfig({ packageName: createRequire(import.meta.url)('./package.json').name, entryPoints: ['index', 'create-component', 'use-controller'], + includeNodeBuild: true, }); diff --git a/packages/labs/react/src/create-component.ts b/packages/labs/react/src/create-component.ts index 3db9fdca09..a439591e46 100644 --- a/packages/labs/react/src/create-component.ts +++ b/packages/labs/react/src/create-component.ts @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +const NODE_MODE = false; + // Match a prop name to a typed event callback by // adding an Event type as an expected property on a string. export type EventName = string & { @@ -315,7 +317,11 @@ export function createComponent< if ( eventProps.has(k) || (!reservedReactProperties.has(k) && - !(k in HTMLElement.prototype) && + // NODE_MODE check below is to support React SSR where HTMLElement + // might not be defined + !(NODE_MODE && typeof HTMLElement === 'undefined' + ? false + : k in HTMLElement.prototype) && k in element.prototype) ) { this._elementProps[k] = v; diff --git a/packages/labs/react/src/test/node-render.ts b/packages/labs/react/src/test/node-render.ts new file mode 100644 index 0000000000..a04574b461 --- /dev/null +++ b/packages/labs/react/src/test/node-render.ts @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2022 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ + +// This file will be loaded by Node from the node:test script to verify that +// wrapped components can be server rendered by React. + +import {createComponent} from '@lit-labs/react'; +import {ReactiveElement} from '@lit/reactive-element'; +import {customElement} from '@lit/reactive-element/decorators/custom-element.js'; +import React from 'react'; +import {renderToString} from 'react-dom/server.js'; + +@customElement('my-element') +class MyElement extends ReactiveElement {} + +const Component = createComponent({ + react: React, + tagName: 'my-element', + elementClass: MyElement, +}); + +renderToString(React.createElement(Component));