Jelmer
Jelmer
NNuxt
Created by Jelmer on 8/5/2024 in #❓・help
Nitro server plugin to cache Nuxt images: how to respond with a file from disk?
Hi, I am writing a server plugin like below. I am using the @nuxt/image module with the ipx provider. I would like it to save its generated image files to disk, and serve those files whenever the exact same file is requested. This example below works. I get served files from disk. But I am using a new Response and doing event.respondWith(res); which keeps resulting in this error in the CLI:
[nuxt] [request error] [unhandled] [500] Cannot set headers after they are sent to the client
at ServerResponse.setHeader (node:_http_outgoing:659:11)
at setResponseHeaders (./node_modules/h3/dist/index.mjs:778:20)
[nuxt] [request error] [unhandled] [500] Cannot set headers after they are sent to the client
at ServerResponse.setHeader (node:_http_outgoing:659:11)
at setResponseHeaders (./node_modules/h3/dist/index.mjs:778:20)
My knowledge of Nitro is limited; if I were to create a plugin like this, is this the correct way? How can I respond with the image file inside the request hook without getting [500] Cannot set headers after they are sent to the client ? Should I use another method to create this functionality? Help is greatly appreciated 🙂
// server/plugins/cache.ts
export default defineNitroPlugin(async (nitroApp) => {
await mkdir(cacheFolder, { recursive: true });

nitroApp.hooks.hook('request', async (event) => {
const { path } = event;

if (!path.startsWith('/_ipx/')) return;

const targetCacheFilePath = getCacheKey(path);
const exists = existsSync(targetCacheFilePath);

if (exists) {
const file = await readFile(targetCacheFilePath);
const res = new Response(file, {
status: 200,
headers: {
'X-Nuxt-Image-Cache': 'HIT',
},
});

await event.respondWith(res);
console.log('Image served from cache:', targetCacheFilePath);
return;
}
});

nitroApp.hooks.hook('afterResponse', async (event, response) => {
// save generated image file to disk, not important right now
});
});
// server/plugins/cache.ts
export default defineNitroPlugin(async (nitroApp) => {
await mkdir(cacheFolder, { recursive: true });

nitroApp.hooks.hook('request', async (event) => {
const { path } = event;

if (!path.startsWith('/_ipx/')) return;

const targetCacheFilePath = getCacheKey(path);
const exists = existsSync(targetCacheFilePath);

if (exists) {
const file = await readFile(targetCacheFilePath);
const res = new Response(file, {
status: 200,
headers: {
'X-Nuxt-Image-Cache': 'HIT',
},
});

await event.respondWith(res);
console.log('Image served from cache:', targetCacheFilePath);
return;
}
});

nitroApp.hooks.hook('afterResponse', async (event, response) => {
// save generated image file to disk, not important right now
});
});
3 replies
NNuxt
Created by Jelmer on 3/14/2023 in #❓・help
How to do Static Site Generation with no JS on the client side in Nuxt 3
Hi there! I would like to know if it's possible to use nuxt generate to create a static html version of my app, without any JS on the client side. Right now when I generate the app it will include JS to (I think) hydrate the client side JS over the generated html. I would like to generate just HTML and CSS. My content will be fetched from an API. So considering this nuxt example page:
<script setup>
// pages/index.vue
const posts = await $fetch("https://jsonplaceholder.typicode.com/posts");
</script>

<template>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</template>
<script setup>
// pages/index.vue
const posts = await $fetch("https://jsonplaceholder.typicode.com/posts");
</script>

<template>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</template>
I would like to generate this static HTML version:
<html>
<head>
...
<!-- 0 scripts injected here! -->
</head>
<body>
<ul>
<li>sunt aut facere repellat provident occaecati excepturi optio reprehenderit</li>
<li>qui est esse</li>
<li>ea molestias quasi exercitationem repellat qui ipsa sit aut</li>
<li>eum et est occaecati</li>
(...etc)
</ul>

<!-- 0 scripts injected here! -->
</body>
</html>
<html>
<head>
...
<!-- 0 scripts injected here! -->
</head>
<body>
<ul>
<li>sunt aut facere repellat provident occaecati excepturi optio reprehenderit</li>
<li>qui est esse</li>
<li>ea molestias quasi exercitationem repellat qui ipsa sit aut</li>
<li>eum et est occaecati</li>
(...etc)
</ul>

<!-- 0 scripts injected here! -->
</body>
</html>
Is this possible?
9 replies