カルキチブログ

webpackに登場する用語をなんとなく理解する

ここ最近はバックエンド系の記事が続いていた気がしたので、久しぶりにフロント系の記事を書いてみました。

フロントエンド開発で避けて通れないのものといえばwebpackがありますが、webpackは設定項目が多い上に仕組みを理解するのが大変です。

僕自身今でこそ基本的な設定なら書けますが、初めてwebpackの設定ファイルを見た時は「こんなの理解してる奴ら正気の沙汰じゃないやんw」みたいな感じに思いました。

今回の記事では、最低限Webpackを理解するのに必要な設定項目について解説してみました。

ちなみにですが、以下のことについては解説はしていません。

  • webpackの設定方法
  • webpackの使い方
  • webpackの高度な知識(あくまで基本のみ)

そもそもwebpackとはなんなのか

webpackとは簡単に説明すると、複数のCSSやJSを一つのファイルにまとめて圧縮して出力したり、SCSSやTypeScriptなどそのままではブラウザで読み込むことができないコードをブラウザで読み込むことができる形に変換するためのツールです。

webpackはCSSやJSを1つのファイルに圧縮して出力することで、HTTPリクエストを削減し、サイトやアプリケーションの表示速度を落ちにくくすることができます。

サーバに対して10回リクエストを飛ばすのと、1回リクエストを飛ばすのでは、後者の方が早く処理が終わりそうですよね?

webpackを使うと、分割されたCSSやJSを全部一つに結合することができます。

また、CSSやJSを複数に分割することでコードの見通しが良くなるので、保守性の高いコードを書くということにもつながります。

もう一つ代表的な用途は、JavaScript以外の言語のコンパイル(変換)です。

コンパイル対象になることが多い言語としては、SCSSやTypeScriptなどが挙げられますが、SCSSやTypeScriptは当然のことながらブラウザでそのまま読み込んだり、実行することはできません。

CSSでセレクタをネストして書いたり、JSでinterfaceを使ってクラスやオブジェクトの型を指定したりしても、ブラウザは書かれたスタイルやコードを理解することはできません。

webpackについて調べると、バンドラーやコンパイルなどややこしい用語がちょくちょく出てきますが、とどのつまり、やっている処理は複数ファイルのまとめと圧縮、ブラウザで扱うことのできない言語をブラウザが理解できる形式に変換しているだけだったりします。

→だけとかいうとちょっと怒られそうですが、、、

これだけは覚えておきたいor理解しておきたい用語について

webpackを使おうとすると様々な用語が出てきますが、出てくる用語を一つ一つ全て理解するのはとても大変です。

全て理解して覚えるというのは多分無理なので、これだけは覚えておきたいor理解しておきたいという用語をピックアップして解説していきたいと思います。

entry

名前そのまま、処理の起点になるファイルの指定をここで行います。

下記のサンプルコードだと、webpack-config.jsと同じ階層にあるsrc/index.tsxが起点になります。

module.exports = {
  // 処理の起点になるファイルを指定(相対パスでいける)
  entry: './src/index.tsx',
}

公式を見た感じ、配列やオブジェクトでも指定できるっぽいですが、文字列で指定することが多い気がします。

output

これも名前そのまま、処理を行ったファイルを出力するディレクトリを指定します。

ただ、こちらは出力するファイルを絶対パスで指定してあげる必要があります。

// パスモジュールを読み込む
const path = require('path');

module.exports = {
  entry: './src/index.tsx',
  output: {
    // webpackの設定ファイルがある場所を絶対パスで指定
    path: path.resolve(__dirname, 'dist'),
    // ファイル名を指定
    filename: 'bundle.js',
  },
}

ポイントは、const path = require('path');でファイルパスを操作するためのパスモジュールを読み込んでいる部分です。

pathモジュールはNode.jsの標準モジュールなので、npmやyarnでインストールしなくても使うことができます。

path.resolve(__dirname, 'dist')は、filenameで指定しているbundle.jsを絶対パスで取得するという処理を行っています。

path.resolve()とか__dirnameあたりで、絶対パスに変換する処理を行っているらしいのですが、解説できるだけの知識がなく解説できそうにないので、今回は省きます。

興味がある方はこのあたり記事を読んでいただけたらと思います。

https://ocws.jp/blog/post1825/

https://nodejs.org/api/path.html#path_path_resolve_paths

ちなみにですが、path: __dirname + '/dist'path.join(__dirname, 'dist')でも指定できそうです。

https://webpack.js.org/concepts/output/#root

https://stackoverflow.com/questions/35048686/whats-the-difference-between-path-resolve-and-path-join

mode

ぶっちゃけ入れるかどうか迷ったのですが、これもまあ重要なので一応、、、

modeでは、Webpackを実行する際のモードを指定することができます。

const path = require('path');

module.exports = {
   // モードの設定を行う
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
}

