webpackを用いてhtml、css、typescriptの複合環境をビルドするときに、CSSファイルの取り込み方を調べたので記録




動作を確認した環境


バージョン確認コマンド:
npm -v
npx webpack -v
npm:9.5.1
webpack:5.90.3


各ファイルの配置


CSSをbuildするのに編集を行うファイルは以下の3つです。
.
├── bundler
│   ├── babel.config.js
│   └── webpack.config.js   // 編集するファイル
├── dist                    // webpack build後の出力ディレクトリ
│   ├── index.html
│   ├── main.css
│   └── script
│       └── bundle.js
├── package.json
├── package-lock.json
├── src
│   ├── index.html
│   ├── script
│   │   └── app.ts          // 編集するファイル
│   └── stylesheets
│       └── style.css       // 追加するファイル
└── tsconfig.json
最終的にstyle.cssがwebpackによりビルドされて、distディレクトリ以下のmain.cssとして出力されます。


webpack.config.jsでCSSを使う記述


webpackでCSSを扱うのに以下4つをインストールします。

インストールコマンド:
npm install --save-dev css-loader style-loader
npm install --save-dev mini-css-extract-plugin
npm install --save-dev css-minimizer-webpack-plugin
npm install --save-dev webpack-remove-empty-scripts
webpack.config.js
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');         // CSSの取り込み
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');   // 不要なJSファイルの削除

module.exports = {
  module: {
    rules: [
      // CSS
      {
        test: /\.css$/,
        use:
        [
            MiniCSSExtractPlugin.loader,
            'css-loader'
        ]
      },
    ]
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new MiniCSSExtractPlugin(),
    new RemoveEmptyScriptsPlugin(),
  ]
};

このようにwebpackのコンフィグレーションファイルへ記述します。

この記述により、CSSがminify(サイズを小さく)してjavascriptファイルとは別にファイルを分割した状態でファイルが作成されるらしいです。


typescript(javascript)上の記述


CSSファイルはHTML上ではなく、各バンドルファイルでビルド対象のTypescript(javascript)ファイル先頭で以下のようにimportすることで、取り込みます。

typescript:
import '../stylesheets/style.css'

typescript/javascrptのファイルから見た時の相対位置でパスを指定しています。



webpack.config.js全文


説明に取りこぼしがあってはダメですし、出し惜しむものでもないので、一応webpackconfig.jsの全文を掲載しておきます。

パスやファイル名などは適したものに置き換えてご確認ください。

webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); 
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');

module.exports = {
  mode: 'development',
  entry: ['./src/script/app.ts'],

  output: {
    filename: 'script/bundle.js',
    path: path.resolve(__dirname, '../dist')
  },

  resolve: {
    extensions: ['.tsx','.ts', '.js'],
  },

  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
      // 画像
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]'
        }
      },
      // CSS
      {
        test: /\.css$/,
        use:
        [
            MiniCSSExtractPlugin.loader,
            'css-loader'
        ]
      },
    ]
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html'
    }),
    // ファイルをコピーするプラグインの追加
    new CopyWebpackPlugin({
      patterns: [
        {
          from: './src/images',
          to: 'images',
        },
        {
          from: './src/assets',
          to: 'assets',
        },
        // GLTFのLoaderもdist内に含める
        {
          from: './node_modules/three/examples/jsm/libs/draco/',
          to: 'draco',
        },
      ],
    }),
    new MiniCSSExtractPlugin(),
    new RemoveEmptyScriptsPlugin(),
  ]
};

一部上で紹介したファイル構造と対応していないので、ご注意ください。



参考:

以上

このエントリーをはてなブックマークに追加