withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
44.98k stars 2.35k forks source link

[RFC] Astro component's Request-Time Server Side Composition(SSC) functionality #525

Closed toinbis closed 3 years ago

toinbis commented 3 years ago

This is a forked discussion from https://github.com/snowpackjs/astro/issues/370 issue after https://github.com/snowpackjs/astro/issues/370#issuecomment-864517160 comment.

Motivation

Astro allows building classical frontends(html+css+vanilla js dom manipulations) with modern tooling (including micro frontends principles). But it can only be used in static-site/serverless hosting/jamstack environments.

I propose considering covering the same needs in server-side request-time html/css/vanilla-js composition environment, such as websites running express.js in the backend.

Quit detailed description of the problem is provided below, but I think RFC issues require as much context as possible for everyone to be on the same page.

Example use case scenario/user story

Let's consider such bussiness requirements:

Architecture supporting above requirements might look something like that:

Screenshot 2021-06-23 at 23 22 45

Example use case implementation and user feedback

I build a proof-of-concept website using such stack https://turboeshop.com/fastestpageintheworld/ .

Components were developed in separate repo using react and published to bit.dev headless component repository: Screenshot 2021-06-23 at 23 29 45

In headless CMS content editors can craft whatever pages they like using all the component repository with 0 development team involvement: Screenshot 2021-06-23 at 23 33 06

I've shared this proof of concept with HackerNews community, in https://news.ycombinator.com/item?id=25342767 thread, as https://news.ycombinator.com/item?id=25357862 and https://news.ycombinator.com/item?id=25360658 comment.

For certain set of bussiness requirements, that's literally an ideal flow with excelent end result. But there is one problem.

The Problem

Let's add one more additional bussiness requirement:

Which means, that in the bottom of the page there must be such part would be automatically outputed to HTML by default Astro tooling. How the would be rendered in the final html file, when rendering is performed by astro default tooling, can be controlled with approaches defined by Matthew in #370 as const shouldInsertScript = Astro.component.instanceCount === 1 or other similar approaches.

All clear and simple if we use only Astro tooling for developing, previewing and build-time rendering html pages.

  1. But now I want to render Astro component without default Astro tooling. It’s an express.js controller environment where I will compose pieces of *.astro component into final html myself.
import { componentA } from “@mywebsite/astrocomponents.atoms.componentA"

// import React from “react” // This is what current working react alternative looks like
// import { renderToStaticMarkup } from "react-dom/server" // This is what current working react alternative looks like
//  import Astro from “react”
import { renderHtmlToStaticMarkup } from “astro-dom/server”
import { renderJsToStaticScripts } from “astro-dom/server”

const componentAhtml = renderHtmlToStaticMarkup(<componentA>)
// value of componentAhtml is ```<div>Component A</div><script>console.log('Message from Component A')</script>```

const componentAjs = renderJsToStaticScripts(<componentA>)
// value of componentAjs is ```[`console.log(‘Static Message from Component A’)`]``` //i.e. multiple js snippets could be returned.

The <script: static> is 50% of what this RFC is about, renderHtmlToStaticMarkup and renderHtmlToStaticJS is another 50%. Astro needs to provides these helper functions that would expose low-level API of returning separate pieces of astro component. We probably want to expose the opportunity to retriuve the both templates and rendered versions of both js and html.

  1. And there are also two obvious more advanced scenarios:

a) renderHtmlToStaticMarkup needs to be able to accept props (react does this), renderHtmlToStaticJS also if we decide we can use Githubissues.

  • Githubissues is a development platform for aggregating issues.