本文書はwepack入門者に向けて公開した”入門者/初心者にもわかるwebpack5の基礎”の続きです。今回は、webpack.config.jsの設定方法、CSSスタイルシートをwebpackを使ってjsファイルにまとめるために必要なLoader(ローダー)について説明を行います。本文書を読み終えるとwebpackのLoaderとは何をするのか理解することができます。

前準備

webpackの動作確認を行うためにはnpmのインストールが事前に行われている必要があります。またnpmでwebpack, webpack-cliをインストールし、package.jsonのscriptsに以下のwebpackコマンドの設定が完了している環境で動作確認を行っています。


  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "build": "webpack --mode production,
    "watch": "webpack --mode development --watch"
  },

上記の設定がわからない場合は下記の文書を事前にお読みください。

webpack.config.jsの設定方法

wepackはwebpackコマンドのみで処理を行うことができます。そのため前回の文書では、webpackコマンドのみでファイルを束ねる機能の動作確認を行ったので今回はwebpackの設定ファイルであるwebpack.config.jsの設定について確認を行っていきます。

npx webpack -helpを実行するとwebpackコマンドに多数のオプションがあることが確認できます。設定ファイルであるwebpack.config.jsファイルを利用しなくてもLoaderの指定もコマンドラインのみで行うことはできます。
fukidashi

webpack.config.jsの作成

空のwebpack.config.jsファイルを作成します。


mac $ touch webpack.config.js

作成したwebpack.config.jsファイルに下記の内容を記述してください。


const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
}

entryでは元になるindex.jsファイルを指定し、webpack実行後にdistディレクトリの下に作成されるbundle.jsファイルをoutputで指定しています。

webpackの設定ファイルを使用しない場合の初期設定では、src/index.jsがentry、dist/main.jsがoutputに使われるファイル名と決まっています。webpack.config.jsファイルを利用するとファイル名やファイルの保存場所も自由に設定することができます。
fukidashi

webpack.config.jsファイルの1行目では、requireでnode.jsのpathモジュールの読み込みを行っています。pathモジュールはファイルパスを効率よく扱うためのユーティリティツールで以下のように利用することができます。

[path.resolveの使い方]
path.resolve(‘/foo/bar’, ‘./baz’);
// Returns(上記の実行で戻される値): ‘/foo/bar/baz’

webpack.config.jsファイルのpathで利用している__dirnameはスクリプトが存在するディレクトリを出力する変数です。pathモジュールのresolveメソッドに__dirnameとdistを入れることでpathには/distが設定されることになります。

index.jsにconsole.log(‘Hellow World”)など簡単なコードを記述した後にwebpackコマンドを実行しwebpack.config.jsの記述に誤りがないか確認を行います。エラーがでなければ設定ファイルの記述に誤りはありません。


console.log('Hello World');

jsファイルの更新の監視を行うnpm run watchコマンドの実行でも構いませんが処理完了後にdistフォルダにbundle.jsファイルが作成されていることを確認してください。


mac $ npm run dev

> test@1.0.0 dev /Users/mac/Document/test
> webpack --mode development

Hash: 242e97791fa2548e7e72
Version: webpack 4.31.0
Time: 95ms
Built at: 2019-05-18 20:51:59
    Asset     Size  Chunks             Chunk Names
bundle.js  3.8 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./src/index.js] 27 bytes {main} [built]

webpackの設定ファイルでの設定は元になるファイルや生成ファイルの名前やフォルダを指定するだけではなここから個別機能の設定を記述していくことになります。

CSSスタイルシートをまとめる

前回の文書では複数のJavaScriptファイルをwebpackを使って1つファイルにまとめられることを確認しました。今回はホームページ制作を行った経験のある初心者の人にとっても馴染みの深いCSSスタイルシートをwebpackを使ってJavaScriptファイルにまとめる方法を確認します。

webpackのLoader(ローダー)とは

webpackはJavaScriptファイルのみそのままの状態で取り扱うことができます。しかしJavaScriptファイル以外の他の言語で書かれたプログラムをwebpackで扱うことができません。JavaScript以外のファイルでもwebpackでも扱えるようにする場合にはLoader(ローダー)を利用する必要があります。Loaderは一つではなくそれぞれの言語や行いたい処理に対応するLoaderが存在します。

css-loader, style-loaderのインストール

CSSスタイルシートをwebpackで扱えるようにするためには、css-loaderとstyle-loaderが必要になります。2つのLoaderそれぞれの別々の役割を持っているのでどちらもCSSをwebpackで扱うためには必須のLoaderです。

css-loaderは、CSSスタイルシートの内容をJavaScriptファイルに埋め込むため(load)に利用されます。css-loaderを利用することでimportなどを理解し生成されるmain.jsファイルの中にCSSスタイルシートにあるcss情報が保存されます。style-loaderはJavaScriptファイルに埋め込まれたCSSの情報をhtmlのstyleタグに加える際に利用されます。生成されたbundle.jsファイルをHTMLで指定するとHTMLのheadタグの中にstyle-loaderが作成したstyleタグが追加されます。styleタグの中にはCSSのclass情報が入っています。

npm installでこの2つのパッケージのインストールを行います。


mac  % npm install css-loader style-loader --save-dev

added 17 packages, and audited 139 packages in 2s

20 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

npmの理解に不安がある人は下記の文書が参考になります。

CSSスタイルシートの作成

CSSによるスタイリングを行うclassを設定するためにdivタグをindex.htmlに追加します。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>webpack</title>
	<script src="dist/bundle.js"></script>	
</head>
<body>
	<div class="first-header">
		<h1>CSS Loadersを理解する</h1>
	</div>
</body>
</html>

追加したdivのfirst-headerクラスにCSSでスタイリングを行います。style.cssをsrcディレクトリの下に作成して下記のスタイルを書き込みます。当たり前ですがindex.htmlファイルからsytle.cssを指定しているわけではないのでstyle.cssファイルを作成しても何も変化はありません。


.first-header{
	background-color: red;
	color:white;
	padding:20px;
}

webpack.config.jsへのcss-loaderの追加

css-loader, style-loaderに関する設定はwebpack.config.jsで行います。 webpack.config.jsにmodule句を追加しルールを設定する必要があります。

拡張子にcssがついたファイルのみにstyle-loader, css-loaderを適用させるためtestを追加しています。useにはstyle-loaderとcss-loaderを追加しますが追加した順番も重要です。後ろのcss-loaderから実行されcss-loaderの処理後にstyle-loaderが実行されます。


const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }, 
  module:{
    rules:[
        {
            test:/\.css$/,
            use:['style-loader','css-loader']
        }
   ]
  }
}

index.jsでのcssファイルのimport

index.jsファイルで、cssファイルのimportを行う必要があります。importに指定するファイルは先ほど作成したstyle.cssです。今回は動作確認のためstyle.cssのimportとconsole.logしか記述していませんが、通常はJavaScriptで行いたいその他の処理もここに記述します。


import './style.css';

console.log('Hello World');

webpackの実行

ここまでの設定で、CSSファイルをbundle.jsファイルにまとめる準備が揃ったので、webpackを実行します。実行ログにはstyle.cssファイルに関する情報も表示されています。


 % npm run dev  

> test@1.0.0 dev
> webpack --mode development

asset bundle.js 20.5 KiB [compared for emit] (name: main)
runtime modules 937 bytes 4 modules
cacheable modules 8.12 KiB
  modules by path ./node_modules/ 6.58 KiB
    ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 2.19 KiB [built] [code generated]
    ./node_modules/style-loader/dist/runtime/styleDomAPI.js 1010 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/insertBySelector.js 1010 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js 286 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/insertStyleElement.js 261 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/styleTagTransform.js 333 bytes [built] [code generated]
    ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated]
  modules by path ./src/ 1.53 KiB
    ./src/index.js 51 bytes [built] [code generated]
    ./src/style.css 1.11 KiB [built] [code generated]
    ./node_modules/css-loader/dist/cjs.js!./src/style.css 379 bytes [built] [code generated]
webpack 5.52.0 compiled successfully in 351 ms

ブラウザでindex.htmlを開くとdivタグへ設定したスタイリングが反映されていることが確認できます。また、Chromeの開発ツールでみるとstyleタグがhtmlのheadタグの中に追加されていることも確認することができます。

css_loaderを利用してスタイル
css_loaderを利用してスタイル

bundle.jsの中身の確認

webpackによって生成されたbundle.jsの中身を確認してスタイル設定が埋め込まれているのか確認を行います。bundle.jsファイルを開いてclass名のfirst-headerを検索するとファイルの中にfirst-headerの文字列を見つけることができます。


Module\n___CSS_LOADER_EXPORT___.push[module.i, \".first-header{\\n\\tbackground-color: red;\\n\\tcolor:white;\\n\\tpadding:20px;\\n}\",

css-loaderを使うことでcssスタイルシートの内容がJavaScriptファイルに埋め込まれbundle.jsにまとめられていることがわかります。

sass-loaderの追加

webpackは確認した通りCSSを取り扱えるだけではなくSassをCSSへと変換する機能を追加することができます。CSSへの自動変換機能を利用するためにはここでもLoaderが必要となります。追加するLoaderはsass-loaderです。webpackの一連の処理の中にSassからCSSへの自動変換の機能を追加することでSassからCSSへの変換する作業の手間を減らすことができます。

Sassとは

CSSをより効率的に記述するために開発されたメタ言語です。CSSプリプロセッサとも呼ばれます。メタ言語、CSSプリプロセッサは馴染みのない単語かもしれませんが聞き覚えのない人はぜひこの機会に覚えてください。

Sassの詳しい設定方法はここでは省いていますが、Sassの主な機能の一つである変数を通してどのようにCSSの効率化につながるのかだけ確認しておきます。

下記のように変数名を$+任意の名前とし値を指定すると変数として利用することができます。変数を設定できることによるメリットを確認しておきます。例えばホームページの配色を設定する度に変数を定義し、残りのclassの中で変数を利用することで色の配色を変えた場合に変数の色を変更することですべてのclassにその変更を反映させることができます。個別にclass毎に変更するという手間が省けます。


$main_color: #FF0000;
$sub_color: #FFFFFF;

.first-header{
	background-color: $main_color;
	color: $sub_color;
	padding:20px;
}
SassにはSCSSとSassの2つの記述方法があります。本文書ではSCSSを利用し、ファイルの拡張子は.scssで作成します。
fukidashi

sass-loader, node-sassのインストール

sass-loaderを利用するためにはnpmでsass-loaderとnode-sassの2つのパッケージをインストールする必要があります。


mac $ npm install sass-loader node-sass --save-dev

webpack.config.jsへのsass-loaderの追加

sass-loaderのインストールが完了したら、webpack.config.jsにsass-loaderの情報を追加する必要があります。

webpack.config.jsファイルのCSSからの変更点は下記の2点です。

  • testの値をcssからscssに変更。
  • useの配列にsass-loaderの追加

これまでは拡張子がcssのものにuseのLoaderが適用されていましたが、下記設定ではscssの拡張子を持つファイルのみCSSに関連する3つのLoaderが適用されることになります。


test:/\.scss$/,
use:['style-loader','css-loader','sass-loader']

useの後ろ側にsass-loaderを追加したのは、css-loaderでcssをJavaScriptに埋め込む前にsass-loaderによりscssをcssに変換しておく必要があるためです。

useは後ろから順番に適用されていきます。適用するloaderだけではなく順番も重要です。
fukidashi

webpack.config.jsファイルはsass-loaderの追加により以下のようになりました。


const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }, 
  module:{
    rules:[
        {
            test:/\.scss$/,
            use:['style-loader','css-loader','sass-loader']
        }
   ]
  }
}

scssだけではなくsassも適用させたい場合はtestは下記のように変更を行います。


test: /\.(sass|scss)$/,

Sassファイルの作成

Sassファイルは下記のように作成します。ファイルはsrcディレクトリの下に保存し、拡張子は.scssにしてください。


$main_color: #FF0000;
$sub_color: #FFFFFF;

.first-header{
	background-color: $main_color;
	color: $sub_color;
	padding:20px;
}

index.jsファイルの更新

先ほどまではstyle.cssファイルをimportしていましたが、今回はstyle.scssファイルをimportします。


import './style.scss';

console.log('Hello World');

index.htmlファイルは下記の内容で作成します。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>webpack</title>
	<script src="dist/bundle.js"></script>	
</head>
<body>
	<div class="first-header">
		<h1>SCSS Loadersを理解する</h1>
	</div>
</body>
</html>

ここまでの設定でCSSからScssへの変更は完了です。

webpackの実行

npm run devコマンドでwebpackを実行します。


mac  % npm run dev

> test@1.0.0 dev
> webpack --mode development

asset bundle.js 20.9 KiB [emitted] (name: main)
runtime modules 937 bytes 4 modules
cacheable modules 8.2 KiB
  modules by path ./node_modules/ 6.58 KiB
    ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 2.19 KiB [built] [code generated]
    ./node_modules/style-loader/dist/runtime/styleDomAPI.js 1010 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/insertBySelector.js 1010 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js 286 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/insertStyleElement.js 261 bytes [built] [code generated]
    ./node_modules/style-loader/dist/runtime/styleTagTransform.js 333 bytes [built] [code generated]
    ./node_modules/css-loader/dist/runtime/api.js 1.57 KiB [built] [code generated]
  modules by path ./src/ 1.61 KiB
    ./src/index.js 52 bytes [built] [code generated]
    ./src/style.scss 1.19 KiB [built] [code generated]
    ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/style.scss 378 bytes [built] [code generated]
webpack 5.52.0 compiled successfully in 476 ms

実行後、ブラウザでindex.htmlファイルを確認してください。Scssで変数だった値が展開されて.first-classクラスに適用されていることを確認することができます。

scss-loaderの確認
scss-loaderの確認

まとめ

webpackでは、Loaderの使うことでJavaScript以外のファイルも扱えることを理解することができました。これ以外にもさまざまなLoaderが存在しLoader毎の機能を理解していく必要があります。今回は、WEB開発初心者にとって身近なCSS、SCSSを使うことでwebpackのLoaderがどんな処理をするためにあるのかがわかってもらえたかと思います。