Skip to content
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

Images inside <template [tag]> are not generated during nuxt generate, but work in development mode #1608

Open
w33bvGL opened this issue Nov 22, 2024 · 6 comments

Comments

@w33bvGL
Copy link

w33bvGL commented Nov 22, 2024

I have encountered a problem with the @nuxt/image module when using it inside a <template> tag. Images are not generated correctly when running nuxt generate, although they work fine in development mode ( nuxt dev ).

<UPopover :popper="{ placement: 'bottom-end' }">
   <UButton icon="bi:globe-americas"/>
  
    <template #panel>
      <NuxtImg
        src="/img/example.webp"
        width="25"
        format="webp"
        densities="x1 x2"
        />
  </template>
</UPopover>

When running nuxt dev - the image will be displayed correctly.
When I run nuxt generate and try to open the page, the image is not generated and the browser shows a 404 error http://localhost:3000/_ipx/f_webp/img/example.webp

<template #panel>

Expected behavior: The image should be generated and available during static generation, similar to how it works in development mode.

The image is not generated during static site generation and the page shows a 404 error when trying to load the image. However, the image works fine when running nuxt dev.

package.json

 "dependencies": {
 "@nuxt/ui": "^2.19.2",
 "@nuxtjs/i18n": "^9.0.0",
 "axios": "^1.7.7",
 "lodash": "^4.17.21",
 "nuxt": "^3.14.159",
 "nuxt-zod-i18n": "^1.10.0",
 "vue": "latest",
 "vue-router": "latest",
 "zod": "^3.23.8"
 },
 "devDependencies": {
 "@nuxt/image": "^1.8.1",
 "nuxt-aos": "^1.2.5",
 "nuxt-swiper": "^2.0.0",
 "sass-embedded": "^1.81.0"
}

Additional information:
This issue seems to be related specifically to the use of NuxtImg inside a tag with a named slot ( #panel in this case).

The images work fine in development mode, but are not generated during static build.

I have verified that the images are correctly placed.

When I remove the slot ( without #panel), the image is generated correctly during static build. But adding #panel or any other gives an error.

@w33bvGL w33bvGL changed the title Изображения внутри <template [tag]>не генерируются во время nuxt generate, но работают в режиме разработки Images inside <template [tag]> are not generated during nuxt generate, but work in NuxtImg NuxtUI development mode Nov 22, 2024
@w33bvGL w33bvGL changed the title Images inside <template [tag]> are not generated during nuxt generate, but work in NuxtImg NuxtUI development mode Images inside <template [tag]> are not generated during nuxt generate, but work in development mode Nov 22, 2024
@RodrigoSpinelli
Copy link

Did you manage to solve the issue?

@w33bvGL
Copy link
Author

w33bvGL commented Dec 9, 2024

Did you manage to solve the issue?

no (

@a1mersnow
Copy link

a1mersnow commented Dec 30, 2024

Note

Please see here for a better solution

I wrote a utility to manually collect all possible images:

interface ImageOptions {
  width: number
  height: number
  sizes?: string
}

export function ensureGenImages(urls: string[], opts?: ImageOptions) {
  if (!import.meta.server)
    return
  const img = useImage()
  const { width, height, sizes } = opts || {}
  urls.forEach((url) => {
    if (opts) {
      const srcset = img.getSizes(url, { modifiers: { width, height }, sizes })
      // we don't need this in deed, see another comment below
      extractUrls(srcset.srcset).forEach((url) => {
        $fetch(url)
      })
    }
    else {
      // we don't need the `$fetch` call in deed, see another comment below
      $fetch(img(url))
    }
  })
}

function extractUrls(srcset: string) {
  return srcset.split(',').map(s => s.trim().split(' ')[0])
}

The fetch will cause ipx to generate images...

The not graceful place is that you need to extract the imageOptions(width,height,sizes) or double writing code. But I didn't find a way to avoid this...

And you need to call this utility function at somewhere always render.

@RodrigoSpinelli
Copy link

It's already a solution, thanks for sharing.

@a1mersnow
Copy link

a1mersnow commented Dec 31, 2024

I found that practically the $fetch call has no effect. What make this work are img call and img.getSizes call, so a more simple code:

interface ImageOptions {
  width: number
  height: number
  sizes?: string
}

export function ensureGenImages(urls: string[], opts?: ImageOptions) {
  if (!import.meta.server || !import.meta.prerender)
    return
  const img = useImage()
  const { width, height, sizes } = opts || {}
  urls.forEach((url) => {
    if (opts) {
      img.getSizes(url, { modifiers: { width, height }, sizes })
    }
    else {
      img(url)
    }
  })
}

@w33bvGL
Copy link
Author

w33bvGL commented Jan 1, 2025

It's already a solution, thanks for sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants