Webpack単一行のSVGスプライト

数日前に、SVGスプライトを作成するためのwebpackローダーであるsvg-sprite-loaderの完全に更新されたバージョンがリリースされました。 内部では、それがどのように機能し、開発者の生活を楽にするかについて詳しく説明します。







モジュールとしての画像



webpackの場合、どのファイルもモジュールです。 この概念に従って、ビューのインポート時にSVGを処理するようにsvg-sprite-loaderが構成されました。







import twitterLogo from './logos/twitter.svg';
      
      





画像の内容は<symbol>



変換され、モジュールに転送されます。これにより、シンボルとスプライトを操作するためのクライアントコードが生成されます。 このコードは、プログラムの実行中に通常のモジュールとして呼び出されます。 結果のコードは次のようになります。







 //  ,          <symbol> import SpriteSymbol from 'svg-sprite-loader/runtime/symbol'; //  -,    SVG        import globalSprite from 'svg-sprite-loader/runtime/browser-sprite'; //     const symbol = new SpriteSymbol({ /* symbol data */ }); //     globalSprite.add(symbol); //      SpriteSymbol export default symbol;
      
      





したがって、最初はプレーンテキストであるSVGファイルは、フィールドid



viewBox



、およびcontent



を持つオブジェクトになり、後でマークアップ<svg><use xlink:href="#id"></svg>



viewBox



<svg><use xlink:href="#id"></svg>



ます。 ただし、このようなリンクが機能するには、すべてのキャラクターを含むスプライトがページの一部である必要があります。 すべての文字を格納するglobalSpriteシングルトンオブジェクトを覚えていますか? そのコードは次のようになります。







 import BrowserSprite from '…'; const sprite = new BrowserSprite(); document.addEventListener('DOMContentLoaded', () => { sprite.mount(document.body); }); export default sprite;
      
      





つまり、 DOMContentLoaded



イベントDOMContentLoaded



とすぐに、スプライトがページに自動的に挿入されDOMContentLoaded



。 1行のイメージインポートで、それをオブジェクトに変換し、スプライトを作成しました。スプライト自体は、必要なときに必要な場所に描画されます。 便利に。 ただし、シンボルを手動で参照する必要があります。







この問題は、テンプレートエンジンを使用して解決できます。 Reactの例を使用して、スプライトシンボルを描画するコンポーネントを作成します。







 // icon.jsx export default function Icon({glyph, viewBox = '0 0 16 16', className = 'icon', …props}){ return ( <svg className={className} viewBox={viewBox} {…props}> <use xlinkHref={`#${glyph}`} /> </svg> ); }
      
      





ローダーとの組み合わせで、その使用は次のようになります。







 import Icon from './icon.jsx'; import twitterLogo from './logos/twitter.svg'; <Icon glyph={twitterLogo.id} viewBox={twitterLogo.viewBox} />
      
      





便利に。 ただし、キャラクターのIDとviewBoxを指定する必要があります。 しかし、SVGをインポートするときに、返されるのはシンボルオブジェクトではなく、レンダリングにこのシンボルを使用するコンポーネントである場合はどうでしょうか。 これは、SVGイメージ上でバインディングを生成するNode.jsモジュールへのパスを示すruntimeGenerator



オプションのおかげで可能です。 このようなジェネレーターの例は、 ここにあります 。 次のコードが生成されます。







 import React from 'react'; import SpriteSymbol from 'runtime/symbol'; import globalSprite from 'runtime/global-browser-sprite'; import Icon from './icon.jsx'; const symbol = new SpriteSymbol({ /* symbol data */ }); globalSprite.add(symbol); export default function TwitterIcon({…props}) { return <Icon glyph={symbol.id} viewBox={symbol.viewBox} {…props} />; }
      
      





そして、画像をインポートすると、事前定義されたプロパティを持つReactコンポーネントがすでに返されます:







 import TwitterLogo from './logos/twitter.svg'; render( <div> <TwitterLogo width="100" /> <TwitterLogo fill="red" /> <TwitterLogo fill="blue" style={{width: 600}} /> </div>, document.querySelector('.app') );
      
      





便利に。 そして、これらすべてをインポートの1行で行います。







サーバー側のレンダリング



ブラウザでオンザフライでスプライトを作成することは確かに便利ですが、コードレンダリングUIがサーバー上で機能する場合はどうなりますか? DOMおよびブラウザイベントはありません。スプライトはどのようにレンダリングされますか? これらの目的のために、svg-sprite-loaderは、すべてのランタイム環境で機能する同形バージョンのスプライトの使用を提案します。 彼は環境について何も知らないので、手動でレンダリングを呼び出す必要があります。 サーバーでページをレンダリングする例:







 import template from 'page-view.twig'; import globalSprite from 'svg-sprite-loader/runtime/sprite'; //          id  const symbols = globalSprite.symbols.reduce((acc, s) => { acc[s.id] = s; return acc; }, {}); //      '<svg><symbol id="…">…</symbol>…</svg>' const sprite = sprite.stringify(); const content = template.render({ sprite, symbols });
      
      





スプライトを描画するには、 sprite



変数を表示し、 symbols



オブジェクトを使用してsymbols



を挿入する必要があります。







 // layout.twig <body> {{ sprite }} // pages/about.twig <svg viewBox="{{ symbols.twitter.viewBox }}"> <use xlink:href="#{{ symbols.twitter.id }}" /> </svg> </body>
      
      





Reactの場合、すべてがブラウザーと同じように機能し、インポート時にコンポーネントをコンパイルできます。







別個のファイルとしてのスプライト



しかし、マークアップで<svg><use … /></svg>



コンストラクトを<svg><use … /></svg>



できない場合、または多くの手直しが必要な場合はどうでしょうか? SPAを作成しない場合は、マークアップからではなくスタイルからインターフェイスイメージをインポートする方が論理的であるため、誰もがSVGをバックグラウンドイメージとして使用することにすでに慣れています。







この場合、特別なモードが提供されます。これはまったく異なる方法で機能し、追加のプラグイン(ローダーに付属)が必要です。 そのようなインポートがあるとします:







 .logo { backgroung-image: url(./logos/twitter.svg); }
      
      





ローダーはプラグインと組み合わせて次のことを行います。







  1. すべての画像は<symbol>



    変換され、スプライトに配置されます。スプライトは別個のファイル(デフォルトではsprite.svg)として作成されます。







  2. すべての画像インポートは、最後にシンボルのIDを持つスプライトパスに置き換えられます。


 .logo { backgroung-image: url(sprite.svg#twitter); }
      
      





このアプローチでは、 SVGスタック手法を適用できます。これは、Safari(モバイルおよびデスクトップ)および4.4.4までのAndroidブラウザーを除くすべてのブラウザーでサポートされています。 しかし、いつものようにポリフィルがあります。







自動設定



ローダーは、主なことを理解するのに十分な環境の知識を持っています。









これは、ほとんどの場合、ローダーのデフォルト設定で十分であることを意味します。







 //  webpack 1 module: { loaders: [ { test: /\.svg$/, loader: 'svg-sprite-loader' } ] } //  webpack 2 module: { rules: [ { test: /\.svg$/, loader: 'svg-sprite-loader' } ] }
      
      





他に何





参照資料






All Articles