なぽろぐ

気ままに感じたことを記事にまとめます。Vtuberのイベントのことと、プログラム関連のことが多めだと思います。

Nextjsでsvgをインラインで読み込んでreact componentとして使う

Nextjsでもsvgをreact componentで使いたい

素のreactのプロジェクトだとこれ使ってパチッとやってたやつをNextjsでもやりたいってやつです. github.com

次のように書ければ目的達成という感じです.

import Icon from "~/assets/icons/icon.svg"
export const Component = () => {
  return (
    <Icon />
  )
}

Nextjs用のライブラリがあるですね~.うれしい.これを使うだけなのですが,next-imagesを併用してると動かないときもあるのでメモしておこうと思います. github.com

next-react-svg と next-images を併用する

next-images"jpg", "jpeg", "png", "svg", "gif", "ico", "webp", "jp2", "avif" の拡張子を含むファイルをすべて url-loader 通しちゃうので next-react-svg を使っていても svg は url 形式になってしまいます.なので次のようにnext-react-svgがincludeしてるpathnext-imagesではexcludeするという処理をすれば動きます.

next-compose-pluginswithXXXに対応するconfigを見やすく記述することができるpluginなのでいれています.

const { withPlugins } = require("next-compose-plugins")
const withImages = require('next-images')
const withReactSvg = require("next-react-svg")
const path = require('path')

const nextCofig = {
  / * someconfig .... */
  webpack(config) {
    config.resolve.alias['~'] = path.resolve('src')

    return config
  }
}

module.exports = withPlugins([
  [withImages, {
    exclude: path.resolve(__dirname, "src/assets/icons")
  }],
  [withReactSvg, {
    include: path.resolve(__dirname, "src/assets/icons")
  }]
], nextConfig)

typescriptを使う人向けにsvgの型定義を置いておきます.~/assets/icons/*.svgからimportするときはComponentで読み込んでほしいので次のようにどこかに記述して置けれいいはずです.

declare module '*.svg'
declare module '~/assets/svg/*.svg' {
  const value: React.FunctionComponent<React.SVGAttributes<SVGElement>>

  export = value
}

これで次のような記述をすることでsvgをcomponentとして扱うことができます.

import Icon from "~/assets/icons/icon.svg"
export const Component = () => {
  return (
    <Icon />
  )
}