Reputation: 563
Inside the /public/images
directory of my Nuxt 3 project, I have a number of images, which are spread out into multiple sub-directories. For a gallery page, I want to read all file paths so that I can render an img
tag for each one and don't have to hard-code them. Currently, I do this inside an API endpoint. The code for that looks like this:
import { readdir, stat } from "node:fs";
import { join } from "node:path";
async function read(path, callback) {
let images = [];
readdir(path, (err, files) => {
if (err) {
throw err;
}
let i = 0;
(function next() {
if (i === files.length) {
return callback(images);
}
const file = join(path, files[i++]);
stat(file, (err, stats) => {
if (err) {
throw err;
}
if (stats.isDirectory()) {
read(file, (value) => {
images = images.concat(value);
next();
});
} else {
images.push(file);
next();
}
});
})();
});
}
export default defineEventHandler(async (_event) => {
return await new Promise((resolve, reject) => {
try {
read("./public/images/blog", (value) => {
resolve(value.map((value) => value.substring(6)));
});
} catch (error) {
reject(error);
}
});
});
What I would like to do instead is create this array containing all image paths at build time. From my understanding, this could be achieved using lifecycle hooks. However, I don't understand the documentation for this part of the framework. Can somebody point me in the right direction?
Upvotes: 0
Views: 1158
Reputation: 1319
nuxt.config.ts
import { getImages } from './imageHandler';
export default defineNuxtConfig(async () => {
return {
runtimeConfig: {
public: {
images: await getImages()
}
}
}
})
MyComponent.vue
<script setup lang="ts">
let config = useRuntimeConfig();
let images = config.public.images;
</script>
<template>
<img v-for="img in images" :src="img" />
</template>
Note: If you use TypeScript the compiler will complain but the code should run. Use type any for the function to silence the compiler. There are no type declarations because this an undocumented deprecated feature that only exists for backwards compatibility with nuxt 2
Note 2: If you're on a nuxt 3 version that doesn't have this feature (either because it hasn't been added yet or because it has already been removed), you can rewrite your filesystem calls to their synchronous counterparts (fs.readdirSync etc.) and still achieve the same functionality
Note 3: Use runtimeConfig if you only need the data on the server. Use runtimeConfig.public if you need it on the client as well.
See: https://github.com/nuxt/framework/pull/1612 for more info about async function as nuxt.config
See: https://nuxt.com/docs/migration/runtime-config#runtime-config for more info about runtimeConfig
You can define a module and use the 'build:before' lifecycle hook to execute code at build time.
Read more about lifecycle hooks here: https://nuxt.com/docs/guide/going-further/hooks
See also: https://nuxt.com/docs/guide/going-further/modules
Although after you have obtained your array of images I'm not sure how you can reference that array from other parts of the code, but I hope this is enough to help you in the right direction.
modules/yourModule.ts
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup(options, nuxt) {
nuxt.hook('build:before', async ()=>{
// read contents of public and get images
let images = [];
// do something with images
})
}
})
nuxt.config.ts
import { getProjects } from "./data"
import yourModule from "./modules/yourModule"
export default defineNuxtConfig({
modules: [
yourModule
]
})
Upvotes: 1