🎇

svgファイルをReactコンポーネントに変換する方法

3 min read

やりたいこと

.svg.tsx の拡張子に変換したい

技術選定

  • React
  • TypeScript
  • Next.js

実現方法

SVGRというツールを用いることで簡単に実現できた

前提知識

SVGRとは何か?

svgファイル から Reactコンポーネント にコマンド1つで簡単に変換できる CLI ツール

SVGR の基本構成

svgファイル(.svg) → SVGR → React Component(.jsx | .tsx)

SVGRを用いて svg を jsx に変換する基本手順

1. 実行ファイルをinstallする

yarn add -D @svgr/cli

2. CLIコマンドを叩く

npx @svgr/cli -d src/components/icons public/icons

※ -d [出力先のディレクトリ名] [svgファイルが格納されているディレクトリ名]
  • ※1 Usage: npx @svgr/cli [-d out-dir] [--ignore-existing] [src-dir]
  • ※2 npx : ローカルインストールしたコマンドを実行するために使用される便利コマンド

この2つのステップでpublic/iconsにあるsvgファイルが
src/components/iconsにjsファイルとして出力される

実際の現場で運用する際はいちいち2のnpxコマンドを叩くのはとても面倒。

package.jsonのscripts配下にエイリアス登録しておくと使い回しやすいので
package.jsonのscripts配下に実行コマンドをエイリアス登録しておくと良い

"scripts": {
  "icons": "npx @svgr/cli -d src/components/icons public/icons"
}

これでyarn iconsと叩くだけでsvgファイルを
コマンド1つでコンポーネントファイル(js)に変換できる

ただし、この設定のままだと svgファイル を jsファイル にしか変換できない。
やりたいことは svg を tsx に変換したいだったので
SVGR の設定ファイルを作成して編集する必要がある。

svg を jsx ではなく tsx に変換する手順

  • 設定ファイル(.svgrrc.js)を作成する
  • 設定ファイルにtypescript: trueと記載する
module.exports = {
  typescript: true
}

この設定ファイルをルートディレクトリ
作成した上でもう一度yarn iconsと叩く

svg から tsx に変換できた ↓
yarn icons.png

補足事項

上記、設定のままだと以下のように
default exportのコンポーネントに変換される

import * as React from 'react'

function SvgVectorRight(props: React.SVGProps<SVGSVGElement>) {
  return (
    <svg xmlns='http://www.w3.org/2000/svg' width={32} height={32} {...props}>
      <path d='M19.414 27.414l10-10a2 2 0 000-2.828l-10-10a2 2 0 10-2.828 2.828L23.172 14H4a2 2 0 100 4h19.172l-6.586 6.586c-.39.39-.586.902-.586 1.414s.195 1.024.586 1.414a2 2 0 002.828 0z' />
    </svg>
  )
}

export default SvgVectorRight

自分はdefault exportではなく名前付きexportのコンポーネントに変換したかった
これは、SVGR | template を編集することで、実現することができた

// .svgrrc.js

module.exports = {
  typescript: true,
  template: ({ template }, opts, { imports, componentName, props, jsx }) => {
    const plugins = ['jsx']
    if (opts.typescript) {
      plugins.push('typescript')
    }
    const typeScriptTpl = template.smart({ plugins })
    return typeScriptTpl.ast`${imports}

    export const ${componentName} = (${props}): JSX.Element => {
        return ${jsx};
      }
    `
  },
}

上記、設定ファイルにした上で、もう一度yarn iconsを叩くと
以下のような名前付きexportのコンポーネントに変換される

import * as React from 'react'

export const SvgVectorRight = (props: React.SVGProps<SVGSVGElement>): JSX.Element => {
  return (
    <svg xmlns='http://www.w3.org/2000/svg' width={32} height={32} {...props}>
      <path d='M19.414 27.414l10-10a2 2 0 000-2.828l-10-10a2 2 0 10-2.828 2.828L23.172 14H4a2 2 0 100 4h19.172l-6.586 6.586c-.39.39-.586.902-.586 1.414s.195 1.024.586 1.414a2 2 0 002.828 0z' />
    </svg>
  )
}

これで**「やりたいこと」**を実現できた!ほぼコピペでいけます!
Reactのアイコンの管理方法に悩んでいる人はぜひ活用してみてください!

参考文献

SVGR | Options

Discussion

ログインするとコメントできます