【webpack】イメージ画像ファイルのバンドル

Webページ作成では画像ファイルを取り扱う事はよくあります。
webpack実行時に、使用する画像ファイルもdistファイルに出力されると便利です。

今回はwebpack実行時に、使用する画像ファイルをdistディレクトリへ出力させます。

なお、前回までの内容の続きになります。

概要

今までは nodejs のパッケージを使用して、cssファイルのような jsファイルとは違うファイルをバンドルしていました。webpackではイメージ画像の類(アセットファイル)はローダーを使用せずともバンドルが可能です。

構成

今回はサンプルとしてsrcディレクトリ以下に image ディレクトリを作成し、このディレクトリに適当に2つの画像ファイルを配置しました。なお、ディレクトリ名やファイル名は任意で構いません。

また、jsディレクトリ以下に image_list.js ファイルを作成しました。なお、こちらもファイル名は任意で構いません。

.
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── image
│   │   ├── bg_image_org.png
│   │   └── play_icon.png
│   ├── js
│   │   ├── index.js
│   │   ├── test.mjs
│   │   └── image_list.js
│   ├── css
│   │   └── style.css
│   └── index.html
└── webpack.config.js

style.css

今回は cssから、画像ファイル bg_image_org.png を background-image プロパティを使用して読み込ませます。

.box {
  background-image: url(../image/bg_image_org.png);
}

index.html

index.htmlからは play_icon.pngをimgタグを使用して読み込ませます。

      <div class="box">
        <h1>Hello, Webpack!</h1>
        <img src="image/play_icon.png">
      </div>

image_list.js

新たに作成した image_list.js にはバンドルさせたい画像ファイルをimportさせます。
今回は play_icon.png を import します。なお、bg_image_org.pngをimportさせない理由は後ほど説明します。

import '../image/play_icon.png'

webpackの設定

webpack.config.js を以下のように修正します。

'use strict'

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: 'development',
  entry: './src/js/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    assetModuleFilename: "image/[name][ext]",
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin()
  ],
  module: {
    rules: [
      {
        test: /\.(css)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            // Interprets `@import` and `url()` like `import/require()` and will resolve them
            loader: 'css-loader'
          }
        ]
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: "asset/resource"
      }
    ]
  }
}

説明

今回は output に assetModuleFilename を指定してイメージ画像の出力先を指定します。

  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    assetModuleFilename: "image/[name][ext]",
  },

そして、画像ファイルの拡張子をバンドルさせるルールを追記します。

  module: {
    rules: [
      {
        ....(省略)
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: "asset/resource"
      }
    ]
  }

webpackの実行

webpackを実行します。

npx webpack

distディレクトリは以下のようになります。imageディレクトリが作成され、そのディレクトリ以下に画像ファイルが存在する事が分かります。

dist
├── image
│   ├── bg_image_org.png
│   └── play_icon.png
├── index.html
├── main.css
└── main.js

dist以下のindex.htmlをブラウザで表示させます。

適当な画像を使用しているので少し分かりにくいですが、三角アイコンはimgタグを使用して読み込んだ画像 play_icon.png になります。
背景画像はbackground-image プロパティを使用して読み込んだ画像 bg_image_org.png になります。

background-image プロパティ

なぜ、background-image プロパティを使用して読み込んだ画像ファイル bg_image_org.png は、image_list.js に imoprtを記載しなくても良いかというと、index.js が cssファイル(style.css)をimportしているからです。style.cssは bg_image_org.png を background-image プロパティを使用して読み込んでいます。この為、bg_image_org.png はバンドル対象になります。

一方、index.html は imgタグを使用して画像ファイル play_icon.png を読み込んでいますが、index.htmlはindex.jsからimportされていません。したがって、index.htmlでimgタグを使用している画像ファイルはバンドル対象になりません。なので今回は、image_list.js を作成し、image_list.js からplay_icon.pngをimportし、さらに index.js が image_list.js を読み込むようにしました。これで index.jsからimportを辿って画像ファイルをバンドルさせる事が出来ます。

最後に

特にありません。

© DeNnie.Lab All Rights Reserved.