framework icon indicating copy to clipboard operation
framework copied to clipboard

Image assets imported relatively in components are not processed properly

Open doomspec opened this issue 3 years ago • 28 comments
trafficstars

Environment

  • Operating System: Linux
  • Node Version: v14.18.1
  • Nuxt Version: 3.0.0-27386759.b449d0b
  • Package Manager: [email protected]
  • Bundler: Vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://codesandbox.io/s/prod-cdn-2g32p

Describe the bug

I am trying to put the image assets in the components path (next to the .vue component files) and try to use them by a relative path like <img src="./play.svg" />, the assets are not loaded properly in nuxi build, though they work well in nuxi dev.

Additional context

No response

Logs

No response

doomspec avatar Jan 26 '22 16:01 doomspec

Try putting this in your nuxt.config:

//...  
  vite: {
    build: { assetsInlineLimit: 0 },
   },

StevenJPx2 avatar Jan 27 '22 04:01 StevenJPx2

Try putting this in your nuxt.config:

//...  
  vite: {
    build: { assetsInlineLimit: 0 },
   },

I updated the sandbox and added this config. But it still doesn't work.

doomspec avatar Jan 28 '22 00:01 doomspec

The same goes for images that are inside the assets folder. I have the structure ./assets/img/test-img.jpg and try to use it inside a picture tag with srcset="~/assets/img/test-img.jpg" which doesn't work when running npm run dev. Using srcset="assets/img/test-img.jpg" or srcset="/assets/img/test-img.jpg" works. I created a sample project to check and reproduce this issue. I am using NodeJs version 14.16.1.

Sample Project: https://github.com/Der-Alex/image-asset-example

Der-Alex avatar Feb 03 '22 09:02 Der-Alex

Hmm, I just checked this out in my own project. Yes, this is a troubling issue. Don't know why this is marked as a minor bug if it doesn't have a workaround.

Edit: made a workaround. Not good if you want component-level interactivity, though. You might have to use render functions at that point.

Component.vue

<template>
...
<slot name="img"/>
...
</template>

Page.vue

<template>
...

<component>
  <template #img>
    <img src="/* put asset here */" /* ... */ />
  </template>
</component>

// all other functionality should be directly be put in the page itself
// styling should be in the page stylesheet, I tried putting scoped CSS for the image
// in the component, but that's not working
...
</template>

StevenJPx2 avatar Feb 04 '22 13:02 StevenJPx2

@Der-Alex have you tried using a larger image or adding this config?

vite: {
  build: { assetsInlineLimit: 0 },
},

Because when I did in your example none of the methods worked with npm run start

baronkoko avatar Feb 16 '22 09:02 baronkoko

@baronkoko See: https://github.com/nuxt/framework/issues/2939#issuecomment-1022825138

StevenJPx2 avatar Feb 16 '22 09:02 StevenJPx2

@StevenJPx2 thank you for the quick response.

I set this config and tried to import assets in two ways /assets/... and assets/.... Both of these methods work great with npm run dev. But none works with npm run build npm run start. Сan you take a look, please? Maybe I made a mistake somewhere, but in another project, I have the same thing.

Nuxt CLI v3.0.0-27415326.3c563fa

Reproduction: https://github.com/baronkoko/nuxt3-assets

baronkoko avatar Feb 16 '22 10:02 baronkoko

As far as I can see in my case this is a problem with loading assets via the srcset attribute. Assets are loaded fine via the src attribute with @/ alias on both dev and prod versions.

Can anyone help with the assets loading via the srset attribute, please?

baronkoko avatar Feb 18 '22 08:02 baronkoko

@baronkoko As it stands, you can't use srcset or add an image path into a component, because it won't render in build. For the component fix, I have given a workaround, srcset would probably need you to do a JS workaround by detecting screen-size and changing the image that way.

StevenJPx2 avatar Feb 18 '22 09:02 StevenJPx2

stands

<img> src attribute works great, it doesn't need a workaround. Or maybe I misunderstood you in this regard. The only problem with srcset. It does not work with npm run build npm run start. The path is generated, even with a hash, but there are no assets in the _nuxt folder. Screenshot 2022-02-18 at 11 40 56

baronkoko avatar Feb 18 '22 09:02 baronkoko

@baronkoko Yeah, I mentioned how to work around srcset not working by using src alone.

StevenJPx2 avatar Feb 18 '22 11:02 StevenJPx2

@StevenJPx2 got it, thank you. Will this srset problem be fixed or do you not have such information?

baronkoko avatar Feb 18 '22 12:02 baronkoko

No idea. I hope it gets fixed soon. @danielroe?

StevenJPx2 avatar Feb 21 '22 17:02 StevenJPx2

When is this getting resolved? This might have to do with Vue-loader, maybe?

StevenJPx2 avatar Mar 05 '22 08:03 StevenJPx2

Okay, so this is a Vite issue. I had to move away from using Nuxt 3 to Vitesse to see what the incompatibilities are and this props up there as well.

This solved the issue for me.

Essentially, you have to import the image as a module of sorts, line this:

<script setup>
import imgSrcWithAlias from '@/assets/icon-1.svg'
</script>

<template>
  <component-a :img-src="imgSrcWithAlias" />
</template>

And this works in Vitesse. @baronkoko I don't know if this fixes your srcset issue but I think this fixes @doomspec issue.

StevenJPx2 avatar Apr 02 '22 05:04 StevenJPx2

@StevenJPx2 this will mark all images as prefetch to read them on page load. don't do this if you are using responsive images for various resolutions. Then they will be all loaded at the beginning.

hoomb avatar Apr 02 '22 06:04 hoomb

@hoomb I wasn't aware of that. Either way, this looks to be a Vite issue, right?

StevenJPx2 avatar Apr 02 '22 07:04 StevenJPx2

@StevenJPx2 yes. It is a Issue with Vite

This works for me:

  <img src="@/assets/images/myimage.jpg" alt="my image">

And regarding to the Problem with responsive images and srcset, this is the solution which I'm using till there comes a fix from Vite

<style lang="scss" scoped>
@mixin bg-image($img) {
  background: url(~/assets/images/#{$img}_sm.jpg) no-repeat center center;
  background-size: cover;

  @media (min-width: 720px) {
    background: url(~/assets/images/#{$img}_md.jpg) no-repeat center center;
    background-size: cover;
  }

  @media (min-width: 1024px) {
    background: url(~/assets/images/#{$img}_lg.jpg) no-repeat center center;
    background-size: cover;
  }

  @media (min-width: 1920px) {
    background: url(~/assets/images/#{$img}_xl.jpg) no-repeat center center;
    background-size: cover;
  }
}

.slide-image {
  width: 100%;
  height: 100%;

  &.slide-0 {
    @include bg-image(image1);
  }

  &.slide-1 {
    @include bg-image(image2);
  }
}
</style>

hoomb avatar Apr 02 '22 12:04 hoomb

@hoomb Problem is not with adding the image source directly to an image element. The problem is with passing the image path as a prop to a component which then loads it into an image element. Vite seems to not resolve paths which do not load directly into an img[src].

StevenJPx2 avatar Apr 02 '22 13:04 StevenJPx2

@StevenJPx2 @hoomb Thank you both. I tried srcset in Vite Vue and there it works fine with the relative path. I updated my example of using srcset in the Nuxt 3 (https://github.com/baronkoko/nuxt3-assets) using the relative path, but unfortunately, it also only works with npm run dev, but not with npm run build npm run start. As I noticed, with npm run build npm run start Nuxt 3 does not create these files in the .output/public/_nuxt folder, although the paths are correct and a hash is added. Screenshot 2022-04-04 at 10 26 06

baronkoko avatar Apr 04 '22 07:04 baronkoko

@baronkoko It will work with bare Vite Vue because it is processing the page as an SPA. Everything rendered will be on the client side. So, Vitesse uses SSG which prerender items on the page and Nuxt uses both SSR and SSG. This is what causes the build issues.

StevenJPx2 avatar Apr 04 '22 07:04 StevenJPx2

@StevenJPx2 so, since we know what the problem is, we only have to wait until it is fixed, right?

baronkoko avatar Apr 04 '22 07:04 baronkoko

I looked more into the problem.

  • @vue/compiler-sfc allows to handle srcset via transformAssetUrls option, and has some defaults link
  • vite is using that option to transform source#srcset link
  • In nuxt found 2 places where transformAssetUrls is used, and no srcset there link1, link2

unrevised6419 avatar Apr 27 '22 08:04 unrevised6419

I went into my node_modules and found this code and added there srcset and it works fine. 🤔

ps: I've used patch-package to patch the lib

unrevised6419 avatar Apr 27 '22 09:04 unrevised6419

I looked more into the problem.

  • @vue/compiler-sfc allows to handle srcset via transformAssetUrls option, and has some defaults link

  • vite is using that option to transform source#srcset link

  • In nuxt found 2 places where transformAssetUrls is used, and no srcset there link1, link2

Can you check for any components not loading any image sources in the build for SSR AND SSG?

StevenJPx2 avatar Apr 27 '22 12:04 StevenJPx2

Any updates on this one?

baronkoko avatar Jun 20 '22 09:06 baronkoko

Same,it seems these image assets are not packed by nuxt. All image tags are still using the relative path.

Block81838 avatar Aug 08 '22 20:08 Block81838

There is a possible way via importing the image, and then bind the img src prop with imported image.

Block81838 avatar Aug 09 '22 01:08 Block81838

There is a possible way via importing the image, and then bind the img src prop with imported image.

Yes, we did discuss that above. But @danielroe, is there any movement on this?

StevenJPx2 avatar Aug 18 '22 04:08 StevenJPx2

I can't reproduce this now on RC8 - I believe the Vite 2 -> 3 upgrade has resolved this issue. If not, please provide a reproduction and I'll look into it.

danielroe avatar Aug 18 '22 07:08 danielroe