Skip to content
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

add support for (progressive) hydration for compatible renderers (globalThis for state?) #880

Open
1 of 5 tasks
thescientist13 opened this issue Feb 9, 2022 · 0 comments
Assignees
Labels
CLI Content as Data documentation Greenwood specific docs feature New feature or request SSR
Milestone

Comments

@thescientist13
Copy link
Member

thescientist13 commented Feb 9, 2022

Type of Change

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

Summary

At it simplest, in the context of server or pre-rendering, hydration is the ability for a client side library to re-use the existing HTML (often generated by same client library on the server side) so that on load of the page, the client side library can avoid having to do any DOM manipulation and just build up its internal state / event handers from the existing inert HTML on the page already. This really help with things like Cumulative Layout Shift (CLI) and Time to Interactive (TTI) which are a part of core web vitals.

I think this should be a feature turned off by default, and that can be enabled via greenwood.config.js.

Details

Libraries like Lit provide such a capability (which will be the pilot for this particular issue though I do want roll our own at some point in service of #548 ) but in the context where data comes into play, that same data must be present in the client as well to ensure that server and client HTML match.

Thus Greenwood needs to expose / inject data somehow into the system we have set up, or alter it to be more accommodating. For static prerendering, this may require another approach since it won't be coming from a [route].js file. My initial hunch is to follow a similar convention as per interpolateFrontmatter and just stuff everything into globalThis as per #1005 , e.g.

<script type="module">
  globalThis = <!-- JSON.stringify(data) from the backend -->
</script>

Will also want to add this for WCC using metadata

if (Object.keys(metadata).length > 0) {
  data.frontmatter = data.frontmatter || {};
  data.frontmatter.imports = data.frontmatter.imports || [];

  for (const entry in metadata) {
    data.frontmatter.imports.push(
      metadata[entry].moduleURL.pathname.replace(parsedCompilation.context.userWorkspace, '')
    );
  }
}

Also should support different strategies like eager or lazy loading.


Coming out of https://github.com/ProjectEvergreen/greenwood/pull/1157/files#r1359495833, I think we have the mechanism by which to orchestrate this now, and it can be opt-in without any specification configuration. The gist being any SSR page can export a loader function, which Greenwood can use to

  1. It helps draw a line between a basic component definition, and a custom bespoke API
  2. For hydration, we need to know the props. Having a loader function allows us to serialize the props for further hydration at runtime.
export default class MyPage extends HTMLElement {

  constructor({ post }) {
    this.super();
    console.log(post);
  }
}

export async function loader(request) {
  const params = new URLSearchParams(request.url.slice(request.url.indexOf('?')));
  const postId = params.get('id');
  const post = await fetch(`https://example.com/posts/${postId}`).then(resp => resp.json());

  return {
    post
  };
}

That said, if SSR pages never have their code sent to the client, is any of this needed? A page could also SSR the data right into their child components like in this example?, e.g.

import '../components/upcoming-events/upcoming-events.js';

export default class Home extends HTMLElement {
  async connectedCallback() {
    const events = (await fetch('https://www.analogstudios.net/api/v2/events?tag=tt').then(resp => resp.json()))
 
    this.innerHTML = `
      <tt-upcoming-events
        events='${JSON.stringify(events).replace(/'/g, '\\"')}'
      ></tt-upcoming-events>
    `;
  }
}

Could be worth looking into WCCG Context Community Protocol. We can even consider making it opt-in, e.g.

// src/pages/posts.js

export default class PostPage extends HTMLElement {
  // ...
}

export const useContext = true;

Or else maybe there is a use case to ship the SSR page code to the client? 🤔


The pilot for this can be Lit's SSR hydration support added in #1201

and WCC

@thescientist13 thescientist13 added P0 Critical issue that should get addressed ASAP documentation Greenwood specific docs CLI Content as Data SSR labels Feb 9, 2022
@thescientist13 thescientist13 added this to the 1.0 milestone Feb 9, 2022
@thescientist13 thescientist13 self-assigned this Feb 9, 2022
@thescientist13 thescientist13 added the feature New feature or request label Mar 15, 2022
@thescientist13 thescientist13 pinned this issue Mar 27, 2022
@thescientist13 thescientist13 changed the title add support for hydration for compatible renders (globalThis state?) add support for hydration for compatible renderers (globalThis state?) Mar 29, 2022
@thescientist13 thescientist13 changed the title add support for hydration for compatible renderers (globalThis state?) add support for hydration for compatible renderers (globalThis for state?) Mar 29, 2022
@thescientist13 thescientist13 changed the title add support for hydration for compatible renderers (globalThis for state?) add support for (progressive) hydration for compatible renderers (globalThis for state?) Jun 22, 2022
@thescientist13 thescientist13 moved this from 🔖 Ready to 📋 Backlog in [Greenwood] Phase 9 - Standards and Conventions Oct 29, 2022
@thescientist13 thescientist13 unpinned this issue Nov 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLI Content as Data documentation Greenwood specific docs feature New feature or request SSR
Projects
Status: 📋 Backlog
Development

No branches or pull requests

1 participant