-
-
Notifications
You must be signed in to change notification settings - Fork 355
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
Rendering JSON responses #568
Comments
I was originally thinking about to make it possible to return any kind of JSON responses (like what API routes do) and letting the users implement the actual rendering part. Actually, this will enable users to implement API routes in somewhat easy way. |
Currently, with Client Routing, the initial HTML request is (and needs to be) HTML, while subsequent requests are actually JSON. So I'm not sure how this feature request differs with the current satus quo. I'm wondering how this connects to island archtiecture. The bottom line and goal of island archtiecture is to ship less JavaScript to the client-side. What kind of JSON response do you want to make that would enable you to achieve island architecture? |
Actually it's not required that the response should be in JSON. All I need is just a part(not a whole page) of HTML that can be fetched through JS. |
In You can then add your HTML parts to pageContext and use |
Hi, I am facing the same need. I have SSR app with backend (fastify) integration. In the VPS app I have some modules that are used in ATM I found a wokraround how to do it in VPS, but it is not standard/documented way and I am aware it may break one day. I will try explain my sollution: Goal: I want to serve some data in endpoint
// pages/api/data.page.server.ts
import { getData } from 'some-data-module';
export const onBeforeRender = async (pageContext) => {
const data = await getData();
return {
pageContext: {
pageProps: { // pageProps is required by VPS
data,
},
},
};
};
export async function render() {
return {}; // return empty object as no other props are needed
}
app.get('/api/*', async (req, res) => {
const pageContextInit = {
urlOriginal: req.raw.url
};
const pageContext = await renderPage(pageContextInit);
res.status(200)
.type('application/json')
.send(pageContext.pageProps); // return pageProps that were generated in onBeforeRender
return res;
}) The same way you can also implement POST API endpoint and passing some request data to But as I mentined before, it is just a hacky workaround. I am thinking of different sollution. @brillout Would it be possible to define some file that will hold additional modules exports that will be accessible alongside Example:
// /exports.ts
import { getData } from 'some-data-module';
import { someFunction } from './utils';
export { getData, someFunction }
import { renderPage, exports } from 'vite-plugin-ssr';
...
app.get('/api/data', async (req, res) => {
const data = await exports.getData();
res.status(200)
.type('application/json')
.send(data);
return res;
}) Thanks! |
@bagr001 What's your motivation for not completely bypassing VPS and creating a normal Fastify route instead? |
@brillout My motivation is to share code that is transpiled by Vite and used both in VPS SSR and also directly in server code. It would be ideal to completely bypassing VPS, but I cannot find a solution how to solve this ATM :-( In my primary use case, I aim for data-caching. Let's say I have a function that fetches some data and stores them in a module exported variable that acts like a cache. I want to access this data from VPS There is a workaround to make the caching code as an external module that is built independently, but then the DX sucks for my scenario. That is why I am trying to find a way to transpile some server code by Vite and make it accessible from the server - same as VPS plugin works. Thanks. // server/index.ts
await cacheWarmup();
server.listen(); // data/cache.ts
export let cache;
export async function cacheWarmup() {
cache = await fetch('/api/data');
} // pages/index.page.server.ts
import { cache} from '@/data/cache';
export const onBeforeRender = async (pageContext) => {
return {
pageContext: {
pageProps: {
cache,
....
},
},
};
}; |
@bagr001 Either use |
Maybe take a look at telefunc? |
👍 Telefunc is an option as well, since (Regardless of the solution you go with, I recommend looking into that |
I have a similar use-case where I just want a fragment, instead of the entire html/head. Did it like this, but relies heavy on the import { renderPage } from 'vite-plugin-ssr';
async function renderFragment(requestContext) {
const vpsRenderResult = await renderPage(requestContext);
return {
fragment: {
body: vpsRenderResult.markup.body,
assets: vpsRenderResult._pageAssets,
}
};
}
app.get('*', async (req, res, next) => {
const { fragment } = await renderFragment({/* context */});
if (!fragment) {
return next();
} else {
res.send(JSON.stringify(fragment));
}
}); Might be a nice addition to have a way to retrieve the generated manifest. |
@leonmondria I think your use case is quite different though, feel free to create a GitHub Discussion explaing your use case in further details. |
Well actually @leonmondria 's usecase matches almost exactly with mine. |
@leonmondria @XiNiHa Would the following work for you? // /renderer/_default.page.server.js
export { onBeforeRender }
export const passToClient = 'htmlFragments'
async function onBeforeRender(pageContext) {
if (pageContext.isClientSideRouting) {
return {
pageContext: {
htmlFragments: [/*...*/]
}
}
}
} The new feature here being Note that VPS already returns JSON for subsequent client-side routing requests, so AFAICT there isn't any need to modify the usually Also note that As for Let me know if that doesn't work for you or if you have any questions. |
Looks great for me! |
Released in |
Description
From @XiNiHa
How would such an example POST request look like and what would the JSON contain?
The text was updated successfully, but these errors were encountered: