External SVGs that you can style
How it works
- Fetches your SVGs in browser with
fetch
request. And caches of course. - Puts it into sprite that is stored in your
body
. - Provides you with the React component and standalone API to use this icon in your code.
- That's it. You now may use all the fancy css-styling like if it was inline SVG.
Why
- Sprites may become huge, containing hundreds of icons, and you don't need all of your icons on every page.
- Styling with css is a must-have, and this is the only way of getting it except for inlining.
- Inlining SVGs with React might be painful (there is a tool though), it also increases the bundle size a nd just doesn't feel right.
Usage
Install it from npm
npm i handy-svg
React
import {HandySvg} from 'handy-svg';
import iconSrc from './icon.svg';
export const Icon = () => (
<HandySvg
src={iconSrc}
width="32"
height="32"
/>
);
I assume here that you use file-loader
for bundling your svg-files and get public url to SVG file in iconSrc
, like so:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
};
But in fact there is no difference for the handy-svg where you get your SVGs urls from.
Standalone
You may also use handy-svg without React at all.
import {injector} from 'handy-svg/lib/injector';
const src = "https://cdn-server.net/icon.svg";
// Fetches svg content and puts it to sprite
injector.load(src);
// Gets the id of your svg in sprite
const id = injector.getId(src);
// Then you can use it at your will
const svg = `<svg><use href="#${id}" /></svg>`;
API
<HandySvg />
import {HandySvg} from 'handy-svg';
type HandySvgProps = {
src: string; // your icon url
loadTimeot?: number; // load timeout. 4800 by default
loadRetryCount?: number; // load retry. 2 by default
[key: string]: string | number | undefined; // any extra props will be passed to svg tag
}
<HandySvg {...props} />
injector.load()
import {injector} from 'handy-svg/lib/injector';
type LoadOptions = {
flushImmediate?: boolean; // inject icon to the body without debouncing
timeout?: number; // load timeout. 4800 by default
retryCount?: number; // load retry. 2 by default
}
injector.load(src: string, options: LoadOptions): Promise<void>;
injector.getId()
import {injector} from 'handy-svg/lib/injector';
injector.getId(src: string): string;
CSP
You should add hostnames of your icons to the connect-src directive of your Content-Security-Policy header for this to work properly.