Closed Princesseuh closed 6 months ago
Major point to be resolved: how do we surface styles
and scripts
? Ideally this API would work similarly to Svelte's Component.render()
, but Astro's compiler strips out scripts and styles to be handled by Vite. I have yet to figure out what we should do here!
FWIW, even though it's out of scope here (as it should be), based on the API described above, this could work in Storybook's client-side environment too, similar to how preact-render-to-string
or react-dom/server
does. In the end it would depend on which API's it would use under the hood, like node:fs
, etc.
I'm really eager for this one right now. I'm unsure of other use cases, but this seems like it'll make it easy-peasy to render MDX blog posts into RSS!
https://github.com/withastro/roadmap/discussions/462 - initial discussion mention vite-plugin-astro
as a requirement. Is that true? Would that mean that express.js or https://hono.dev would not be able to generate components using this API?
Thanks a lot for shipping this anyways!
This would be really helpful for my use case where I am trying to create unique SVGs.
// Outputs: /svg-1.json
export async function get({params, request, props}) {
return {
body: await astro.renderToString(SvgComponent, { props, slots, request, params })
};
}
Bumping for storybook support.
Hi!, any update about this? It would be amazing to have Astro in Storybook
If we had any updates, we'd share them. Please refrain from posting unnecessary comments.
I found this thread from the storybook discussion. I think that's probably one of the more apparent use cases. I'd like to add one of my own:
In recent projects we have established a pattern to allow a parent component to evaluate if it's children will output anything, and take appropriate actions if not. To achieve this, each component exposes a shouldRender
function which the parent can call. At the moment, those functions do not render anything, they just return a boolean. For example if typeof x !== undefined && y.length > 0
.
Two examples of where we could use this:
In some scenarios this pattern becomes difficult to set up and maintain. It probably adds some overhead that we can not optimise. Being able to render children in isolation, like proposed in this RFC, would greatly simplify our workflow! Hopefully without any additional overhead at all :)
Another use-case is as simple as ability to cache the rendered HTML.
If you have static content that comes either from some CMS or is changed once a day or similar it does not make sense to cache the underlying data if you can directly cache HTML and put it directly in the response instead of rendering it every single time.
I was mostly working around this issue by using an external markdown renderer, but recently stumbled upon the problem with the images — given Astro handles them in a “smart” way, the generated images are not available in the RSS that I generate, so it would be really nice to see this issue to move forward.
Major point to be resolved: how do we surface
styles
andscripts?
Ideally this API would work similarly to Svelte'sComponent.render()
, but Astro's compiler strips out scripts and styles to be handled by Vite. I have yet to figure out what we should do here!
I think for a lot of use cases for this feature, it would be totally fine to omit the styles and scripts in the first implementation, and think about them later.
Are there other blockers that prevent the development of this? If there is no obvious path for styles and scripts, but there is one for just outputting the rendered HTML — can we go with it to unlock this issue, and then work iteratively on the improvements for it?
I agree that most use cases I can think of will not necessarily need any style/scripts and if needed can be added manually whenever the produce html string is eventually used.
I wouldn't mind it being developed without style/script in its first implementation.
Later on, scripts and styles could be added as different methods.
const element = {
html: Component.render(),
js: Component.scripts(),
css: Component.styles(),
}
await astro.renderToString(Component, { props, slots, request, params })
will be possible to use outside of astro so we can use only templating part of astro with any http framework like express or fastify?
This could be really useful for testing rendering with astro, I don't know if it is possible in any other way, but I haven't found a way yet.
Adding my usecase, besides storybook I want this for rendering screenshots/mockups directly to images.
I'm curious what "in isolation" means in this context. To me it means sandboxing one component from another, but you seem to mean something more than that. I'm wondering if this would help me solve situations where reusing a component that stands up a nanostore causes the different instances of the component to stomp on each other's storage.
@lschierer No, this is about having a way to render a component to HTML programmatically.
The issue you describe is not really within Astro's purview to solve—you can solve it using JS. For example, you could have each component receive a key prop that it uses to get the nanostore (by looking it up in a shared Map), with a sensible default value. Then two instances of the same component that should have different stores can use their differing keys to get them.
Or, if they never need to share state, just call atom
separately for each component instance. E.g. get all the component root elements via querySelectorAll, and for each do some setup that includes creating the unique atom for that instance.
Has progress halted on this? It doesn't seem like the branch is very active. I for one am very eager to use this API.
Has progress halted on this? It doesn't seem like the branch is very active. I for one am very eager to use this API.
@ematipico is currently working on this and shared a preview in our Discord yesterday.
An update: I am currently writing the RFC Stage 3, where we can jump in and discuss expectations and usage.
In the meantime, here's a branch with a working test and a screenshot of the usage. https://github.com/withastro/astro/compare/feat/container-api?expand=1
@ematipico Can we use .astro file instead of object in renderToString? So we can use astro instead of other templating languages like liquid and framework like express.
@ematipico Can we use .astro file instead of object in renderToString? So we can use astro instead of other templating languages like liquid and framework like express.
I'd like to see this as well, at least as an option.
@ematipico Can we use .astro file instead of object in renderToString? So we can use astro instead of other templating languages like liquid and framework like express.
This example is using an internal API for prototyping purposes, it does not reflect the final API! In a normal Astro (Vite) environment, you'll be able to import .astro
files without an issue. The ability to import .astro
files in a vanilla Node environment is a completely different topic that we'd consider out of scope here.
@natemoo-re Would it be so different to support it vanilla Node? How is it out of scope for rendering components in isolation that seems like exactly the case and people would like to use it that way.
@natemoo-re Would it be so different to support it vanilla Node? How is it out of scope for rendering components in isolation that seems like exactly the case and people would like to use it that way.
This use case will likely be addressed by something like Vite's recent runtime API. I'm just calling out the fact that importing and compiling .astro
files outside of a Vite environment isn't something that's likely to be shipped along with this first iteration of the Container API. We know that's something people want, but we're focusing on use cases within existing Astro projects for now to reduce scope so we can ship something.
@natemoo-re Would it make sense to create another issue where we can track the solution with e.g. runtime API ? I'm subscribed to this thread exclusively for this feature that @cdtut mentions, and seems like many others as well.
RFC Stage 3 is now open: https://github.com/withastro/roadmap/issues/533
@natemoo-re Would it make sense to create another issue where we can track the solution with e.g. runtime API ? I'm subscribed to this thread exclusively for this feature that @cdtut mentions, and seems like many others as well.
My advice is to open a stage 1 RFC after the container API lands in user-land and people start using it. I think it's best to first build up good foundations and then implement new things on top of it. Let's first shape the scope of the APIs together, and then let's start proposing new stuff. Maybe landing this API sooner rather than later can be a signal for Vite to stabilise their runtime APIs.
Now that the wheels started to turn, it wouldn't take long to see more APIs for the container APIs.
Stage 3 RFC available in #916
Body
feat/container
branch for an exploration of implementation.Summary
Astro components are tightly coupled to
astro
(the metaframework). This proposal introduces a possible server-side API for rendering.astro
files in isolation, outside of the fullastro
build pipeline.Background & Motivation
Some of our own proposals, as well as many third-party tool integrations, are blocked until we expose a proper server-side rendering API for
.astro
components. Other frameworks have tools likepreact-render-to-string
orreact-dom/server
that make rendering components on the server straight-forward.We've avoided doing this because... it's very hard! Part of the appeal of
.astro
components is that they have immediate access to a number of powerful APIs, context about your site, and a rich set of framework renderers. In the fullastro
build process, we are able to wire up all this context invisibly. Wiring up the context manually as a third-party is prohibitively complex.Goals
.astro
components in isolationastro
parity, but abstract away internal APIs.astro
files on the server.astro
component output.mdx
compiledContent/html output?@astrojs/*
) if possibleExample
The container can be optionally constructed with some settings that are typically reserved for Astro configuration.
The second argument to
renderToString
optionally provides render-specific data that may be exposed through the Astro global, likeprops
,slots
,request
, and/orparams
.