images resize avec sharp
This commit is contained in:
		| @@ -3,9 +3,9 @@ | |||||||
|         <article v-for="content in contents" :key="content.id"> |         <article v-for="content in contents" :key="content.id"> | ||||||
|             <div> |             <div> | ||||||
|                 <img |                 <img | ||||||
|                     :src="`/api/assets/${content.image ? content.image : content.shop_image}.webp`" |                     :src="`/small/${content.image ? content.image : content.shop_image}.webp`" | ||||||
|                     :alt="content.titre" |                     :alt="content.titre" | ||||||
|                     @click="displaySlider(content.id)"  |                     @click="displaySlider(content.id)" | ||||||
|                 /> |                 /> | ||||||
|             </div> |             </div> | ||||||
|             <div> |             <div> | ||||||
| @@ -28,7 +28,7 @@ | |||||||
|             <swiper-slide v-for="content in contents" :key="content.id"> |             <swiper-slide v-for="content in contents" :key="content.id"> | ||||||
|                 <div class="swiper-zoom-container"> |                 <div class="swiper-zoom-container"> | ||||||
|                     <img |                     <img | ||||||
|                         :src="`/api/assets/${content.image ? content.image : content.shop_image}.webp`" |                         :src="`/large/${content.image ? content.image : content.shop_image}.webp`" | ||||||
|                         :alt="content.titre" |                         :alt="content.titre" | ||||||
|                     /> |                     /> | ||||||
|                 </div> |                 </div> | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								nuxt.config.ts
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								nuxt.config.ts
									
									
									
									
									
								
							| @@ -2,15 +2,15 @@ | |||||||
