こまぶろ

技術のこととか仕事のこととか。

フロントエンド弱者が腹を括ってWebpackに触ってみた

前回UdemyのVue.jsのコースについての記事を書きましたが、続きがなかなか視聴できていないので、今週はそれとは違う内容になります。少々お待ちください・・・。

さて、ブログを始めたくらいの時期からこれまで、フロントエンドの勉強を細々と続けてきました。

  • GitHub Pagesで静的Webサイトを公開したり

ky-yk-d.hatenablog.com

  • twitter:cardやog:imageを設定してみたり

ky-yk-d.hatenablog.com

  • Dynamo DBに繋いでみたり

ky-yk-d.hatenablog.com

と、少しずつ知識は広がってきていますが、その中で、チラチラと目に入りながらも避けてきたものがあります。

それは、Webpackです。

公式のホームページかっこいいですね。

webpack.js.org

単にWebサイトの基本やVue.jsの文法を学ぶだけなら、Webpackなどのモジュールバンドラーを使う必要はないのですが、

  • Vue.jsの勉強をしていると途中からvue-cliが導入されたり
  • 使おうとしているライブラリのサンプルがWebpack前提だったり

と、ここから先に進むにはブラウザでそのまま動くファイルだけでは限界があるなと感じ、Webpackの勉強を始めることにしました。

例によって、山田祥寛さんの書籍を見ながらぽちぽちやりまして、ソースコードGitHubに上げていっています(サンプルコードそのままではありません)。

速習webpack 速習シリーズ

速習webpack 速習シリーズ

github.com

まだ、書籍も途中なのですが、基本的なファイルのローダーを扱うところまでできましたのでまとめてみます。まだ理解が不十分なので、間違ったことを書いているかもしれません。お気づきの方はコメントくださると幸いです。

Webpackを導入する

Webpackとは何か

「モジュールバンドラー」です。JavaScriptスタイルシート、画像ファイルなどをまとめるツールとのことです。モジュールバンドラーを利用するメリットとしては、以下のようなものが挙げられています。

  • 依存関係の解決
  • リクエスト数の抑制
  • ソースの可読性の向上・グローバル汚染、名前の競合の回避

個人的な経験としても、htmlファイルの中に<script>タグでJSファイルを埋め込んでいくときに、記述の順番を間違えて動作しない(先に読み込んだJSから後に読み込むJSを利用していた)という経験をしており、これが増えてくるとヤバそうだと感じていました。かといって、ひとつのファイルに全部書き込むのは嫌なので、モジュールシステム、モジュールバンドラーの出番というわけですね。

モジュールバンドラーのなかでも、Webpackは広く採用されているものです。『速習Webpack』では、Webpackの長所として下記のものを挙げています。

3つ目の理由に関連したものかもしれませんが、採用実績が豊富であるため、試したいライブラリのサンプルが見つけやすいのもメリットではないかと感じています。

Webpackをインストールする

それでは、Webpackをインストールしていきます。npmを利用します。

ターミナル

> cd プロジェクトのパス
> npm
> npm init -y # -y は規定の値で設定ファイルを作成
# package.jsonが生成される
> npm install --save-dev webpack webpack-cli
# --save-dev はpackage.jsonにインストールするパッケージの情報を記録するオプション
# webpack-cli はwebpackコマンドを実行するために必要

package,jsonはNode.jsの設定ファイルで、依存関係などを記載しておくと別の環境で必要なライブラリを用意したいときに便利(npm installだけで構築できる)らしいです。

qiita.com

Webpackがインストールできたら、下記のような構成を作ります。

.
├── node_modules   ←npmでインストールしたライブラリが置かれる
│
├── dist ← バンドルしたファイルが出力される
│   └── index.html ←生成したJSファイルを呼び出すhtml
│
├── src ← Webpackによってバンドルされる対象のファイル
│   └── index.js ←エントリーポイント
│
├── package.json
│
└── webpack.config.js

このような構成を作って、npx webpackを実行すると、dist配下にmain.jsが生成されます。これがバンドルしたファイルです。npx [パッケージ名]で、ローカルのnode_modules内のパッケージを実行するコマンドです。

qiita.com

ちなみに、エントリーポイントと出力場所はデフォルトでそれぞれ、/src/index.js、/dist/main.jsになっているようですが、下記のような設定ファイルを作成することで変更することが可能のようです。このwebpack.config.jsは、ローダー等を追加する際にも必要になってきます。

webpack.config.js

module.exports = {
    mode: 'development', // productionを指定すると実行効率の良いコードを生成する
    entry: './src/index.js',
    output: {
        path: `${__dirname}/dist`,
        filename: 'main.js'
    },
/* 後略 */

開発サーバーの導入

静的Webサイトを作るだけであれば、上記のnpx webpackコマンドを実行してから/dist/index.htmlを開けばよいのですが、いちいちビルドするのはだるいので、開発サーバーを導入します。ホットリロードってやつですね。

ターミナル

npm install --save-dev webpack-dev-server
# 開発サーバーがインストールされる

webpack.config.js

module.exports = {
  /* 中略 */
  devServer: {
    contentBase: './dist'
  },
};

[プロジェクトルート]/dist配下のファイルがコンテンツとして公開されるということですね。

次に、開発サーバーを起動するためのコマンドにショートカットを設定しておきます。package.jsonを編集します。ここではビルド用のショートカットも設定しています。

package.json

"scripts": {
    "start": "webpack-dev-server  --open",
    "build": "webpack --config webpack.config.js"
},

こうしておくと、npm startコマンドで開発サーバが起動します。package.jsonscriptsに記載した内容はnpm run hogehogeで呼び出せるようになりますが、startは特殊らしく、単にnpm startで起動できるようになります。

ローダー

モジュールバンドラーとしてのWebpackのコアな機能は、JavaScriptのモジュールをバンドルすることなのですが、ローダーを用いるとCSSや画像ファイルをモジュール化して、Webpackのバンドルの対象とすることができます。

山田さん曰く、

webpackを学ぶということは、ローダーを学ぶことである

とのことです。書籍では様々なファイルに対応したローダー(スタイルシート、画像、Webフォント、CSVJSON、HTMLなど)を紹介していますが、スタイルシートに関わるものだけご紹介します。

スタイルシートのバンドル

css-loaderによってスタイルシートを読み込み、style-loaderによって<style>要素として埋め込みます。いずれも、npm installでインストールします。インストールしたローダーは、webpack.config.jsに記載します。

webpack.config.js

module.exports = {
/* 中略 */
    module: {
        rules: [
            // スタイルシートを処理するローダー
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

use要素で指定したローダーは、逆順に処理されるので、上記の設定によって

  • 拡張子が.cssのファイルに対して、
  • css-loaderでモジュール化して、
  • style-loaderでページに埋め込む

という処理が施されることになります。エントリーポイントである/src/index.jsから、import './hogehoge.css;という形でモジュールとして読み込むことができます。

外部ファイルとして出力する場合について

スタイルを<style>タグで埋め込むのではなく外部ファイルとして出力して利用したい場合には、style-loaderは使えません。『速習Webpack』では、この用途のために、extract-text-webpack-pluginを用いています。

github.com

しかし、これはまさにこの記事を執筆していて気づいたのですが、Webpack 4 以降ではこのプラグインは非推奨となっているようです。

docs(readme) WP4 deprecation for css. Link to MiniCSSExtractPlugin (#… · webpack-contrib/extract-text-webpack-plugin@0b69b72 · GitHub

現在では、mini-css-extract-pluginがWebpack 4 で利用されるべきプラグインとされています。こちらについては使ってみていないのですが、余裕があれば別途使用してみて記事にするかもしれません。

github.com

その他のファイルのバンドル

バンドル対象としたいファイル形式と、紹介されているローダーだけ記載しておきます。

  • 画像ファイルのバンドル
    url-loaderを用います
  • フォントファイルのバンドル
    file-loaderを用います
  • JSONファイルのバンドル
    気味の悪い拡張子のファイルですが、Webpackは標準対応しているのでローダー不要です
  • CSV/TSVファイルのバンドル
    csv-loaderを用います
  • HTMLファイルのバンドル
    html-loaderを用います
  • XMLファイルのバンドル
    xml-loaderを用います

おわりに

今回、WebpackをWebpackとして勉強してみて、使い方はなんとなくわかりました。ホットリロードが便利なので、これからは積極的にWebpackを用いて開発していこう!と思いました。

  • Node.js
  • モジュール
  • ES2015
  • Sass

などについても、Webpackを使いながら勉強していこうと思います。UdemyのコースでもWebpack使うみたいなので、楽しみですね。