使用 React 组件在 Safari 中获取“不安全尝试加载 URL 数据:image/svg+xml...”

问题描述 投票:0回答:2

我正在使用 rollup 来捆绑一个 React npm 包,其中包含一个图标组件,该组件将名称作为 prop,并返回一个由 React 组件包装的具有该名称的图标。 这是组件代码:

    import sprite from './public/sprite.svg';
    
    function Icon({ name }) {
       return <svg className="svg-wrapper">
          <use href={`${sprite}#${name}`} />
       </svg>
      );
    }

文件夹结构如下:


     - src
     - - public 
     - - - sprite.svg
     - - icons
     - - - some-icon.svg
     - - - some-other-icon.svg
     - - index.tsx # component with the code mentioned above

这是我的汇总配置:


    export default {
          plugins: [
            esbuild({
              sourceMap: false,
              target: "esnext"
            }),
            image(),
            svgicons({
              inputFolder: "src/icons",
              output: "public/sprite.svg"
            }),
            json()
         ]
        }

这在 Chrome 中工作正常(尽管它确实内联了

href
内的所有 svg,我认为这是此方法的目的),但在 Safari 中它会触发以下错误:

    Unsafe attempt to load URL data:image/svg+xml,%3c%3fxm ....
    Domains, protocols and ports must match.

问题是,如前所述,这是一个 npm 包,它将图标打包为 js 包(内联)的一部分,因此对该组件的服务方式没有太多控制,因为这是由浏览器缓存处理的(也是浏览器缓存之一)使用这种方法的要点)。我对 CORS 非常熟悉,我知道也许避免使用

data:image/svg+xml
uri 链接可以解决此问题,但会增加此包的构建步骤的复杂性(需要使用 svgr/svgo 构建图标,然后进行某种查找表根据名称属性返回正确的图标,即)。

所以,最终我的问题是,通过反应组件库中的精灵方法,是否有一种万无一失的方法可以避免此类问题和跨浏览器不一致? 预先感谢您提供的任何帮助。

reactjs svg rollup svg-sprite
2个回答
2
投票

我已经为这个问题苦苦挣扎了一段时间。我猜这是 Safari 上的一个错误,因为正在处理 dataURI,就好像它是外部 URL 一样。

关于您的代码,您可以在公共文件夹中公开您的精灵或将其发布在 cdn 中(有利于缓存目的),并更改 rollup 处理您的 svg 的方式(似乎它将您的 svg 打包为 dataURI)。或者,我实现了一种解决方法来转换 blob 中的 dataURI。

import sprite from './public/sprite.svg';

function dataURItoBlobUrl(dataURI: string) {
  const svg = decodeURI(dataURI).split(',')[1];
  const blob = new Blob([svg], { type: "image/svg+xml" });

  return URL.createObjectURL(blob);
}

const blobUrl = dataURItoBlobUrl(sprite);

export const Icon: FC<IconProps> = ({ name, ...props }) => {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" {...props}>
      <use href={`${blobUrl}#${name}`}></use>
    </svg>
  );
};

0
投票

我已将

file.svg
放入服务器上的
public/icons
文件夹,然后定义以下组件:

import React from 'react';
import { SvgIcon } from '@material-ui/core';

export default function SvgIcon({ name, ...props }) {

    return (
        <SvgIcon {...props}>
            <use xlinkHref={`./icons/file.svg#${name}`} />
        </SvgIcon>
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.