Remix V2中基于coinSymbol动态导入本地.png图片失败的问题
问题:Remix V2中如何根据变量动态导入本地PNG图片?
在Remix V2开发React项目时,尝试根据coinSymbol变量值动态导入本地目录中的.png图片,使用import()函数配合多种相对/绝对路径均无法生效,报错提示无法获取动态导入的模块,官方文档也未明确说明非ES模块公共资源的处理方式。请问是否可以基于coinSymbol值动态导入这些图片?
以下代码尝试根据组件接收的coinSymbol访问30x30文件夹内的图片
动态导入图标的函数代码:
function useImportIcon(coinSymbol: string): [IconSrc, ImportError] { const [iconSrc, setIconSrc] = useState<IconSrc>(null); const [error, setError] = useState<ImportError>(null); useEffect(() => { import(`../../../assets/images/coins/30x30/${coinSymbol}.png`) // or `~/assets/....` .then((iconModule) => setIconSrc(iconModule.default)) .catch((error: Error) => { console.error(`Failed to load icon for ${coinSymbol}:`, error); setError(error); }); }, [coinSymbol]); return [iconSrc, error]; }
报错信息:
Failed to load icon for BTC: TypeError: Failed to fetch dynamically imported module: http://localhost:3000/assets/images/coins/30x30/BTC.png
文件夹结构:
. └── assets └── images └── coins └── 30x30 ├── 1INCH.png ├── AAVE.png ├── ACA.png ├── ACH.png ├── ACM.png ├── ADA.png ├── ADX.png ├── BTC.png ├── coins-big.css ├── coins-big@2x.png ├── coins-small.css └── coins-small@2x.png
已尝试的路径:
await import(`~/assets/images/coins/30x30/${coinSymbol}.png`) await import(`/assets/images/coins/30x30/${coinSymbol}.png`) await import(`assets/images/coins/30x30/${coinSymbol}.png`)
解决方案
方法一:利用Remix公共资源目录(推荐)
Remix默认将public目录下的资源直接映射到服务器根路径,无需通过import()处理静态图片:
- 调整资源位置:将
assets/images/coins整个目录移动到项目根目录的public文件夹下,最终结构为:
. └── public └── images └── coins └── 30x30 ├── BTC.png └── ...其他图片
- 修改图标加载逻辑:直接构造资源URL,无需
import(),还可添加图片存在性验证:
function useImportIcon(coinSymbol: string): [IconSrc, ImportError] { const [iconSrc, setIconSrc] = useState<IconSrc>(null); const [error, setError] = useState<ImportError>(null); useEffect(() => { const iconUrl = `/images/coins/30x30/${coinSymbol}.png`; const img = new Image(); img.onload = () => setIconSrc(iconUrl); img.onerror = (err) => { console.error(`Failed to load icon for ${coinSymbol}:`, err); setError(err as Error); }; img.src = iconUrl; }, [coinSymbol]); return [iconSrc, error]; }
方法二:通过Vite Glob导入(保留assets目录)
如果需要将图片留在源码目录的assets中,可利用Remix V2默认使用的Vite的import.meta.glob功能,提前声明所有可能的图片文件,让构建工具能正确解析动态导入:
// 提前扫描并导入30x30目录下所有PNG图片 const iconImporters = import.meta.glob('../../../assets/images/coins/30x30/*.png'); function useImportIcon(coinSymbol: string): [IconSrc, ImportError] { const [iconSrc, setIconSrc] = useState<IconSrc>(null); const [error, setError] = useState<ImportError>(null); useEffect(() => { const targetPath = `../../../assets/images/coins/30x30/${coinSymbol}.png`; const importer = iconImporters[targetPath]; if (!importer) { setError(new Error(`Icon for ${coinSymbol} does not exist`)); return; } importer() .then(module => setIconSrc(module.default)) .catch(err => { console.error(`Failed to load icon for ${coinSymbol}:`, err); setError(err); }); }, [coinSymbol]); return [iconSrc, error]; }
说明:import.meta.glob会在构建阶段扫描匹配的文件,生成对应的导入函数,确保动态导入能被正确解析和打包。
内容的提问来源于stack exchange,提问作者Producdevity
相关产品推荐
相关产品推荐

