vue3构建时缺少动态图像(通过内部.json内部图像提供)

huangapple go评论84阅读模式
英文:

vue3 dynamic img missing on build (internal img fed throught internal .json)

问题

I build myself a website with a vue3 project, I'm using a lots of components to be re-used by other pages so a lot of the content of these components is being fed throught a internal .json file inside my project. I've looked for a solution but sadly cant find anything thats suited for my project.
Having a lot of img i cannot afford to individually import them. My previous solution was to manually put them in the dist folder after the build and modify my path in my .json to fit correctly but i've switch from manual build (npm run build) to a workflow to better work with my hosting solution (Github Pages). And it seems that with that i cant access the build folder to manually put my img with that.

I'll provide the related script under here to help understand the situation :

  • first script (PageAccueil.vue)
<script setup>
    import AccueilSite from '@/components/AccueilSite/AccueilSite.vue'
</script>
<template> 
    <div class="accueil">
        <AccueilSite />
    </div>
</template>
  • second script (AccueilSite.vue)
<script setup>
    import VignetteCategorie from '@/components/AccueilSite/VignetteCategorie.vue'
    import categorieData from '@/assets/json/categories.json'
</script>
<template>
    <div class="accueil-site">
        <div class="accueil-top">
            <div class="wrapImg">
                <img src="@/assets/img/jpg/lacSup/69-71/69-71_00.jpg" alt="lac-sup-principal">
            </div>
            <div class="wrapInfo">
                <div class="info-container">
                    <h1>Pemana Inc.</h1>
                    <h3>Location de quai et de logement</h3>
                    <div class="wrapImg">
                        <img src="@/assets/img/svg/logo_pemana_light.svg" alt="logo-light-full">
                    </div>
                </div>
            </div>
        </div>
        <div class="listeVignetteCat" v-if="categorieData">
            <h2>Explorer nos locations</h2>
            <VignetteCategorie v-for="categorie in categorieData" :key="categorie.id"
                :objCat="categorie" 
            />
        </div>
    </div>
</template>
  • third script (VignetteCategorie.vue)
<script setup>
    const props = defineProps({
        objCat : null
    })
</script>
<template>
    <RouterLink class="vignetteCategorie" :to="props.objCat.link">
        <div class="wrapImg">
            <img v-if="props.objCat.img" :src="props.objCat.img" :alt="props.objCat.name">
            <img v-else src="@/assets/img/png/no-img.png" :alt="props.objCat.name">
        </div>
        <div class="wrapInfo">
            <span class="material-symbols-outlined" v-text="props.objCat.icon"></span>
            <p v-text="props.objCat.name"></p>
        </div>
    </RouterLink>
</template>
  • finally, the .json concerned (categorie.json)
[
  {
    "id": 0,
    "name": "Quai Marina Zool",
    "icon": "anchor",
    "link": "/marina",
    "img": "/assets/marina_3d_1000x.jpg"
  },
  {
    "id": 1,
    "name": "Logement Lac-Supérieur",
    "icon": "home",
    "link": "/lac-superieur",
    "img": "/assets/69-71_00.jpg"
  },
  {
    "id": 2,
    "name": "Logement Saint-Jérôme",
    "icon": "home",
    "link": "/saint-jerome",
    "img": "/assets/1003_00.jpg"
  },
  {
    "id": 3,
    "name": "Projet à venir",
    "icon": "map",
    "link": "/a-venir",
    "img": "/assets/proj_a_venir.png"
  }
]

So in the second script, upon building, i have no problem at all with the image because i am "directly" calling to them (script → img)
However, in the third script (VignetteCategorie.vue), the img link works locally (npm run dev) //with corrected path .json, but when i build it the concerned img get ignore since they arent directly calling to them (script → .json → img)
I am looking for a solution that could help me get these img in my build, as i said, i cant afford to manually import them individually in my script since im dealing with a lot of img with multiple .vue components.

Please help vue3构建时缺少动态图像(通过内部.json内部图像提供)

In case more research into my code are needed, here's the link to my github repo : https://github.com/Kebrouh/pemana

