2019.8.20
画像などのjs以外のリソースをimportしてjsxで使用したいということがまぁまぁあると思います。react-svg-loader
というパッケージを使うとsvgをimportしてjsxとして使用することができます。
npm i react-svg-loader --save-dev
インラインで直接使う場合は以下のようにimportすればOKです。この書き方初めて知りました。
import Image1 from 'react-svg-loader!./image1.svg';
Webpackで使用する場合は、READMEの導入を参考にwebpack.config.js
のloader
に設定を追加します。
{
test: /\.svg$/,
use: [
{
loader: "babel-loader"
},
{
loader: "react-svg-loader",
options: {
jsx: true // true outputs JSX tags
}
}
]
}
ReactのコードもREADMEにならってこのように書きます。jsxで書けるのがいいですね。
import Image1 from './image1.svg';
<Image1 width={50} height={50}/>
Webpackを起動するとエラーが出ました。jsxをゴニョゴニョしてるところでエラーが出てるのでしょうかね?もしかしたらTypeScriptを使ってるのでts-loader
でjsxをコンパイルしているからなのかな?
ERROR in ./image1.svg
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: ****/hoge.svg: Unexpected token (5:6)
試しに以下のoptions
の項目を削除してみました。するとエラーが消えました。
options: {
jsx: true // true outputs JSX tags
}
SVGOというsvgを最適化して、サイズを軽くしてくれるnode.js製のライブラリがあります。options
でsvgoを使用することもできます。
GitHub - svg/svgo: Node.js tool for optimizing SVG files
webpack.config.js
を次のようにします。
{
test: /\.svg$/,
use: [
"babel-loader",
{
loader: "react-svg-loader",
options: {
svgo: {
plugins: [
{ removeTitle: false }
],
floatPrecision: 2
}
}
}
]
}
TypeScriptを使用しているとこのようなエラーが出ます。
[tsl] ERROR in hoge.tsx(7,20)
TS2307: Cannot find module './image1.svg'.
WebpackでTypeScriptを使用しているときにコード以外のリソースをimportしようとするとモジュールが存在しないのでコンパイルエラーになります。そこで自前の型定義ファイルを作ることで回避します。
TypeScript#importing-other-assets | webpack
custom.d.ts
というファイルをプロジェクトのトップレベルに配置します。中身は下記のような定義を書いておきます。
declare module "*.svg" {
const content: any;
export default content;
}
これでモジュールとして認識されるようになるので読み込めるようになります。
Jestでコンポーネントファイルのテストを書いているのですが、テストを走らせるとsvgの読み込みのところでエラーが出ました。
at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:471:17)
at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:513:25)
at Object.<anonymous> (src/Hoge.tsx:7:1)
Jestのテストでもsvgを読み込めるようにjest-svg-transformer
をインストールしてみました。
jest.config.js
のtransform
を下記のようにするとsvgを読み込めるようになり、エラーが解消されました。
{
"transform": {
"^.+\\.svg$": "jest-svg-transformer"
}
}