【webpack速習】vol.2: Asset Management
今回は下記ページの要点をまとめていきたいと思います。
- webpackが登場する前は、Grunt や Gulp などを使ってJavaScript ファイル以外の画像のような他のアセットを処理して、
/src
フォルダから/dist
または/build
ディレクトリに移動していた。 - 同じ考え方がJavaScriptモジュールにも使用されたが
webpack
のようなツールはすべての依存関係を動的に束ねる(依存関係グラフを作成する) - webpackの優れた機能の1つが、JavaScript以外に、他のどんな種類のファイルも含めることができる
- JavaScriptモジュールのように明示的な依存関係の解決が、他のファイルにも適用できる
CSSを読み込む
JavaScriptモジュール内からCSSファイルをインポートするには、style-loader
と css-loader
をインストールして、webpack.config.js のモジュール設定に追加する。
yarn add style-loader css-loader --dev
▼ webpack.config.js
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, // ↓↓↓ ここから追加 ↓↓↓ module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } };
test
プロパティに書かれた正規表現を使ってどのファイルを探し、特定の Loader を提供すべきかを決定する。
この場合だと、.css で終わるファイルはすべて style-loader と css -loader に提供されて処理される。
▼ src/style.css
.hello { color: red; }
▼ src/index.js
import _ from 'lodash'; import './style.css'; // 追加 function component() { let element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); element.classList.add('hello'); // 追加 return element; } document.body.appendChild(component());
これで yarn build
を実行してブラウザで index.html
を見て Hello webpack
が赤字になっていればOK。
補足
- css-loader を使わないと、JavaScriptファイル内で CSSを import できない(ビルド時に
import './style.css';
がエラーになる) - style-loader を使わないと、スタイルが適用されない。
- style-loader を使うことで、
import './style.css';
の内容が、head
要素内に<style>
タグとして出力される
- style-loader を使うことで、
画像の読み込み
file-loader
をインストールする
yarn add file-loader --dev
▼ webpack.config.js
// 略 module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ] }, // ↓↓↓ 追加 ↓↓↓ { test: /\.(png|svg|jpg|gif)/, use: [ 'file-loader', ] }, ] },
これにより、index.js に依存する 画像ファイルが処理できるようになる。
▼ src/index.js
// 略 import Icon from './icon.png'; function component() { // 略 const myIcon = new Image(); myIcon.src = Icon; element.appendChild(myIcon); return element; }
▼ src/style.css
.hello { color: red; background: url('./icon.png'); /* 追加 */ }
yarn build
を実行すると、/src
内の icon.png
が、ランダムな文字列のファイル名(自分の場合は ec8ccebd91480268a89ec15f8f2c43be.png
)で /dist
内に出力される。
ブラウザで表示確認を行うと、appendされた画像、スタイルで指定された背景画像ともに、画像パスが生成されたランダム文字列のファイル名を参照するようになっている。
Icon
を './icon.png' からインポートすると、その画像が処理されて出力ディレクトリに追加され、Icon
変数には処理後のその画像の最終的なURLが含まれる。- css-loader を使用すると、CSS内のURL(
'./icon.png'
)に対しても同様の処理が行われる。- Loader はこれがローカルファイルであることを認識し、
'./ icon.png'
パスを出力ディレクトリ内の画像への最終パスに置き換える。
- Loader はこれがローカルファイルであることを認識し、
- 画像を縮小し最適化するためにどうやればいいかは、image-webpack-loaderとurl-loaderをチェック
フォントファイルを読み込む
フォントも基本、画像と同じく file-loader
で処理する
▼ webpack.config.js
// 略 module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', ] }, { test: /\.(png|svg|jpg|gif)/, use: [ 'file-loader', ] }, // ↓↓↓ 追加 ↓↓↓ { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader', ] }, ] },
フォントの扱いについて詳しい参考記事: survivejs.com
csvやxmlなどのデータファイルを読み込む
JSON
は標準でサポートされているため、デフォルトでインポートできる。
csv、tsv、xmlをインポートするには csv-loader
xml-loader
を使う。
yarn add csv-loader xml-loader --dev
▼ webpack.config.js
// 略 module: { rules: [ // 略 // ↓↓↓ 追加 ↓↓↓ { test: /\.(csv|tsv)$/, use: [ 'csv-loader', ] }, { test: /\.xml$/, use: [ 'xml-loader', ] }, ] },
▼ src/data.xml
<?xml version="1.0" encoding="UTF-8"?> <note> <to>Mary</to> <from>John</from> <heading>Reminder</heading> <body>Call Cindy on Tuesday</body> </note>
▼ src/data.json
[ { "id": 1, "name": "Taro", "age": 20 }, { "id": 2, "name": "Bob", "age": 35 } ]
▼ src/index.js
// 略 import xmlData from './data.xml'; import jsonData from './data.json'; function component() { // 略 console.log('xmlData :', xmlData); console.log('jsonData :', jsonData); // 略 }
yarn build
実行してブラウザのconsoleで確認できればOK。
※これは D3.js のようなデータ視覚化を実装するときに特に役に立つとのこと。
ページ読み込み時にajaxで取得する代わりにビルドプロセス中にロードしておけばすぐに使える。
グローバルなアセット
モジュールとアセットをグループ化することで、そのひとまとめをそのまま他の所で流用できるようになる。
たとえば下記の構造の場合、/my-components
で使われるアセットはすべて同ディレクトリ内にあるので、移植性が高い。
/components |– /my-component | |– index.jsx | |– index.css | |– icon.svg | |– img.png