[{"data":1,"prerenderedAt":428},["ShallowReactive",2],{"\u002Fpost\u002Fnuxt3-dynamic-images":3},{"id":4,"title":5,"body":6,"date":411,"description":17,"extension":412,"hidden":413,"image":414,"meta":415,"navigation":154,"path":416,"seo":417,"sitemap":418,"stem":419,"subtitle":420,"tags":421,"__hash__":427},"posts\u002Fpost\u002Fnuxt3-dynamic-images.md","Nuxt3 動態加載圖片（到底該放哪裡？）",{"type":7,"value":8,"toc":402},"minimark",[9,14,18,21,26,29,51,54,68,72,77,203,206,210,213,240,243,268,275,280,321,324,327,335,338,347,355,370,373,376,380,398],[10,11,13],"h1",{"id":12},"nuxt3-動態加載圖片別再搞錯-assets-跟-public","Nuxt3 動態加載圖片，別再搞錯 assets 跟 public！",[15,16,17],"p",{},"做 Nuxt3 專案你一定遇過這個問題：「我要根據 API 傳回來的檔名顯示圖檔，那圖片到底該放 assets 還是 public？」",[15,19,20],{},"老實說，這問題我自己也被搞過，網路上的說法一堆，還有很多超複雜的解釋。這篇就直接白話搞定，給你結論跟範例。",[22,23,25],"h2",{"id":24},"assets-跟-public-到底差在哪","assets 跟 public 到底差在哪？",[15,27,28],{},"先講結論：",[30,31,32,45],"ul",{},[33,34,35,44],"li",{},[36,37,38,39,43],"strong",{},"要用字串拼 ",[40,41,42],"code",{},"src"," 路徑？"," → 全部放 public",[33,46,47,50],{},[36,48,49],{},"要給 vite\u002Fwebpack 處理 hash？"," → 放 assets，但只能靜態 import，用變數就掰掰",[15,52,53],{},"簡單來說：",[30,55,56,62],{},[33,57,58,61],{},[40,59,60],{},"public"," = 用 URL 直接拿圖，怎麼拼都行",[33,63,64,67],{},[40,65,66],{},"assets"," = 只能靜態 import（vite\u002Fwebpack 會 hash 路徑），不能用字串拼",[22,69,71],{"id":70},"為什麼-public-比-assets-靈活","為什麼 public 比 assets 靈活？",[15,73,74,76],{},[40,75,60],{}," 下的東西打包時完全不會動，名字、路徑都不會被處理。所以你怎麼拼 URL 都能抓到圖（無論 dev\u002Fprod 都一樣）：",[78,79,84],"pre",{"className":80,"code":81,"language":82,"meta":83,"style":83},"language-vue shiki shiki-themes light-plus tokyo-night","\u003Ctemplate>\n  \u003Cimg :src=\"`\u002Fimages\u002Fproducts\u002F${imageName}.webp`\" alt=\"\">\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst imageName = 'product-001'\n\u003C\u002Fscript>\n","vue","",[40,85,86,102,139,149,156,169,194],{"__ignoreMap":83},[87,88,91,95,99],"span",{"class":89,"line":90},"line",1,[87,92,94],{"class":93},"sd4Bp","\u003C",[87,96,98],{"class":97},"s77fc","template",[87,100,101],{"class":93},">\n",[87,103,105,108,111,115,119,123,127,129,132,134,137],{"class":89,"line":104},2,[87,106,107],{"class":93},"  \u003C",[87,109,110],{"class":97},"img",[87,112,114],{"class":113},"sU3-j"," :src",[87,116,118],{"class":117},"s6v6z","=",[87,120,122],{"class":121},"s00W4","\"",[87,124,126],{"class":125},"sDr3-","`\u002Fimages\u002Fproducts\u002F${imageName}.webp`",[87,128,122],{"class":121},[87,130,131],{"class":113}," alt",[87,133,118],{"class":117},[87,135,136],{"class":121},"\"\"",[87,138,101],{"class":93},[87,140,142,145,147],{"class":89,"line":141},3,[87,143,144],{"class":93},"\u003C\u002F",[87,146,98],{"class":97},[87,148,101],{"class":93},[87,150,152],{"class":89,"line":151},4,[87,153,155],{"emptyLinePlaceholder":154},true,"\n",[87,157,159,161,164,167],{"class":89,"line":158},5,[87,160,94],{"class":93},[87,162,163],{"class":97},"script",[87,165,166],{"class":113}," setup",[87,168,101],{"class":93},[87,170,172,176,180,183,187,191],{"class":89,"line":171},6,[87,173,175],{"class":174},"sucPa","const",[87,177,179],{"class":178},"sq2Xa"," imageName",[87,181,182],{"class":117}," =",[87,184,186],{"class":185},"sq7Q2"," '",[87,188,190],{"class":189},"s58z3","product-001",[87,192,193],{"class":185},"'\n",[87,195,197,199,201],{"class":89,"line":196},7,[87,198,144],{"class":93},[87,200,163],{"class":97},[87,202,101],{"class":93},[15,204,205],{},"這做法超簡單，而且不用在意 Vite\u002FWebpack 會不會幫你 hash 路徑，反正就是長什麼名就給你什麼名。",[22,207,209],{"id":208},"assets-只能給靜態-import","assets 只能給靜態 import",[15,211,212],{},"如果你硬要用 assets 裡的圖，只能這樣：",[78,214,218],{"className":215,"code":216,"language":217,"meta":83,"style":83},"language-js shiki shiki-themes light-plus tokyo-night","import dog from '~\u002Fassets\u002Fimages\u002Fdog.png'\n","js",[40,219,220],{"__ignoreMap":83},[87,221,222,226,230,233,235,238],{"class":89,"line":90},[87,223,225],{"class":224},"swGrk","import",[87,227,229],{"class":228},"sTOFy"," dog",[87,231,232],{"class":224}," from",[87,234,186],{"class":185},[87,236,237],{"class":189},"~\u002Fassets\u002Fimages\u002Fdog.png",[87,239,193],{"class":185},[15,241,242],{},"或者在 component 直接：",[78,244,246],{"className":80,"code":245,"language":82,"meta":83,"style":83},"\u003Cimg src=\"~\u002Fassets\u002Fimages\u002Fdog.png\" \u002F>\n",[40,247,248],{"__ignoreMap":83},[87,249,250,252,254,257,259,261,263,265],{"class":89,"line":90},[87,251,94],{"class":93},[87,253,110],{"class":97},[87,255,256],{"class":113}," src",[87,258,118],{"class":117},[87,260,122],{"class":121},[87,262,237],{"class":125},[87,264,122],{"class":121},[87,266,267],{"class":93}," \u002F>\n",[15,269,270,271,274],{},"vite\u002Fwebpack 會自動幫你加 hash，路徑變成 ",[40,272,273],{},"\u002Fassets\u002Fdog.abcd1234.png","。",[15,276,277],{},[36,278,279],{},"但是！你不能這樣搞：",[78,281,283],{"className":215,"code":282,"language":217,"meta":83,"style":83},"const imgPath = `~\u002Fassets\u002Fimages\u002F${imgName}.png` \u002F\u002F 掰掰，這抓不到\n",[40,284,285],{"__ignoreMap":83},[87,286,287,289,292,294,297,300,304,308,311,314,317],{"class":89,"line":90},[87,288,175],{"class":174},[87,290,291],{"class":178}," imgPath",[87,293,182],{"class":117},[87,295,296],{"class":185}," `",[87,298,299],{"class":189},"~\u002Fassets\u002Fimages\u002F",[87,301,303],{"class":302},"sgi5Y","${",[87,305,307],{"class":306},"sJUHq","imgName",[87,309,310],{"class":302},"}",[87,312,313],{"class":189},".png",[87,315,316],{"class":185},"`",[87,318,320],{"class":319},"shM36"," \u002F\u002F 掰掰，這抓不到\n",[15,322,323],{},"因為 build 完根本沒這個檔名，webpack 不知道你要什麼。",[22,325,326],{"id":326},"選擇題",[30,328,329,332],{},[33,330,331],{},"想動態換圖？→ 放 public",[33,333,334],{},"圖片名不變、想被 hash 處理？→ 放 assets",[22,336,337],{"id":337},"常見問題",[15,339,340,343,346],{},[36,341,342],{},"Q: API 傳一堆檔名，怎麼顯示圖？",[344,345],"br",{},"\nA: 圖全部丟 public，直接拼 URL",[15,348,349,352,354],{},[36,350,351],{},"Q: 靜態圖只在 component 用？",[344,353],{},"\nA: assets 隨你，vite 會 hash，自然幫你優化",[15,356,357,360,362,363,366,367,369],{},[36,358,359],{},"Q: public 圖片路徑 dev\u002Fprod 會變嗎？",[344,361],{},"\nA: 不會。你看到 ",[40,364,365],{},"\u002Fimages\u002Ffoo.png"," 就是 ",[40,368,365],{},"，不用想太多",[22,371,372],{"id":372},"最後",[15,374,375],{},"遇到圖片路徑有鬼，十之八九就是 assets 跟 public 放錯了，檢查一下就對了。",[22,377,379],{"id":378},"ref","Ref",[30,381,382,391],{},[33,383,384],{},[385,386,390],"a",{"href":387,"rel":388},"https:\u002F\u002Fwww.lichter.io\u002Farticles\u002Fnuxt3-vue3-dynamic-images\u002F",[389],"nofollow","Vue 3: How to load dynamic images",[33,392,393],{},[385,394,397],{"href":395,"rel":396},"https:\u002F\u002Fclairechang.tw\u002F2023\u002F09\u002F12\u002Fnuxt3\u002Fnuxt-v3-assets-vs-public\u002F",[389],"Nuxt 3 深入靜態資源的使用 Public & Assets",[399,400,401],"style",{},"html pre.shiki code .swGrk, html code.shiki .swGrk{--shiki-default:#AF00DB;--shiki-dark:#7DCFFF}html pre.shiki code .sTOFy, html code.shiki .sTOFy{--shiki-default:#001080;--shiki-dark:#0DB9D7}html pre.shiki code .sq7Q2, html code.shiki .sq7Q2{--shiki-default:#A31515;--shiki-dark:#89DDFF}html pre.shiki code .s58z3, html code.shiki .s58z3{--shiki-default:#A31515;--shiki-dark:#9ECE6A}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sucPa, html code.shiki .sucPa{--shiki-default:#0000FF;--shiki-default-font-style:inherit;--shiki-dark:#9D7CD8;--shiki-dark-font-style:italic}html pre.shiki code .sq2Xa, html code.shiki .sq2Xa{--shiki-default:#0070C1;--shiki-dark:#BB9AF7}html pre.shiki code .s6v6z, html code.shiki .s6v6z{--shiki-default:#000000;--shiki-dark:#89DDFF}html pre.shiki code .sgi5Y, html code.shiki .sgi5Y{--shiki-default:#0000FF;--shiki-dark:#7DCFFF}html pre.shiki code .sJUHq, html code.shiki .sJUHq{--shiki-default:#001080;--shiki-dark:#C0CAF5}html pre.shiki code .shM36, html code.shiki .shM36{--shiki-default:#008000;--shiki-default-font-style:inherit;--shiki-dark:#51597D;--shiki-dark-font-style:italic}html pre.shiki code .sd4Bp, html code.shiki .sd4Bp{--shiki-default:#800000;--shiki-dark:#BA3C97}html pre.shiki code .s77fc, html code.shiki .s77fc{--shiki-default:#800000;--shiki-dark:#F7768E}html pre.shiki code .sU3-j, html code.shiki .sU3-j{--shiki-default:#E50000;--shiki-dark:#BB9AF7}html pre.shiki code .s00W4, html code.shiki .s00W4{--shiki-default:#0000FF;--shiki-dark:#89DDFF}html pre.shiki code .sDr3-, html code.shiki .sDr3-{--shiki-default:#0000FF;--shiki-dark:#9ECE6A}",{"title":83,"searchDepth":104,"depth":104,"links":403},[404,405,406,407,408,409,410],{"id":24,"depth":104,"text":25},{"id":70,"depth":104,"text":71},{"id":208,"depth":104,"text":209},{"id":326,"depth":104,"text":326},{"id":337,"depth":104,"text":337},{"id":372,"depth":104,"text":372},{"id":378,"depth":104,"text":379},"2025-07-01","md",false,"\u002Fimages\u002Fpost\u002Fnuxt3-dynamic-images\u002Fpost.webp",{},"\u002Fpost\u002Fnuxt3-dynamic-images",{"title":5,"description":17},{"loc":416},"post\u002Fnuxt3-dynamic-images","Nuxt3 動態加載圖片",[422,423,424,425,426],"nuxt3","dynamic-images","nuxt3-動態加載圖片","動態加載圖片","vite","ZA8XQ4BwGzfudf904HaXieBq87n1Oj06DChE6UJLDoQ",1791370767494]