ProjectEvergreen/greenwood

support server rendering a native `HTMLElement`

thescientist13 opened this issue · 0 comments

Type of Change

  • New Feature Request
  • Documentation / Website
  • Improvement / Suggestion
  • Bug
  • Other (please clarify below)

Summary

(grabbed some of this from #926 )

Would like Greenwood to come up with a native solution to HTMLElement SSR rendering, coming out my conversations in the Lit repo - lit/lit#2092 (comment)

The goal would be to leverage Declarative Shadow DOM and provide a default alternative to puppeteer, and moving puppeteer to a custom plugin instead, including all the @webcomponents polyfill dependencies. Effectively this is providing a Next.js like pages experience, but for native custom elements.

Details

I suppose there are two outcomes from this:

  1. Server rendering your client code (e.g. prerender + static)
  2. As part of wcc, we could potentially allow a custom element to be the export and Greenwood can use renderToString to get the final HTML.
    import './path/to/card.js';
    
    export default class ArtistsPage extends HTMLElement {
      async connectedCallback() {
        if (!this.shadowRoot) {
          const artists = await fetch('https://www.analogstudios.net/api/artists').then(resp => resp.json());
          const html = artists.map(artist => {
            return `
              <wc-card>
                <h2 slot="title">${artist.name}</h2>
                <img slot="image" src="${artist.imageUrl}" alt="${artist.name}"/>
              </wc-card>
            `;
          }).join('');
    
          this.attachShadow({ mode: 'open' });
          this.shadowRoot.innerHTML = html;
        }
      }
    }

Because of how wcc works, we should be able to get card.js back as metadata that we can feed into the bundler, which means there would be no need to specify it via <script> tags in the template, which means this could potentially usurp the need for getTemplate and getPage?