【React】SVGファイルをインラインで読み込んで、React Conponentにする方法

【React】SVGファイルをインラインで読み込んで、React Conponentにする方法

スポンサーリンク

どうも、イソップです。

Reactアプリケーションでは、アイコンを使うことが多いと思いますが、
画像アイコンでは再レンダリング時に表示がチラついてしまうので、
Font AwesomeなどのフォントアイコンやSVG画像を利用するのが、個人的にきれいに表示するコツです。

インラインSVGを利用すれば、レスポンシブに対応させつつ、
アイコンカラーを変えたりアニメーションさせたりできるので、とてもオススメです。
ただ、インラインで用意しなければならず少し扱いが面倒なんですよね。

そこで、今回はちょっと面倒なSVGファイルを、
インラインSVGで読み込み、React Conponentとして読み込む方法を紹介します。

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 は解釈されずエラーを吐くので、手動で削除しておくのが良いでしょう。

【React】SVGファイルをインラインで読み込んで、React Conponentにする方法