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

Rfc/issue 952 data loading strategies #1157

Merged
merged 13 commits into from
Oct 31, 2023

Conversation

thescientist13
Copy link
Member

@thescientist13 thescientist13 commented Oct 1, 2023

Related Issue

resolves #952

Summary of Changes

  1. Add async loader function constructor props for SSR pages request time data (aka getServerSideProps)
  2. (breaking) Refactor / rename getFrontmatter.static -> export const prerender = true (aka getStaticProps)
  3. Added documentation for loader Web Server Components (WSCs) and export const prerender
  4. (breaking) Refactor plugin-graphql
    • Closer ESM compat (now no more need for Rollup aliases)
    • Document / validate prerender: true / custom imports alternative to Puppeteer
  5. Upgrade wcc@0.9.0

TODO

  1. equivalent for getStaticPaths - I think this depends on landing Server side routes should support dynamic route naming (with prerendering) #882 , so will need to track there instead
  2. Adopt non-loader implementation of data fetching
  3. Align Greenwood and WCC on data loading behavior - feature/issue 119 constructor props wcc#120
  4. Need to do anything for adapters?
  5. address PR feedback

Thoughts / Questions

  1. loaders pattern vs RSC flavor page components? - https://github.com/ProjectEvergreen/greenwood/pull/1157/files#r1349748857
  2. GraphQL thoughts - should we keep it?
  3. Graph refactoring (or own issue?) - Content as Data #1167
    • rename imports field to resources in frontmatter for graph
    • Change graph.json from path -> url (instance of URL)
    • Make graph an actual graph (edges + nodes). What's the best data structure for this? Otherwise should we not call it a graph.json?
    • How to vanilla fetch the graph without GraphQL? Come in as compilation props?
  4. Rethink SSR pages API (getFrontmatter, getTemplates, getBody, etc) - will save this for Layouts (Templates) and Pages #955
  5. context plugins as part of SSR (for pages and templates work?) - tracking in Layouts (Templates) and Pages #955
  6. refactor context, move all things into manifest.json - tracking in Layouts (Templates) and Pages #955
  7. Deprecate Custom Elements flavor of Include Plugin? - made a note of this to revisit this

@thescientist13 thescientist13 added RFC Proposal and changes to workflows, architecture, APIs, etc documentation Greenwood specific docs CLI breaking SSR feature New feature or request labels Oct 1, 2023
@thescientist13 thescientist13 linked an issue Oct 7, 2023 that may be closed by this pull request
}
}

