You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()处理静态图片:

  1. 调整资源位置:将assets/images/coins整个目录移动到项目根目录的public文件夹下,最终结构为:
.
└── public
    └── images
        └── coins
            └── 30x30
                ├── BTC.png
                └── ...其他图片
  1. 修改图标加载逻辑:直接构造资源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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:38:10