hemm, this is my first time using this, evrything is described in the previous case

英文:

I build myself a website with a vue3 project, I'm using a lots of components to be re-used by other pages so a lot of the content of these components is being fed throught a internal .json file inside my project. I've looked for a solution but sadly cant find anything thats suited for my project.
Having a lot of img i cannot afford to individually import them. My previous solution was to manually put them in the dist folder after the build and modify my path in my .json to fit correctly but i've switch from manual build (npm run build) to a workflow to better work with my hosting solution (Github Pages). And it seems that with that i cant access the build folder to manually put my img with that.

I'll provide the related script under here to help understand the situation :

  • first script (PageAccueil.vue)
&lt;script setup&gt;
    import AccueilSite from &#39;@/components/AccueilSite/AccueilSite.vue&#39;
&lt;/script&gt;
&lt;template&gt; 
    &lt;div class=&quot;accueil&quot;&gt;
        &lt;AccueilSite /&gt;
    &lt;/div&gt;
&lt;/template&gt;
  • second script (AccueilSite.vue)
&lt;script setup&gt;
    import VignetteCategorie from &#39;@/components/AccueilSite/VignetteCategorie.vue&#39;
    import categorieData from &#39;@/assets/json/categories.json&#39;
&lt;/script&gt;
&lt;template&gt;
    &lt;div class=&quot;accueil-site&quot;&gt;
        &lt;div class=&quot;accueil-top&quot;&gt;
            &lt;div class=&quot;wrapImg&quot;&gt;
                &lt;img src=&quot;@/assets/img/jpg/lacSup/69-71/69-71_00.jpg&quot; alt=&quot;lac-sup-principal&quot;&gt;
            &lt;/div&gt;
            &lt;div class=&quot;wrapInfo&quot;&gt;
                &lt;div class=&quot;info-container&quot;&gt;
                    &lt;h1&gt;Pemana Inc.&lt;/h1&gt;
                    &lt;h3&gt;Location de quai et de logement&lt;/h3&gt;
                    &lt;div class=&quot;wrapImg&quot;&gt;
                        &lt;img src=&quot;@/assets/img/svg/logo_pemana_light.svg&quot; alt=&quot;logo-light-full&quot;&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;listeVignetteCat&quot; v-if=&quot;categorieData&quot;&gt;
            &lt;h2&gt;Explorer nos locations&lt;/h2&gt;
            &lt;VignetteCategorie v-for=&quot;categorie in categorieData&quot; :key=&quot;categorie.id&quot;
                :objCat=&quot;categorie&quot; 
            /&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/template&gt;
  • third script (VignetteCategorie.vue)
&lt;script setup&gt;
    const props = defineProps({
        objCat : null
    })
&lt;/script&gt;
&lt;template&gt;
    &lt;RouterLink class=&quot;vignetteCategorie&quot; :to=&quot;props.objCat.link&quot;&gt;
        &lt;div class=&quot;wrapImg&quot;&gt;
            &lt;img v-if=&quot;props.objCat.img&quot; :src=&quot;props.objCat.img&quot; :alt=&quot;props.objCat.name&quot;&gt;
            &lt;img v-else src=&quot;@/assets/img/png/no-img.png&quot; :alt=&quot;props.objCat.name&quot;&gt;
        &lt;/div&gt;
        &lt;div class=&quot;wrapInfo&quot;&gt;
            &lt;span class=&quot;material-symbols-outlined&quot; v-text=&quot;props.objCat.icon&quot;&gt;&lt;/span&gt;
            &lt;p v-text=&quot;props.objCat.name&quot;&gt;&lt;/p&gt;
        &lt;/div&gt;
    &lt;/RouterLink&gt;
&lt;/template&gt;
  • finally, the .json concerned (categorie.json)
[
  {
    &quot;id&quot;: 0,
    &quot;name&quot;: &quot;Quai Marina Zool&quot;,
    &quot;icon&quot;: &quot;anchor&quot;,
    &quot;link&quot;: &quot;/marina&quot;,
    &quot;img&quot;: &quot;/assets/marina_3d_1000x.jpg&quot;
  },
  {
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Logement Lac-Sup&#233;rieur&quot;,
    &quot;icon&quot;: &quot;home&quot;,
    &quot;link&quot;: &quot;/lac-superieur&quot;,
    &quot;img&quot;: &quot;/assets/69-71_00.jpg&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;name&quot;: &quot;Logement Saint-J&#233;r&#244;me&quot;,
    &quot;icon&quot;: &quot;home&quot;,
    &quot;link&quot;: &quot;/saint-jerome&quot;,
    &quot;img&quot;: &quot;/assets/1003_00.jpg&quot;
  },
  {
    &quot;id&quot;: 3,
    &quot;name&quot;: &quot;Projet &#224; venir&quot;,
    &quot;icon&quot;: &quot;map&quot;,
    &quot;link&quot;: &quot;/a-venir&quot;,
    &quot;img&quot;: &quot;/assets/proj_a_venir.png&quot;
  }
]

So in the second script, upon building, i have no problem at all with the image because i am "directly" calling to them (script → img)
However, in the third script (VignetteCategorie.vue), the img link works locally (npm run dev) //with corrected path .json, but when i build it the concerned img get ignore since they arent directly calling to them (script → .json → img)
I am looking for a solution that could help me get these img in my build, as i said, i cant afford to manually import them individually in my script since im dealing with a lot of img with multiple .vue components.

Please help vue3构建时缺少动态图像(通过内部.json内部图像提供)

In case more research into my code are needed, here's the link to my github repo : https://github.com/Kebrouh/pemana

hemm, this is my first time using this, evrything is described in the previous case

答案1

得分: 0

当您构建Rollup更改您的资产URL时:

/assets/marina_3d_1000x.jpg => dist/assets/marina_3d_100x-234d5f.jpg

当您在导入或模板中直接使用它们时,转换会自动在源中进行,以与包中的URL匹配。

但是,当您尝试从JSON中使用文件路径时,不会进行任何转换,实际上Rollup对您的图像一无所知。所以基本上什么都不会发生...

要在构建中包含JSON图像,您应该导入它们。在您的情况下,图像名称相当随机。但让我们假设它们位于./assets/json文件夹中。

首先,将所有图像导入为URL,这些URL将在包中使用。这样,Rollup将所有图像打包到捆绑包中。您将获得一个对象映射,其中键是您的本地路径,值是将在捆绑包中使用的路径。然后,将本地路径替换为捆绑包中的路径:

https://vitejs.dev/guide/features.html#glob-import

import categorieData from '@/assets/json/categories.json';

const imagePaths = import.meta.glob('./assets/json/**/*.png', { eager: true, as: 'url' }); // 子文件夹也包括

for (const category of categoryData) {
  category.img = imagePaths['.' + category.img];
}

调试和调整以使其实际工作。可能需要一些路径转换。

英文:

When you build the Rollup changes your assets URLs:

/assets/marina_3d_1000x.jpg =&gt; dist/assets/marina_3d_100x-234d5f.jpg

When you use them directly when importing or in templates that conversion is done automatically in the source to match with URLs in the bundle.

But when you try to use file paths from a json, no conversion happen and actually Rollup does know nothing about your images at all. So basically nothing happens...

To include the json images in the build you should import them. In your case the image names are pretty random. But let's assume they are in the ./assets/json folder.

So first you import all images as URLs which will be used in the bundle. This way Rollup will pack all images in the bundle. You get an object map with keys as your local paths and values as paths that will be used in the bundle. Then replace your local paths with paths in the bundle:

https://vitejs.dev/guide/features.html#glob-import

import categorieData from &#39;@/assets/json/categories.json&#39;

const imagePaths = import.meta.glob(&#39;./assets/json/**/*.png&#39;, {eager: true, as: &#39;url&#39;}); // subfolders also

for(const category of categoryData){
  category.img = imagePaths[&#39;.&#39; + category.img];
}

Debug and tweak to make it actually work. There could be some paths transforms needed.

huangapple
  • 本文由 发表于 2023年7月11日 00:31:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76655689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定