vikejs / vike

🔨 Flexible, lean, community-driven, dependable, fast Vite-based frontend framework.
https://vike.dev
MIT License
3.93k stars 335 forks source link

New hook `onRenderContent()`: generate non-HTML files with arbitrary content #1525

Open iacore opened 4 months ago

iacore commented 4 months ago

Description

I hope vike can generate files that is not HTML and without injected tags.

The requirements are

Related: #1522 #1524

Use Cases

brillout commented 4 months ago

Use Cases

So far the recommendation for these two use cases are to use a post-build script (without using Vite).

I agree that being able to use Vite for transpiling the post-build script would be nice. In the meantime, can you fallback to use other utilities such as ts-node (and fast-glob instead of import.meta.glob())?

Why not adding a new CLI command $ vike run path-to/some-script.ts instead of your proposal?

Or maybe a new Vike hook onAfterBuild(), but that would work only for build. Actually, how about a new generic hook onRenderContent() that can generate content that isn't HTML.

Spontaneously I like $ vike run and onRenderContent() most. But I'm happy to discuss this.

Also, what do other frameworks do to support these two use cases? Can someone dig into that?

iacore commented 4 months ago

onRenderContent is best, I think. Still need to offer an option to set the output path, though. It would be nice if the API allows access to pageContext from other files like page title, which will make sitemap generation easier.

Also, what do other frameworks do to support these two use cases? Can someone dig into that?

lume allows generating arbitrary file content. lume has a sitemap plugin.

To set the page URL in lume, you simply do

export const url = "/feed.json";

or

---
url: /blog/example.md
---

# Page Content Here

Eleventy allows generating arbitrary content too. It has a RSS plugin which only provides data and needs the user to provide a template for it. You can use the RSS plugin to generate a site map with the correct template.

brillout commented 4 months ago

Still need to offer an option to set the output path, though.

Or how about using Filesytem Routing as usual?

It would be nice if the API allows access to pageContext from other files

You shouldn't do that in dev, see https://vike.dev/markdown#metadata. Upon pre-rendering you can already access that, although it's currently hidden behind an internal API: pageContext._prerenderContext.pageContexts.

It makes sense that SSGs like Lume and Eleventy supports that use case. I was more wondering about SSR frameworks such as Next.js or Nuxt.

iacore commented 4 months ago

Or how about using Filesytem Routing as usual?

How do I generate dist/client/feed.json but not dist/client/feed.json/index.html?

Also, I can't name a folder feed.json because vite complains about trying to load the folder as JSON. (you can create feed.json/+Page.tsx to test it out)

It makes sense that SSGs like Lume and Eleventy supports that use case. I was more wondering about SSR frameworks such as Next.js or Nuxt.

In those frameworks, the Atom feed is usually an API route, and vike made the decision to not support API routes (I read that in the docs).

brillout commented 4 months ago

How do I generate dist/client/feed.json but not dist/client/feed.json/index.html?

Vike wouldn't create an .html file when the content is generated with onRenderContent().

Also, I can't name a folder feed.json because vite complains about trying to load the folder as JSON. (you can create feed.json/+Page.tsx to test it out)

You could use a Route String.

In those frameworks, the Atom feed is usually an API route, and vike made the decision to not support API routes (I read that in the docs).

You can use an Express.js/Fastify/Hono/... route instead. Note that we're currently working on https://github.com/vikejs/vike/issues/562. I stand to be corrected, but I believe that once #562 is implemented then API routes would be an inferior design in all regards.

iacore commented 4 months ago

Vike wouldn't create an .html file when the content is generated with onRenderContent().

I need a static page! onRenderContent won't generate a JSON file, or can it?

You could use a Route String.

A route string of /feed.json generates /feed.json/index.html

In #562, you linked to vite-node. I'll try writing a script with that. Thanks for the idea!

brillout commented 4 months ago

@iacore It will create a file, it just won't be a .html one. If you set the Route String to end with .json so will the generated file.

brillout commented 4 months ago

Since there is a workaround and there are only two use cases for it, I'm labeling this as low-prio 🐌.

That said, the priority can be increased by:

iacore commented 4 months ago

The vite-node method worked! Do we document the vite-node usage somewhere?

I haven't tried onRenderClient. Is it strange that onRenderClient renders to a file on the server?

brillout commented 4 months ago

I haven't tried onRenderClient. Is it strange that onRenderClient renders to a file on the server?

Apologies I meant onRenderContent() not onRenderClient(). I've edited my comment (and yours).

The vite-node method worked! Do we document the vite-node usage somewhere?

It isn't. I think it's fine for now as there are currently a lot of higher priorities regarding the docs.

iacore commented 4 months ago

Apologies I meant onRenderContent() not onRenderClient(). I've edited my comment (and yours).

I assume you meant onRenderHtml. I can't find a onRenderContent hook.

@iacore It will create a file, it just won't be a .html one. If you set the Route String to end with .json so will the generated file.

as of vike 0.4.165, it generates xxx.json/index.html rather than xxx.json, with the route string below:

// +route.ts
export default '/test.json'
brillout commented 2 months ago

Interesting approach by SvelteKit: https://kit.svelte.dev/docs/seo#manual-setup-sitemaps