SVG icon sets in React with Rollup
--
When I wrote “Embedded SVG icon sets and Reactjs” almost 3 years ago, the way that developers implemented an icon set was considerably different. SVGs were not the most widely used icon types being used and whether they had enough browser support was still questioned by some members of the community. Manually creating a set of PNG icons was commonplace, and products such as Fontello and Font Awesome created icon fonts that were widely preferred to SVG icon sets. Since then, SVGs have garnered the community support they deserve.
In the ever-changing world of web development, the preferred method of icon inclusion isn’t the only thing that has changed. The React framework is considerably different as well. Changes to the React API in addition to a new bundler package called Rollup inspired updates to the way I build and maintain SVG icon sets.
The most notable change affecting the way icons were maintained was driven largely by a limitation of Rollup. More specifically, using require dynamically is not supported by Rollup as it is with Webpack.
// The old way
render() {
const IconComponent= require(`./icons/${this.props.icon}`).default;
return <IconComponent />;
}
That means that the line of code that inserts the proper icon in the Webpack implementation of Icon.js would no longer work. I set out to find a new way of developing an SVG icon set.
Build a better mousetrap
After thinking about the problem a while and testing some less than ideal solutions, the Rollup compatible version of Icon.js file looked like this:
// The new way
import Icons from './Icons';const IconComponent = Icons[this.props.icon];return {IconComponent && IconComponent()};
Instead of each SVG being housed in individual React components, every SVG is held within a single file, wrapped in a function, and exported. Each of these functions simply returns an SVG.
We then make all of these functions available by default by adding them to the default export at the end of the file. This pattern allows Rollup to fetch the correct icon with a function call when bundled, and completely bypass the dynamic require from the Webpack configuration.
export default {
Reply,
Search
}
<Icon icon='Outcome' color='black' size='small' />
What we end up with, is an icon component that behaves very much like its predecessor but does not rely on Webpack black magic for it to work correctly.
While the Webpack implementation still works great, this pattern is a little clearer and only requires you to manipulate a single function to edit, add or remove an SVG.