開発者は多くの場合、SVG を JSX に直接挿入します。これは便利ですが、JS バンドルのサイズが大きくなります。最適化を追求する中で、バンドルを乱雑にせずに SVG アイコンを使用する別の方法を見つけることにしました。 SVG スプライトとは何か、その使用方法、およびそれらを操作するために使用できるツールについて説明します。 理論から始めて、SVG スプライトを段階的に生成するスクリプトを作成し、最後に と のプラグインについて説明します。 vite webpack SVGスプライトとは何ですか? イメージ スプライトは、単一のイメージに配置されたイメージのコレクションです。 SVG スプライトは SVG コンテンツのコレクションであり、 にラップされ、 に配置されます。 <symbol /> <svg /> たとえば、単純な SVG ペン アイコンがあります。 SVG スプライトを取得するには、 タグを に置き換え、外部で でラップします。 <svg /> <symbol /> <svg /> これは SVG スプライトになり、その中に アイコンが含まれています。 id="icon-pen" わかりましたが、このアイコンを HTML ページに配置する方法を考えなければなりません。 タグを 属性とともに使用し、アイコンの ID を指定します。これにより、SVG 内でこの要素が複製されます。 <use /> href どのように機能するかの例を見てみましょう。 <use /> この例では、円が 2 つあります。最初のものは青い輪郭を持ち、2 つ目は最初のものの複製ですが、赤い塗りつぶしが施されています。 SVG スプライトに戻りましょう。 を使用すると、次のようになります。 <use /> ここには、ペンのアイコンが付いたボタンがあります。 これまでは、 内のコードなしでアイコンを使用してきました。ページ上に複数のボタンがある場合、すべてのアイコンは SVG スプライトから取得され、再利用できるため、HTML レイアウトのサイズに複数回影響することはありません。 <button /> SVGスプライトファイルの作成 SVG スプライトを別のファイルに移動して、 ファイルを乱雑にしないようにしましょう。まず、 ファイルを作成し、その中に SVG スプライトを配置します。次のステップでは、 の 属性を使用してアイコンへのアクセスを提供します。 index.html sprite.svg <use/> href SVG スプライト作成の自動化 アイコンの使用時間を大幅に節約するために、このプロセスの自動化を設定しましょう。アイコンに簡単にアクセスして必要に応じて管理するには、アイコンをそれぞれ独自のファイルに分離する必要があります。 まず、すべてのアイコンを同じフォルダーに配置する必要があります。例: 次に、これらのファイルを取得して単一の SVG スプライトに結合するスクリプトを作成しましょう。 プロジェクトのルート ディレクトリに ファイルを作成します。 generateSvgSprite.ts ライブラリをインストールします。 グロブ npm i -D glob を使用して、各アイコンの絶対パスの配列を取得します。 globSync ここで、各ファイル パスを反復処理し、Node の組み込みライブラリ を使用してファイルのコンテンツを取得します。 fs 各アイコンの SVG コードがあり、それらを結合できるようになりました。ただし、各アイコン内の タグを タグに置き換え、不要な SVG 属性を削除する必要があります。 svg symbol SVG コードを HTML パーサー ライブラリで解析して、DOM 表現を取得する必要があります。 使用します。 node-html-parser を SVG コードを解析し、実際の HTML 要素であるかのように SVG 要素を取得しました。 同じパーサーを使用して、空の 要素を作成し、 の子を に移動します。 symbol svgElement symbol から子を抽出した後、そこから と 属性も取得する必要があります。 にはアイコンファイルの名前を設定しましょう。 svgElement id viewBox id これで、SVG スプライトに配置できる 要素ができました。したがって、ファイルを反復処理する前に 変数を定義し、 文字列に変換し、それを にプッシュするだけです。 symbol symbols symbolElement symbols 最後のステップは、SVG スプライト自体を作成することです。これは、「ルート」に があり、子としてシンボルを持つ文字列を表します。 svg const svgSprite = `<svg>${symbols.join('')}</svg>`; また、以下で説明するプラグインの使用を検討していない場合は、作成したスプライトを含むファイルを静的フォルダーに置く必要があります。ほとんどのバンドラーは フォルダーを使用します。 public fs.writeFileSync('public/sprite.svg', svgSprite); これで終わりです。スクリプトを使用する準備ができました。 // generateSvgSprite.ts import { globSync } from 'glob'; import fs from 'fs'; import { HTMLElement, parse } from 'node-html-parser'; import path from 'path'; const svgFiles = globSync('src/icons/*.svg'); const symbols: string[] = []; svgFiles.forEach(file => { const code = fs.readFileSync(file, 'utf-8'); const svgElement = parse(code).querySelector('svg') as HTMLElement; const symbolElement = parse('<symbol/>').querySelector('symbol') as HTMLElement; const fileName = path.basename(file, '.svg'); svgElement.childNodes.forEach(child => symbolElement.appendChild(child)); symbolElement.setAttribute('id', fileName); if (svgElement.attributes.viewBox) { symbolElement.setAttribute('viewBox', svgElement.attributes.viewBox); } symbols.push(symbolElement.toString()); }); const svgSprite = `<svg>${symbols.join('')}</svg>`; fs.writeFileSync('public/sprite.svg', svgSprite); このスクリプトをプロジェクトのルートに置き、 で実行できます。 tsx npx tsx generateSvgSprite.ts 実際、ここで を使用しているのは、以前はどこでも TypeScript でコードを記述していたためであり、このライブラリを使用すると、TypeScript で記述されたノード スクリプトを実行できるようになります。純粋な JavaScript を使用したい場合は、次のように実行できます。 tsx node generateSvgSprite.js それでは、スクリプトが何をしているのかをまとめてみましょう。 フォルダーで ファイルがないか調べます。 src/icons .svg すべてのアイコンの内容を抽出し、そこからシンボル要素を作成します。 すべてのシンボルを単一の <svg />. フォルダーに ファイルが作成されます。 public sprite.svg アイコンの色を変更する方法 よくある重要なケースの 1 つである色について説明しましょう。アイコンがスプライトに入るスクリプトを作成しましたが、このアイコンはプロジェクト全体で異なる色を持つことができます。 要素だけでなく、 、 、 なども fill 属性やストローク属性を持つことができることに留意する必要があります。 という非常に便利な CSS 機能が役に立ちます。 <svg/> path circle line currentcolor このキーワードは、要素の color プロパティの値を表します。たとえば、 である要素に を使用すると、この要素の背景は赤になります。 background: currentcolor color: red 基本的に、すべてのストロークまたは塗りつぶしの属性値を に変更する必要があります。それが手動で行われているのを見ないことを祈ります、へー。また、SVG 文字列を置換または解析するコードを作成することさえ、非常に便利なツール に比べてあまり効率的ではありません。 currentcolor svgo これは、色だけでなく、SVG からの冗長な情報の削除にも役立つ SVG オプティマイザーです。 をインストールしましょう。 svgo npm i -D svgo には組み込みプラグインがあり、そのうちの 1 つは、 プロパティを持つ です。この SVG 出力を使用すると、色が に置き換えられます。以下は、 と の使用法です。 svgo currentColor: true convertColors currentcolor svgo convertColors import { optimize } from 'svgo'; const output = optimize( '<svg viewBox="0 0 24 24"><path fill="#000" d="m15 5 4 4" /></svg>', { plugins: [ { name: 'convertColors', params: { currentColor: true, }, } ], } ) console.log(output); そして出力は次のようになります: <svg viewBox="0 0 24 24"><path fill="currentColor" d="m15 5 4 4"/></svg> 前のパートで書いた魔法のスクリプトに を追加しましょう。 svgo // generateSvgSprite.ts import { globSync } from 'glob'; import fs from 'fs'; import { HTMLElement, parse } from 'node-html-parser'; import path from 'path'; import { Config as SVGOConfig, optimize } from 'svgo'; // import `optimize` function const svgoConfig: SVGOConfig = { plugins: [ { name: 'convertColors', params: { currentColor: true, }, } ], }; const svgFiles = globSync('src/icons/*.svg'); const symbols: string[] = []; svgFiles.forEach(file => { const code = fs.readFileSync(file, 'utf-8'); const result = optimize(code, svgoConfig).data; // here goes `svgo` magic with optimization const svgElement = parse(result).querySelector('svg') as HTMLElement; const symbolElement = parse('<symbol/>').querySelector('symbol') as HTMLElement; const fileName = path.basename(file, '.svg'); svgElement.childNodes.forEach(child => symbolElement.appendChild(child)); symbolElement.setAttribute('id', fileName); if (svgElement.attributes.viewBox) { symbolElement.setAttribute('viewBox', svgElement.attributes.viewBox); } symbols.push(symbolElement.toString()); }); const svgSprite = `<svg xmlns="http://www.w3.org/2000/svg">${symbols.join('')}</svg>`; fs.writeFileSync('public/sprite.svg', svgSprite); そして、スクリプトを実行します。 npx tsx generateSvgSprite.ts その結果、SVG スプライトには のアイコンが含まれることになります。これらのアイコンは、プロジェクト内のどこでも好きな色で使用できます。 currentColor プラグイン スクリプトがあるので、いつでも実行できますが、手動で使用しなければならないのは少し不便です。したがって、外出先で ファイルを監視し、SVG スプライトを生成できるいくつかのプラグインをお勧めします。 .svg ( ユーザー向け) vite-plugin-svg-spritemap vite これは、この記事で作成したばかりのスクリプトを基本的に含むプラグインです。プラグインでは 置換がデフォルトで有効になっているため、プラグインを非常に簡単にセットアップできます。 currentColor // vite.config.ts import svgSpritemap from 'vite-plugin-svg-spritemap'; export default defineConfig({ plugins: [ svgSpritemap({ pattern: 'src/icons/*.svg', filename: 'sprite.svg', }), ], }); ( ユーザー向け) svg-spritemap-webpack-plugin Webpack Vite に切り替えるまでは、この Webpack プラグインを使用していました。ただし、Webpack を使用している場合には、このプラグインは依然として優れたソリューションです。手動で色変換を有効にする必要があります。色変換は次のようになります。 // webpack.config.js const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin'); module.exports = { plugins: [ new SVGSpritemapPlugin('src/icons/*.svg', { output: { svgo: { plugins: [ { name: 'convertColors', params: { currentColor: true, }, }, ], }, filename: 'sprite.svg', }, }), ], } レイアウトでの使用法 の例を提供しますが、主に HTML に関するものであるため、必要な場所に実装できます。したがって、ビルド フォルダーに があるので、スプライト ファイルにアクセスして、基本的な コンポーネントを作成できます。 React sprite.svg Icon const Icon: FC<{ name: string }> = ({ name }) => ( <svg> <use href={`/sprite.svg#${name}`} /> </svg> ); const App = () => { return <Icon name="pen" />; }; 最終結果 すべてをまとめると、アイコンを使用した多くの手動作業を避けるために、次のようになります。 プロジェクト内のアイコンを適切な名前で簡単に保存し、整理しておくことができます すべてのアイコンを別のファイル内の単一のスプライトに結合するスクリプトがあり、これによりバンドル サイズが削減され、プロジェクト内のどこでもこれらのアイコンを使用できるようになります アイコンを不要な属性から整理し、使用場所の色を変更するのに役立つ便利なツールがあります アイコン ファイルを監視し、ビルド プロセスの一部として外出先でスプライトを生成できるプラグインがある 一番上の追加要素である Icon コンポーネントがある 結論 開発の効率化とは、単に時間を節約することだけではありません。それは私たちの創造的な可能性を解き放つことなのです。アイコンの管理などの核心的なタスクを自動化することは、単なる近道ではありません。これは、よりスムーズでインパクトのあるコーディング エクスペリエンスへの入り口となります。そして、そのような日常的な作業にかかる時間を節約することで、より複雑なタスクに集中し、開発者としてより早く成長することができます。