问题
I'm using latest create-react-app
config and facing the issues when switching between different routes.
All my SVG
's are included in sprite file. Logically, sprite.svg file should be cached on the first-page load.
But instead, every change of route (with react-router
4) loads this file which causes flickering. Content changes instantly, but images loads with 1s lag.
Same for png
included via import
in jsx
.
From what I cant see in the console, same files download over and over again.
Live demo at http://cabin.surge.sh/ (i.e. try to change between Pricing / About pages in the header section)
Update:
The way I include SVG image - is dumb component <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 images
<img src={require(`../images/${authorImage}.png`)} srcSet={require(`../images/${authorImage}@2x.png`) + ' 2x'} alt=""/>
回答1:
The reason you get a 200
instead of 304
is that you have a service worker which will intercept the request and serve the same from the cache itself. Which itself is 200
response. If you disable the service worker then you will get a 304
回答2:
If the problem is that the image is not fetched earlier and causing flickering on page change, try to use
componentDidMount() {
const sprite = "../images/sprite.svg";
const prefetchLink = document.createElement("link");
prefetchLink.href = sprite;
prefetchLink.rel = "prefetch";
prefetchLink.as = "image";
document.body.appendChild(prefetchLink);
}
This will hint the browser to fetch resources in the background (idle time) that might be needed later, and store them in the browser’s cache. Once a page has finished loading it begins downloading additional resources and if a user then clicks on a prefetched link, it will load the content instantly.
For a functional version:
//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>
)
);
}
Note that if you do server side rendering you don't want this code to execute on the server because there is no document
on the server.
来源:https://stackoverflow.com/questions/50659679/react-svg-png-render-is-flickering-on-new-url