export async function loader(request) {
Copy link
Member Author

@thescientist13 thescientist13 Oct 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought here is to just lean into the class based paradigm instead of creating a custom API, e.g. loaders. So basically something like this, wherein the request comes through the constructor instead, any synchronous operations are done there, and let all the async work happen in connectedCallback

export default class PostPage extends HTMLElement {
  constructor(request) {
    super();
    
    const params = new URLSearchParams(request.url.slice(request.url.indexOf('?')));
    this.postId = params.get('id');
  }

  async connectedCallback() {
    const { postId } = this;
    const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(resp => resp.json());
    const { id, title, body } = post;

    this.innerHTML = `
      <h1>Fetched Post ID: ${id}</h1>
      <h2>${title}</h2>
      <p>${body}</p>
    `;
  }
}

We can even call them WSCs (Web Server Components) ™️ 🤠

Copy link
Member Author

@thescientist13 thescientist13 Oct 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the last Greenwood weekly meeting, a good suggestion was made that the default behavior could be done as in the snippet above, and that possibly with #880, for users that want to opt-in to hydration, that mechanism could be to export a loader function.

This would have a few benefits:

  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.
  3. Perhaps to tie it all in together, we can leverage apply isomorphic standards to userland libraries and plugins (globalThis) #1005 ?

> _**Note**: Keep in mind that for these "page" components, you will likely want to _avoid_ Declarative Shadow for rendering the top level (to avoid wrapping static content in `<template>` tags), but definitely use Declarative Shadow DOM within any dependent custom elements of your page._
A couple of notes:
- WSCs run only on the server, thus you have full access to any APIs of the runtime, with the ability to perform one time `async` operations for [data loading](/docs/server-rendering/#data-loading) in `connectedCallback`.
- In the above example, card.js will automatically be bundled for you on the client side!
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... goes Greenwood actually do this? 🤔

I feel like yes, but in reality I don't think I've observed it? Can't say I've directly looked for it since I didn't think it was actually a feature 😅

@@ -293,9 +293,9 @@ async function getHybridServer(compilation) {
const isApiRoute = manifest.apis.has(url.pathname);
const request = transformKoaRequestIntoStandardRequest(url, ctx.request);

if (!config.prerender && matchingRoute.isSSR && !matchingRoute.data.static) {
if (!config.prerender && matchingRoute.isSSR && !matchingRoute.prerender) {
console.log('MATCHING ROUTE -> ', matchingRoute.filename);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to delete this console line

@@ -1,23 +1,15 @@
# @greenwood/plugin-graphql

## Overview
A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's content graph. It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend and provides an [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use.
A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's [content graph](https://www.greenwoodjs.io/docs/data/) with our optoinal [pre-made queries](https://www.greenwoodjs.io/docs/menus/). It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend at build time and provides a **"read-only"** [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling mistake here on optional

@@ -1,23 +1,15 @@
# @greenwood/plugin-graphql

## Overview
A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's content graph. It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend and provides an [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use.
A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's [content graph](https://www.greenwoodjs.io/docs/data/) with our optoinal [pre-made queries](https://www.greenwoodjs.io/docs/menus/). It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend at build time and provides a **"read-only"** [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also a little funky grammar here at the end of the last sentence.


> _We are working on re-evaluating and improving our [data loading](https://github.com/ProjectEvergreen/greenwood/issues/952) and [rendering strategies](https://github.com/ProjectEvergreen/greenwood/issues/951) as part of our [1.0 release](https://github.com/ProjectEvergreen/greenwood/milestone/3)._
As of now, this plugin requires some form of [prerendering](https://www.greenwoodjs.io/docs/server-rendering/#render-vs-prerender) either through:
1. Enabling [custom imports](https://www.greenwoodjs.io/docs/server-rendering/#custom-imports)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify that custom imports is related to SSR

@thescientist13 thescientist13 marked this pull request as ready for review October 17, 2023 01:48
@thescientist13 thescientist13 added the dependencies Pull requests that update a dependency file label Oct 28, 2023
@thescientist13 thescientist13 force-pushed the rfc/issue-952-data-loading-strategies branch from 4ebfb81 to 806e9e9 Compare October 28, 2023 01:13
@thescientist13 thescientist13 merged commit 34156fc into release/0.29.0 Oct 31, 2023
7 checks passed
@thescientist13 thescientist13 deleted the rfc/issue-952-data-loading-strategies branch October 31, 2023 00:37
thescientist13 added a commit that referenced this pull request Nov 9, 2023
* add support for SSR page loader with runtime request object

* refactor static export from getFrontmatter to export const prerender

* document loaders and prerendering for SSR routes

* adopt and document constructor props pattern for SSR page data loading

* update develop SSR test case for constructor props

* remove desribe.only

* refactor graphql plugin for ESM compat

* add test case for experimental prerendering with custom .gql imports

* upgrade website for breaking changes

* update website documentation and graphql plugin package README

* add test cases for adapter plugins and SSR constructor props

* upgrade wcc to 0.9.0

* misc PR cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking CLI Content as Data dependencies Pull requests that update a dependency file discussion tied to an ongoing discussion or meeting notes documentation Greenwood specific docs feature New feature or request needs upstream Plugins Greenwood Plugins RFC Proposal and changes to workflows, architecture, APIs, etc SSR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Data Loading Strategies
1 participant