ProjectEvergreen / greenwood

Greenwood is your workbench for the web, embracing web standards from the ground up to empower your stack from front to back.
https://www.greenwoodjs.io
MIT License
97 stars 9 forks source link

Lit v3 upgrade and SSR Pages support and compatibility for renderer plugin #1197

Closed thescientist13 closed 6 months ago

thescientist13 commented 8 months ago

Summary

Was making a demo for Lit SSR on Vercel serverless functions and ran into a few issues. (check out the patches/ folder) in

Node Resolution

We will need to add node as a default bundling export condition or else the DOM shim wont come in. This would be needed for SSR pages and API routes.

// rollup.config.json
plugins: [
  // ...
  nodeResolve({
    exportConditions: ['default', 'module', 'import', 'node']
  })
]

Otherwise, the serve command was failing with the below error.

    ReferenceError: HTMLElement is not defined
    at file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/public/api/card.04a6f554.js:204:752
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
    at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:305:29
    at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:275:7
    at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:233:5
    at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:200:5
  

This is called out in the Lit SSR docs

As such, when Lit runs in Node, it automatically uses a set of minimal DOM APIs necessary to render Lit on the server, and defines the customElements global.


Maybe #1187 will handle this by default? Should look into it.

SSR Client Script

Looks we were missing the addition of the SSR client hydration script from our output

<!-- ssr-client lit-element-hydrate-support should be loaded first. -->
<script type="module" src="/node_modules/@lit-labs/ssr-client/lit-element-hydrate-support.js"></script>

Otherwise we were getting double rendering in the browser

customElements.define conflict ⚠️

Haven't seen this in any of my other demos with WCC, but if you load the home page and click the more products button, the page will crash the following error can be seen in the terminal, meaning this happening in NodeJS land. (Maybe this is why workers are good - #1117 ) Screenshot 2024-01-19 at 8 56 33 PM

Error: Failed to execute 'define' on 'CustomElementRegistry': the name "app-card" has already been used with this registry at CustomElementRegistry.define (file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/public/lit-element.2f782e55.js:220:23) at file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/public/api/card.658da880.js:11316:16 at ModuleJob.run (node:internal/modules/esm/module_job:193:25) at async Promise.all (index 0) at async ESMLoader.import (node:internal/modules/esm/loader:530:24) at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:305:29 at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:275:7 at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:233:5 at async file:///Users/owenbuckley/Workspace/github/greenwood-demo-adapter-vercel-lit/node_modules/@greenwood/cli/src/lifecycles/serve.js:200:5

edit: ah, the Lit implementation specifically fails on multiple customElements.define calls, which in all fairness is to the spec. Wonder if WCC should impose this restriction too? Would add more overhead though... 🤔


We may want to revisit the SSR docs on their recommendation of running in a VM module vs a Worker.

Details

The specific set of fixes and enhancements will need to implement are

  1. Upgrade Lit to v3
  2. Refactor renderToString to use new collectResult SSR API
  3. Will want to add @lit-labs/ssr-client as dependency
  4. Will only be able to support the getBody API for pages, since there is no "Server Components Only" option with Lit
  5. Implement basic hydration support
    • Will want to track full data hydration support as part of #880 and #1177
      • export const hydration = true
      • data loader will be needed? - export const function loader() => { /* ... */ }
  6. Looks like are we missing HTML intercepting and optimizing during SSR pages bundling
  7. plugins have to manage their own type="module-shim" 🤔
  8. Misc
    • How come the Lit card re-renders on client side? (make a repro repo)
      • need the polyfill?
      • chrome doesn't already support it?
  9. After this, could we suggest adding ourselves to the list of tools here (or maybe after the website redesign)? - https://lit.dev/docs/ssr/overview/