development、production、noneの3種類のモードが存在しますが、使用頻度が高いのは、developmentとproductionの2つかなと思います。

上記2つの違いはこんな感じです。

  • development・・・コードの圧縮・最適化は行われないが読みやすい
  • production・・・コードが圧縮・最適化されて出力される

開発する時はdevelopmentで、本番反映するときはproductionが良さそうです。

まあ、当たり前っちゃ当たり前ですね。

module

moduleとは、ローダーと呼ばれる個々のファイルに対して実行する機能を設定するものです。

個人的には、webpackをややこしくしているのはこのmoduleだと思います。

なぜややこしいかというと、とにかくできることが多すぎるからです。

いくつか具体例を挙げてみますと、こんな感じです。

  • SCSSをCSSに変換
  • SCSS以外のCSSメタ言語(Less、Stylus)をCSSに変換
  • TypeScriptをJavaScriptに変換
  • ES6の形式で書かれたJavaScriptを古いブラウザでも読み込めるように、ES5に変換
  • PugやEJSなどのテンプレートエンジンをHTMLに変換
  • 画像もCSSやJSと一緒にまとめる

できることがいっぱいあります。

全部覚えるのはしんどいので、使用頻度の高いライブラリの使い方と設定だけ知っておけば最初のうちは十分だと思います!

ローダーの読み込ませ方ですが、ローダーは以下のように設定して読み込ませることができます。

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  // ローダー
  module: {
    rules: [
      {
        // 処理の対象となるファイルを指定する
        // 正規表現が使用できる
        test: /\.ts|tsx$/,
        // 使用するローダーを指定
        use: 'ts-loader',
        // node_modules配下は対象外
        exclude: /node_modules/,
      },
    ],
  },
}

ローダーを使うためには、Webpack本体以外にも使用するローダーをインストールする必要があります。

ReactでTypeScriptを扱う場合は、ts-loaderと呼ばれるローダーが必要です。

npm i -D ts-loader

ts-loader以外でよく出てくるローダーだと以下のようなローダーがあります。

  • CSSを扱う場合・・・css-loader
  • SCSS扱う場合・・・sass-loader
  • CSSとJSをがっちゃんこ・・・style-loader
  • Babel使いたい・・・babel-loader

babel-loaderは、babel-loader以外にも@babel/coreと@babel/preset-envが必要そうです。

https://github.com/babel/babel-loader

plugins

プラグインはWebpackの機能をさらに拡張するために使用されます。

プラグインもモジュール同様できることがとても多いです。

例えばですが、terser-webpack-pluginというプラグインを使用するとJavaScriptを圧縮(ミニファイ化)して出力することができます。

const path = require('path');
// プラグインを読み込む
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.ts|tsx$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
   // プラグインの設定
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          output: {
            comments: false,
          },
        },
      })
    ],
  },
}

プラグインを利用するときもローダーと同じように、npmやyarnでインストールする必要があります。

npm i -D terser-webpack-plugin

プラグインの種類も非常に豊富で、僕が知っている範囲だと以下のようなプラグインがあります。

  • CSSを別ファイルとして出力する
  • webpackを利用して生成したJavaScriptやCSSを埋め込んだHTMLを生成する
  • jQueryを読み込ませる(WebpackでバンドルされるためCDNを使う必要がなくなる)
  • 出力されたファイルの中身を可視化したHTMLを出力する

出力されたファイルの中身を可視化したHTMLを作成するプラグインは最近知ったのですが、webpack-visualizerというプラグインを使うとできるらしいです。

https://github.com/chrisbateman/webpack-visualizer

まとめ

ではまとめです。

  • webpackは、複数のCSSやJSを一つのファイルにまとめて圧縮して出力したり、SCSSやTypeScriptなどブラウザで読み込むことができないコードをブラウザが読み込むことができる形に変換できるツール
  • とりあえずは、entry、output、mode、modules、pluginsあたりを押さえとけば最低限は使える

今回の記事では、本当にwebpackの最低限の知識だけピックアップしてまとめてみました。

この記事では、webpackの設定方法とかに関しては触れていないので、この記事だけでwebpackの設定ファイルを0から書いて、コードの最適化やコンパイルができるようになるかといえば、多分無理だと思います。

そこらへんも本当はまとめたかったのですが、そこまで入れると今回書いた文字数の倍以上の文字数が必要になりそうなので、今回は断念しました。

おまけ

僕自身webpackに関しては、ここでまとめていること+αくらいの知識しか持ち得ていませんが、正直なんとかはなっています。

webpackはとにかく設定項目がいっぱいありますが、entry、output、mode、modules、pluginsあたりはQiitaとか他の技術ブログを読んでてもよく出てくる印象があったので、「こいつらがwebpackの核じゃね!?」って勝手に思い、今回はこの5個に絞って解説をした記事を書いてみました。

久しぶりに文字をいっぱい打ったので、まあまあ疲れました。

多分3日くらいかけてこの記事書きました。