| // https://github.com/codepie-io/nuxt3-dynamic-routes/blob/main/nuxt.config.ts | // https://github.com/codepie-io/nuxt3-dynamic-routes/blob/main/nuxt.config.ts | ||||||
| // + ssg homemade caching to not retrieve all the files each generation | // + ssg homemade caching to not retrieve all the files each generation | ||||||
|  |  | ||||||
| import { createDirectus, staticToken, rest, readFiles } from '@directus/sdk'; | // import { createDirectus, staticToken, rest, readFiles } from '@directus/sdk'; | ||||||
| import fs from 'fs'; |  | ||||||
| import path from 'path'; | import { crawlImages } from './ssg_hooks/crawlImages.js' | ||||||
| import { promisify } from 'util'; | import { cacheImages } from './ssg_hooks/cacheImages.js' | ||||||
|  |  | ||||||
| export default defineNuxtConfig({ | export default defineNuxtConfig({ | ||||||
|   devtools: { enabled: true }, |   devtools: { enabled: true }, | ||||||
|   modules: [ |   modules: [ | ||||||
|     '@nuxtjs/seo' |     '@nuxtjs/seo', | ||||||
|   ], |   ], | ||||||
|   runtimeConfig: { |   runtimeConfig: { | ||||||
|     apiURL: process.env.DIRECTUS_URL, |     apiURL: process.env.DIRECTUS_URL, | ||||||
| @@ -19,100 +19,18 @@ export default defineNuxtConfig({ | |||||||
|   nitro: { |   nitro: { | ||||||
|     hooks: { |     hooks: { | ||||||
|       async 'prerender:routes'(routes) { |       async 'prerender:routes'(routes) { | ||||||
|          |         await crawlImages(routes); | ||||||
|         const client = createDirectus(process.env.DIRECTUS_URL) |  | ||||||
|           .with(staticToken(process.env.DIRECTUS_API_TOKEN)) |  | ||||||
|           .with(rest()); |  | ||||||
|  |  | ||||||
|         const directusFiles = await client.request( |  | ||||||
|           readFiles({ |  | ||||||
|             query: { |  | ||||||
|               filter: { |  | ||||||
|                 type: { |  | ||||||
|                   _eq: 'image', |  | ||||||
|                 }, |  | ||||||
|               }, |  | ||||||
|             }, |  | ||||||
|           }) |  | ||||||
|         ); |  | ||||||
|  |  | ||||||
|         for (let image of directusFiles) { |  | ||||||
|           const fileExists = async (filePath) => !!(await fs.promises.access(filePath, fs.constants.F_OK).then(() => true).catch(() => false)); |  | ||||||
|  |  | ||||||
|           const filePath = `./public/api/assets/${image.id}.webp`; |  | ||||||
|           fileExists(filePath) |  | ||||||
|               .then(exists => { |  | ||||||
|                   if (!exists) { |  | ||||||
|                     routes.add(`/api/assets/${image.id}.webp`); |  | ||||||
|                   } |  | ||||||
|               }) |  | ||||||
|               .catch(error => console.error('Error:', error)); |  | ||||||
|         } |  | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|     prerender: { |     prerender: { | ||||||
|       routes: [ |       routes: [ | ||||||
|         '/api/items/global' |         '/api/items/global', | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|   hooks: { |   hooks: { | ||||||
|     'nitro:build:public-assets': () => { |     'nitro:build:public-assets': async () => { | ||||||
|       if (!fs.existsSync('./public/api/assets')) fs.mkdirSync('./public/api/assets', { recursive: true }); |       await cacheImages(); | ||||||
|  |  | ||||||
|       const readdir = promisify(fs.readdir); |  | ||||||
|       const stat = promisify(fs.stat); |  | ||||||
|       const copyFile = promisify(fs.copyFile); |  | ||||||
|  |  | ||||||
|       async function directoryExists(directoryPath) { |  | ||||||
|         try { |  | ||||||
|             const stats = await fs.promises.stat(directoryPath); |  | ||||||
|             return stats.isDirectory(); |  | ||||||
|         } catch (error) { |  | ||||||
|             if (error.code === 'ENOENT') { |  | ||||||
|                 return false; |  | ||||||
|             } else { |  | ||||||
|                 throw error; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       async function copyFilesIfNotExist(sourceFolder, destinationFolder) { |  | ||||||
|         try { |  | ||||||
|           const exists = await directoryExists(sourceFolder); |  | ||||||
|           if (!exists) { |  | ||||||
|               console.log(`Source folder '${sourceFolder}' does not exist.`); |  | ||||||
|               return; |  | ||||||
|           } |  | ||||||
|            |  | ||||||
|           const files = await readdir(sourceFolder); |  | ||||||
|           for (const file of files) { |  | ||||||
|               const sourceFilePath = path.join(sourceFolder, file); |  | ||||||
|               const destinationFilePath = path.join(destinationFolder, file); |  | ||||||
|               const sourceFileStat = await stat(sourceFilePath); |  | ||||||
|    |  | ||||||
|               if (sourceFileStat.isFile()) { |  | ||||||
|                   try { |  | ||||||
|                       await stat(destinationFilePath); |  | ||||||
|                   } catch (error) { |  | ||||||
|                       if (error.code === 'ENOENT') { |  | ||||||
|                           await copyFile(sourceFilePath, destinationFilePath); |  | ||||||
|                           console.log(`Copied '${file}' to '${destinationFolder}'.`); |  | ||||||
|                       } else { |  | ||||||
|                           throw error; |  | ||||||
|                       } |  | ||||||
|                   } |  | ||||||
|               } |  | ||||||
|           } |  | ||||||
|           console.log('Files copied successfully.'); |  | ||||||
|         } catch (error) { |  | ||||||
|             console.error('Error:', error); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       const sourceFolder = './.output/public/api/assets';       |  | ||||||
|       const destinationFolder = './public/api/assets'; |  | ||||||
|       copyFilesIfNotExist(sourceFolder, destinationFolder); |  | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   app: { |   app: { | ||||||
| @@ -123,5 +41,5 @@ export default defineNuxtConfig({ | |||||||
|     defaultLocale: 'fr', |     defaultLocale: 'fr', | ||||||
|     name: 'Mahée Auffret', |     name: 'Mahée Auffret', | ||||||
|     description: 'Portfolio de l\'artiste-peintre basée à Rennes Mahée Auffret' |     description: 'Portfolio de l\'artiste-peintre basée à Rennes Mahée Auffret' | ||||||
|   } |   }, | ||||||
| }) | }) | ||||||
							
								
								
									
										6186
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6186
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -11,15 +11,14 @@ | |||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@directus/sdk": "^15.1.0", |     "@directus/sdk": "^15.1.0", | ||||||
|     "@nuxt/image": "^1.3.0", |     "sharp": "^0.33.3", | ||||||
|     "nuxt": "^3.10.1", |  | ||||||
|     "nuxt-directus": "^5.6.0", |  | ||||||
|     "swiper": "^11.0.6", |     "swiper": "^11.0.6", | ||||||
|     "vue": "^3.4.15", |     "vue": "^3.4.15", | ||||||
|     "vue-router": "^4.2.5" |     "vue-router": "^4.2.5" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@nuxtjs/seo": "^2.0.0-rc.8", |     "@nuxtjs/seo": "^2.0.0-rc.8", | ||||||
|  |     "nuxt": "^3.11.2", | ||||||
|     "sass": "^1.71.0" |     "sass": "^1.71.0" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|             /> |             /> | ||||||
|         </div> |         </div> | ||||||
|         <div> |         <div> | ||||||
|             <p>{{ globalData.contact_texte }}</p> |             <p>{{ globalData.contact_text }}</p> | ||||||
|             <a :href="'mailto:' + globalData.email">{{ globalData.email }}</a> |             <a :href="'mailto:' + globalData.email">{{ globalData.email }}</a> | ||||||
|         </div> |         </div> | ||||||
|     </main> |     </main> | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								ssg_hooks/cacheImages.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								ssg_hooks/cacheImages.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | import fs from 'fs'; | ||||||
|  | import path from 'path'; | ||||||
|  | import { promisify } from 'util'; | ||||||
|  |  | ||||||
|  | import { resizeImages } from '../ssg_hooks/resizeImages.js' | ||||||
|  |  | ||||||
|  | export async function cacheImages() { | ||||||
|  |     const sourceFolder = './.output/public/api/assets';       | ||||||
|  |     const destinationFolder = './public/api/assets'; | ||||||
|  |  | ||||||
|  |     if (!fs.existsSync(destinationFolder)) fs.mkdirSync(destinationFolder, { recursive: true }); | ||||||
|  |  | ||||||
|  |     const readdir = promisify(fs.readdir); | ||||||
|  |     const stat = promisify(fs.stat); | ||||||
|  |     const copyFile = promisify(fs.copyFile); | ||||||
|  |  | ||||||
|  |     async function directoryExists(directoryPath) { | ||||||
|  |         try { | ||||||
|  |             const stats = await fs.promises.stat(directoryPath); | ||||||
|  |             return stats.isDirectory(); | ||||||
|  |         } catch (error) { | ||||||
|  |             if (error.code === 'ENOENT') { | ||||||
|  |                 return false; | ||||||
|  |             } else { | ||||||
|  |                 throw error; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async function copyFilesIfNotExist(sourceFolder, destinationFolder) { | ||||||
|  |         try { | ||||||
|  |             const exists = await directoryExists(sourceFolder); | ||||||
|  |             if (!exists) { | ||||||
|  |                 console.log(`Source folder '${sourceFolder}' does not exist.`); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             const files = await readdir(sourceFolder); | ||||||
|  |             for (const file of files) { | ||||||
|  |                 const sourceFilePath = path.join(sourceFolder, file); | ||||||
|  |                 const destinationFilePath = path.join(destinationFolder, file); | ||||||
|  |                 const sourceFileStat = await stat(sourceFilePath); | ||||||
|  |  | ||||||
|  |                 if (sourceFileStat.isFile()) { | ||||||
|  |                     try { | ||||||
|  |                         await stat(destinationFilePath); | ||||||
|  |                     } catch (error) { | ||||||
|  |                         if (error.code === 'ENOENT') { | ||||||
|  |                             await copyFile(sourceFilePath, destinationFilePath); | ||||||
|  |                             console.log(`Copied '${file}' to '${destinationFolder}'.`); | ||||||
|  |                         } else { | ||||||
|  |                             throw error; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             console.log('Files copied successfully.'); | ||||||
|  |  | ||||||
|  |             console.log('Start images resizing.'); | ||||||
|  |               | ||||||
|  |             const imageSizes = [ | ||||||
|  |                 { small: 750 }, | ||||||
|  |                 { large: 1920 }, | ||||||
|  |             ]; | ||||||
|  |  | ||||||
|  |             await resizeImages(imageSizes); | ||||||
|  |              | ||||||
|  |         } catch (error) { | ||||||
|  |             console.error('Error:', error); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     copyFilesIfNotExist(sourceFolder, destinationFolder); | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								ssg_hooks/crawlImages.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ssg_hooks/crawlImages.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | import { createDirectus, staticToken, rest, readFiles } from '@directus/sdk'; | ||||||
|  | import fs from 'fs'; | ||||||
|  |  | ||||||
|  | export async function crawlImages(routes) { | ||||||
|  |     const client = createDirectus(process.env.DIRECTUS_URL) | ||||||
|  |     .with(staticToken(process.env.DIRECTUS_API_TOKEN)) | ||||||
|  |     .with(rest()); | ||||||
|  |      | ||||||
|  |     const directusFiles = await client.request( | ||||||
|  |         readFiles({ | ||||||
|  |             query: { | ||||||
|  |                 filter: { | ||||||
|  |                     type: { | ||||||
|  |                         _eq: 'image/', | ||||||
|  |                     }, | ||||||
|  |                 }, | ||||||
|  |             }, | ||||||
|  |         }) | ||||||
|  |     ); | ||||||
|  |      | ||||||
|  |     for (let image of directusFiles) { | ||||||
|  |         if (image.type != "image/heic") { | ||||||
|  |             const fileExists = async (filePath) => !!(await fs.promises.access(filePath, fs.constants.F_OK).then(() => true).catch(() => false)); | ||||||
|  |              | ||||||
|  |             const filePath = `./public/api/assets/${image.id}.webp`; | ||||||
|  |             fileExists(filePath) | ||||||
|  |             .then(exists => { | ||||||
|  |                 if (!exists) { | ||||||
|  |                     routes.add(`/api/assets/${image.id}.webp`); | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |             .catch(error => console.error('Error:', error)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								ssg_hooks/resizeImages.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ssg_hooks/resizeImages.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | import fs from 'fs'; | ||||||
|  | import sharp from 'sharp'; | ||||||
|  |  | ||||||
|  | export async function resizeImages(sizes) { | ||||||
|  |     const sourceFolder = './public/api/assets'; | ||||||
|  |     const outputFolder = './.output/public'; | ||||||
|  |  | ||||||
|  |     for (const size of sizes) { | ||||||
|  |         const key = Object.keys(size)[0]; | ||||||
|  |         const sizeFolder = `${outputFolder}/${key}`; | ||||||
|  |         if (!fs.existsSync(sizeFolder)) { | ||||||
|  |             fs.mkdirSync(sizeFolder, { recursive: true }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const files = fs.readdirSync(sourceFolder); | ||||||
|  |  | ||||||
|  |     for (const file of files) { | ||||||
|  |         const filePath = `${sourceFolder}/${file}`; | ||||||
|  |  | ||||||
|  |         const image = sharp(filePath); | ||||||
|  |  | ||||||
|  |         for (const size of sizes) { | ||||||
|  |             const key = Object.keys(size)[0]; | ||||||
|  |             const sizeFolder = `${outputFolder}/${key}`; | ||||||
|  |             const width = parseInt(size[key]); | ||||||
|  |  | ||||||
|  |             await image.clone().resize({ width }).toFile(`${sizeFolder}/${file}`); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // fs.rmSync('./.output/public/api/assets', { recursive: true, force: true }); | ||||||
|  |  | ||||||
|  |     console.log('Images resized and saved successfully.'); | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Valentin
					Valentin