webpack.config.js の書き方をしっかり理解しよう
2020/07/047 分で読める記事 — In プログラム

はじめに


みなさん、こんにちは
目標15分でサウナ入りつつ、8分後出てくるを繰り返すサウナ芸人:ギノキンです。

最近Reactの参考書を買って勉強しているのですが、参考書勉強あるあるで「できた気になる」を防止すべく。
理解せずににスルーしていた webpack.config.js について調べてみました。

サウナは8分で出てしまいますが、こちらの記事はより詳細に根気を入れて説明しています!

では、、早速↓↓

webpack.config.js について


僕の中で少し苦手なイメージのある webpack について、改めて向き合って理解していこうと思います。

webpack に苦手意識がある人のほとんどは、この webpack.config.js について理解していない人がほとんど。
なので、今回は下記の webpack.config.js について丁寧に説明していきます。

//webpack.config.js

const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: {
    index: path.join(__dirname, 'src', 'index.js')
  },
  output: {
    path: path.join(__dirname, 'out'),
    filename: 'main.js'
  },
  devtool: 'cheap-module-eval-source-map',
  target: 'node',
  module: {
    rules: [
      {
        test: /.js$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    externalPlugins
  ]
}


entry と output


結論から言うと、、
entry: は、webpackがビルドする際に開始点となるJSファイルを設定しています。
output: は、ビルドファイルの設定。どこにどのようなファイルを出力すればよいか設定しています。

具体的にみていきます。

//webpack.config.js

const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: {
    index: path.join(__dirname, 'src', 'index.js')
  },
  output: {
    path: path.join(__dirname, 'out'),
    filename: 'main.js'
  },
...
}


entryの設定


早速説明していきます。
簡単に理解できますので、安心してください(笑)

ここでは、webpackがビルドした際に
./src/index.js というファイルを探して読み込んでね。」という設定をしています。

まず path.join でパスを連結してくれていて、上記だと ./src/index.js というパスにしてくれています。

これを使うメリットとしては、 macやwindowsなどの開発環境によって /¥ になったりするんですけど、それを防ぐことができます。
そして Node.js の標準モジュールの path を読み込ませて使用しているので、 path.join として使用できています。

__dirnameNode.js で用意されているグローバル変数で、現在実行中のソースコードが格納されているディレクトリパスが格納されています。簡単に言うと、手軽に絶対パスの記述ができるものです。



outputの設定


path:filename: がありますね。

こちらも結論から言うと
path: は、どのディレクトリに出力するか指定しています。
filename: は、どのファイルに出力するか指定しています。

なので、
./src というディレクトリ内の main.js というファイルに出力してね。」という設定をしています。

devtool


まず、結論です。
devtool: を設定することによって、ソースマッピングのスタイルを選択して、デバッグプロセスを強化します。指定可能な値は stringfalse です。
(参照:公式ドキュメントのdevtool

分からない用語が出てきた?ソースマッピングですかね?

分からなければ、しっかり調べていきましょう。



ソースマップについて


ソースマップとは、Babelなどトランスパイル後と前のコードの内容を紐付けしてデバッグしやするするもの。

トランスパイルについて JavaSciprtではwebpackでコンパイルなどをする時に同時にトランスパイルという処理を行います。 具体的に何をしているのかというと、互換性のあるコードに変換をする処理。 (例)「CoffeeScriptとかを記載して、Javascriptへトランスパイルする。」みたいな感じです。 一般的にはBabelというライブラリを使います。



devtool: 'cheap-module-eval-source-map'


まとめると、ここでは 'cheap-module-eval-source-map' を設定しており、公式ドキュメントによると、ビルドと再ビルトの処理速度としては遅めに処理されるようです。

// webpack.config.js

...
module.exports = {
...
  devtool: 'cheap-module-eval-source-map',
...
}


target


結論から言うと、
target: を設定することによって、特定の環境をターゲットにするようにwebpackに指示してくれます。ここでは、'node'と設定しているので、Node.jsのような環境で使用するためにコンパイルしてます。

// webpack.config.js

...
module.exports = {
...
  target: 'node',
...
}


module


module: オプションは、プロジェクト内のさまざまなタイプのモジュールがどのように処理されるかを設定しています。「webpack が特定の module をどう扱うか」を決めるってことです。webpack では moduleJavaScriptCSS などのファイルを指す。
ここでは、 Rule モジュールについて設定されているので、詳しくみていきます。

// webpack.config.js

...
module.exports = {
...
  module: {
    rules: [
      {
        test: /.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'file-loader'
          }
        ]
      },
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'babel-loader'
          },
          {
            loader: 'react-svg-loader',
            options: {
              jsx: true
            }
          }
        ]
      }
    ]
  },
...
}


Rule


まず結論から、
rule: を設定すると、「条件」、「結果」、「ネスト」されたルール3つの部分に分けることができます。



Rule.test


公式ドキュメントによると、テストアサーションに合格したすべてのモジュールを含めます。 Rule.testオプションを指定した場合、Rule.resourceも指定できません。 と書いてありましたが、ちょっと「??」のままでした。

いろいろ調べてみた結果を簡単にいうと、
Rule.test で拡張子を設定する」というイメージです。
webpackでいう module ( JavaScriptCSS など)を設定するってことです。
今回で言うと、拡張子が .js なので、 test: /.js$/ と設定しています。

このまま一気に説明した方が理解がしやすいと思うので、一気に説明していきます。

Rule.loader


この2つですが、簡単にいうと
まず loader: 'babel-loader' と設定することで、 test: /.js$/ で設定した jsファイル'babel-loader' として読み込む設定をしています。



plugins


最後 plugins: です。
pluginsオプションは、さまざまな方法でwebpackビルドプロセスをカスタマイズするために使用されます。 externalPlugins というプラグインがカスタマイズされています。

公式ドキュメントによると、 webpackには豊富なプラグインインターフェイスがあります。 webpack自体のほとんどの機能は、このプラグインインターフェイスを使用します。これにより、Webpackが柔軟になります。



resolve, alias


// webpack.config.js

...
  resolve: {
    alias: {
      '@alias/components': path.resolve(__dirname, '../src/components'),
      '@alias/src': path.resolve(__dirname, '../src'),
    }
  },
...
// hoge.js(resolve.aliasを使用しない場合)

import MyComponent from './../../../components/MyComponent'
import { someSrc } from './../../src/constants'
// hoge.js(resolve.aliasを使用した場合)

import MyComponent from '@alias/components/MyComponent'
import { someSrc } from '@alias/src'


最後


最後の方は駆け足で説明することになりましたが、少しでも理解の手助けになれば幸いです。
こんなことを最後にいうことではありませんが、webpackについては公式ドキュメントに結構丁寧に説明が書いてあるので、そこをみれば理解できるかと思います。

何か間違い等ありましたら教えていただけると幸いです。