【webpack】アセットの管理

この記事では、CSSや画像など、JavaScript以外のファイルをバンドルする基本的な方法を紹介します。

なお、より詳しく知りたい場合は、[公式ドキュメント](https://webpack.js.org/guides/asset-management/)を参照するのをおすすめします。

## 前提条件

以下手順を実施済み

[【webpack】webpack の導入](https://qiita.com/onkz/items/368535611379d1630c67)

## CSS の読み込み

JavaScript内で `import` 文を使用して CSS ファイルを読み込む場合、`style-loader` と `css-loader` をインストールして、設定を追加する必要があります。

```cmd
npm i -D style-loader css-loader
```

```js:webpack.config.js
module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ]
  }
};
```

:::note warn
`use` オプションのローダーは、後ろから順に読み込まれます。この場合 `css-loader` が先に読み込まれる必要があるため、順序を間違えないよう注意してください。
:::

これにより JavaScript 内で `import` 構文を使用して、`.css` ファイルを読み込むことが可能となります。  
具体的には、`import '*.css'` の内容は文字列化されてバンドルされ、HTML ファイルの `<head>` タグ内に `<style>` として挿入されます。

例として、`style.css` ファイルを追加して試してみます。

```css:src/style.css
.hello {
  color: red;
}
```

追加したファイルを `index.js` で読み込みます。また、CSS クラスを適用するためにコードを `functions.js` に追加します。

```js:src/index.js
...

import './style.css'

...
```

```js:src/functions.js
export function hello(v){
  ...
  elm.classList.add('hello');
  ...
}
```

最後に、ビルドコマンドを実行します。

```cmd
> npm run build
```

`dist/index.html` をブラウザで開いて、文字列が赤色になっていれば成功です。

:::note
### 各ローダーの役割について

- `css-loader`:JS ファイル内で `import` 構文を用いて記述された CSS ファイルを解釈して、ビルド時に JS ファイルに埋め込みます。
- `style-loader`: JS ファイルに埋め込まれた CSS の情報を、ビルドされた JS ファイルを読み込む HTML ファイルの `<head>` タグ内に追加します。

:::

## 画像の読み込み

webpack5は背景やアイコンなどの画像を、組み込みのアセットモジュールを使用してシステムに組み込むことが出来ます。

アセットモジュールを有効化するには、構成ファイルに以下を追加します。

```js:webpack.config.js
const path = require('path');

module.exports = {
  ...,
  module: {
    rules: [
      ...,
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
      },
    ]
  }
};
```

また、試しに画像ファイル `src/icon.png` ファイルを追加して、 `index.js` 及び `functions.js` にコードを追加してみます。

```js:index.js
import { hello, icon } from "./functions";

...

document.body.appendChild(icon());
```

```js:functions.js
...

import Icon from './icon.png';

export function icon(){
  const myIcon = new Image();

  myIcon.src = Icon;

  return myIcon;
}
```

コードを追加したら、ビルドコマンドを実行します。

```cmd
> npm run build
```

これで、`dist/index.html` をブラウザで開き、画像が表示されていれば成功です。

## フォントの読み込み

フォントなどのファイルも、アセットモジュールを使用して読み込むことが可能です。

まず、`webpack.config.js` に以下コードを追加します。

```js:webpack.config.js
const path = require('path');

module.exports = {
  ...,
  module: {
    rules: [
      ...,
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
    ]
  }
};
```

次に、プロジェクトの `src` ディレクトリにフォントファイルを追加します。ここでは、Google Fonts の [Roboto](https://fonts.google.com/specimen/Roboto) からダウンロードできる `Roboto-Regular.ttf` を使用します。

フォントファイルをプロジェクトに追加出来たら、CSS の `@font-face` 宣言を使用して組み込みます。

```css:style.css
@font-face {
  font-family: 'Roboto';
  src: url('./Roboto-Regular.ttf');
}

.hello {
  ...
  font-family: 'Roboto';
}
```

:::note
`@font-face` 宣言の中で使われている `url()` ディレクティブは、画像の場合と同様 webpack によって取得されます。
:::

ビルドコマンドを実行して、フォントが読み込まれているか確認します。

```cmd
> npm run build
```

`dist/index.html` をブラウザで開き、文字のフォントが変更されていれば問題ありません。

## データの読み込み

webpack は、標準でJSONファイルの読み込みをサポートしています。また、プロジェクトにローダーを追加することで、CSV・XMLなどのデータもインポートすることが可能となります。

まず、追加のローダーをプロジェクトに追加します。

```cmd
> npm i -D csv-loader xml-loader
```

追加のローダーを有効にするため、 `webpack.config.js` にコードを追加します。

```js:webpack.config.js
const path = require('path');

module.exports = {
  ...,
  module: {
    rules: [
      ...,
      {
        test: /\.(csv|tsv)$/i,
        use: ['csv-loader'],
      },
      {
        test: /\.xml$/i,
        use: ['xml-loader'],
      },
    ]
  }
};
```

プロジェクトの `src` ディレクトリに CSV 及び XML ファイルを追加します。

```csv:data.csv
to,from,heading,body
Mary,John,Reminder,Call Cindy on Tuesday
```

```xml: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>
```

追加したファイルを読み込むには、`import` 構文を使用します。`src/index.js` を以下のように編集します。

```js:index.js
...

import xmlData from './data.xml';
import csvData from './data.csv';

...

console.log(xmlData, csvData);
```

ビルドコマンドを実行して、データの読み込みを適用します。

```cmd
> npm run build
```

`dist/index.html` をブラウザで開き、コンソールに読み込んだデータが表示されていれば成功です。