どうも、イソップです。
Reactアプリケーションでは、アイコンを使うことが多いと思いますが、
画像アイコンでは再レンダリング時に表示がチラついてしまうので、
Font AwesomeなどのフォントアイコンやSVG画像を利用するのが、個人的にきれいに表示するコツです。
インラインSVGを利用すれば、レスポンシブに対応させつつ、
アイコンカラーを変えたりアニメーションさせたりできるので、とてもオススメです。
ただ、インラインで用意しなければならず少し扱いが面倒なんですよね。
そこで、今回はちょっと面倒なSVGファイルを、
インラインSVGで読み込み、React Componentとして読み込む方法を紹介します。
目次
react-svg-loaderを使ってSVGファイルをインライン展開
SVGファイルの読み込みをreact-svg-loaderで行います。
このモジュールを介してSVGをインポートすることで、
SVGをインラインで読み込んで、コンポーネントにしてくれます。
またそれだけではなく、オプションを指定することで、SVGのコードを整形・圧縮してくれる svgo を利用することが出来るので、かなり使い勝手の良いストレスフリーなモジュールなんです。
いくつか探した中でこれが一番良さそうでした。
react-svg-loaderの使い方
まずはインストールしましょう。
$ npm install svg-react-loader --save-dev
次に早速モジュールを利用してSVGを読み込みます。
import Image from 'react-svg-loader!./image.svg';
const GreatButton = () => (
<button>
<Icon />
<span>Great Button</span>
</button>
)
そのままコンポーネントとして利用できます。
オススメはWebpackを利用する方法です。
import Icon from './icon.svg';
const GreatButton = () => (
<button>
<Icon />
<span>Great Button</span>
</button>
)
babelとセットでローダーの設定を行えば、直接 import
するだけでインラインSVGが読み込めます。
loader: [
...
{
test: /\.svg$/,
loader: 'babel!react-svg'
}
]
svgoオプションを利用する
ローダーにsvgoオプションを指定することが出来ます。
{
test: /\.svg$/,
loader: 'react-svg-loader',
query: {
svgo: {
// svgo options
plugins: [{removeTitle: false}],
floatPrecision: 2
}
}
}
babel-loaderなどローダーを複数を利用している場合、query
プロパティが指定できないので、
パラメータを渡す場合はJSONオブジェクトを文字列にする方法がオススメです。
{
test: /\.svg$/,
loader: 'babel-loader!react-svg-loader?' + JSON.stringify({
svgo: {
// svgo options
plugins: [{removeTitle: false}],
floatPrecision: 2
}
}),
}
ちなみに、Webpack2だと次のように指定できます。
{
test: /\.svg$/,
use: [
{
loader: 'babel-loader'
},
{
loader: 'react-svg-loader',
query: {
svgo: {
plugins: [{removeTitle: false}],
floatPrecision: 2
}
}
}
]
}
画像ファイルとインラインSVGを共存させたい
Webpackのローダーの指定方法を次のようにすることで、画像ファイルとインラインSVGが共存可能です。
{
test: /\.inline.svg$/,
loader: 'babel!svg-react'
},
{
test: /\.jpe?g$|\.gif$|\.png$|^(?!.*\.inline\.svg$).*\.svg$/,
loader: 'url'
}
インラインSVGは、***.inline.svg
としてファイルを用意し、
画像ファイルは、***.svg
とします。
【参考】 SVG Images as React Components with Webpack
ReactでSVGを扱う際の注意点
IllustlatorやPhotoshopで書き出したSVGファイルの中身には、
大体の場合、g
要素に data-name
属性が指定されています。
Reactでは data-name
は解釈されずエラーを吐くので、手動で削除しておくのが良いでしょう。