React svg / png 渲染在新 URL 上闪烁

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

我正在使用最新的

create-react-app
配置,并在不同路线之间切换时遇到问题。

我所有的

SVG
都包含在精灵文件中。从逻辑上讲,sprite.svg文件应该在首页加载时缓存。

但是,每次更改路线(使用

react-router
4)都会加载此文件,从而导致闪烁。内容会立即更改,但图像加载会出现 1 秒的延迟。 与通过
png
中的
import
包含的
jsx
相同。

从控制台中看不到,相同的文件会一遍又一遍地下载。

现场演示位于 http://cabin.surge.sh/(即尝试在标题部分的定价/关于页面之间进行更改)

更新:

我包含 SVG 图像的方式 - 是愚蠢的组件

<SvgIcon name="checkmark" />

import React, { Component } from 'react';
import sprite from '../images/sprite.svg';

export default class SvgIcon extends Component {
  render(){
    const { name } = this.props;
    return(
      <svg className={"ico ico-" + name}>
        <use xlinkHref={sprite + "#ico-" + name}></use>
      </svg>
    )
  }
}

PNG 图像

<img src={require(`../images/${authorImage}.png`)} srcSet={require(`../images/${authorImage}@2x.png`)  + ' 2x'} alt=""/>
reactjs react-router
3个回答
2
投票

您得到

200
而不是
304
的原因是您有一个服务工作者,它将拦截请求并从缓存本身提供相同的服务。这本身就是
200
的回应。如果您禁用 Service Worker,那么您将得到
304


2
投票

如果问题是图像没有提前获取并导致页面更改时闪烁,请尝试使用

componentDidMount() {
  const sprite = "../images/sprite.svg";
  const prefetchLink = document.createElement("link");

  prefetchLink.href = sprite;
  prefetchLink.rel = "prefetch";
  prefetchLink.as = "image";
  document.body.appendChild(prefetchLink);
}

这将提示浏览器在后台(空闲时间)获取稍后可能需要的资源,并将它们存储在浏览器的缓存中。页面加载完成后,它会开始下载其他资源,如果用户单击预取的链接,它将立即加载内容。

对于功能版本:

//custom hook to preload image
const usePreload = (url) => {
  const [loaded, setLoaded] = React.useState(false);
  const onLoad = React.useCallback(() => {
    setLoaded(true);
  }, []);
  React.useEffect(() => {
    const prefetchLink = document.createElement('link');
    prefetchLink.href = url;
    prefetchLink.rel = 'prefetch';
    prefetchLink.as = 'image';
    prefetchLink.addEventListener('load', onLoad);
    document.body.appendChild(prefetchLink);
    //clean up
    return () => document.body.removeChild(prefetchLink);
  }, [onLoad, url]);
  return loaded;
};

export default function SvgIcon({ name }) {
  const url = sprite + '#ico-' + name;
  const loaded = usePreload(url);
  return (
    loaded && ( //only render if image is loaded
      <svg className={'ico ico-' + name}>
        <use xlinkHref={url}></use>
      </svg>
    )
  );
}

请注意,如果您进行服务器端渲染,您不希望此代码在服务器上执行,因为服务器上没有

document


0
投票

您必须将缓存 TTL max-age 设置为类似

600
的值。这意味着您希望资源缓存 10 分钟。

如果您使用 NextJS,您可以将其添加到您的

next.config.js

module.exports = {
  trailingSlash: true,
  async headers() {
    return [
      {
        source: '/:all*(svg)',
        locale: false,
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=600, must-revalidate',
          },
        ],
      },
    ];
  },
};
© www.soinside.com 2019 - 2024. All rights reserved.