MENU

サンプルで学ぶ webpack + Babel 環境構築入門

2021 8/27
サンプルで学ぶ webpack + Babel 環境構築入門

こんにちは、りっくんです!

昨今のフロントエンドでは、ES2015以降の記法を使ってJavascriptのコードを書いていくのが鉄板です。

しかしながら、ES2015以降の記法が非対応のレガシーブラウザを考慮したり、ファイル間の依存関係を考えないといけなかったりと、実装者が実装以外の点に関することも色々と考えなければなりません。

そこで今回はそのような懸念点を解決してくれる優れものである、webpackとBabelというものに関して内容を記していこうと思います。

目次

webpackとは

webpackとは、モジュールバンドラのことを指します。

モジュールバンドラとは、平たく言うと複数のファイルを1つにまとめて出力してくれるツールのことを言います。

※複数ファイルをまとめることを「バンドル」と呼ぶ。

なぜ使うのか

  • 依存関係*を処理し、一つのファイルにまとめることができる

※依存関係とは:あるファイルがあるファイルの内容に依存している状態のことを指します。

 例えばjQueryを例に出すと、$('#className') といった$を使った記法を扱う際は、予めjQueryの公式が配布しているデータを読み込む必要があります。なぜなら、HTMLファイルを読み込む際に外部で取り込むスクリプトファイル等々は通常、上から順に読みこまれるからです。したがって、jQuery記法を扱う際には必ず事前に、jQueryファイルを読み込む必要があります。このような状態を、つまりその他のjsファイルがjQueryのファイルに依存していると言えます。

webpackでは、このようなjsファイル同士の依存関係をよしなに解決して、一つのjsにパッキングしてくれます。そのため、JSファイルの読み込み順を気にしなくて済みます。

また、1つのファイルにまとめるので、外部ファイルを読み込む際のリクエストの回数も1回で済み、余分な通信を発生させずに済みます。(CSSや画像もJSファイルとしてパッキングしてくれます)

  • 開発効率アップにつながる

機能ごとにファイルを分けて開発することができます。(関数を別のファイルに管理して、それを本来使用するJSファイルの中で取り込んで使用するなど)

▶︎ コードが整理されて開発効率、保守性が上がります。

と他にもいろいろ利点はありますが、主な利点はこの辺りと思います。

Babelとは

通常であれば最新のECMAScriptで実装されたコードはIE11など、レガシーなブラウザでは動作が保証されません。

そこで、Babelを使うことで最新のECMAScriptで書かれたコードをES2015以前のコードに変換(トランスパイル)することができます。

これにより、最新のECMAScriptのコードを書いた上で、そのままレガシーブラウザでの実装を実現することができます。

これで他のブラウザの挙動に関することも特に気にしなくて済みますね。(ちょっと異なるかもしれないですが、CSSでいうところのベンダープレフィックス的なイメージです)

環境構築をしてみよう

実際に環境構築をしてみましょう。今回はできるだけシンプルな構成で構築してみます。

※ ここからはnode が使えることを前提とします。

新規プロジェクトを作成後、npm init -y を実行。その後、

babelを使う際に

  • @babel/core
    → babel本体
  • @babel/preset-env
    → 対応ブラウザなどの情報を元に、必要なプラグインを自動で選択して、最新の ES6+ を動く状態にしてくれるプラグイン
  • babel-loader
    → JavaScriptのES6以降のコードをES5のコードにトランスパイル(変換)するローダー*

※ローダーとは:CSSや画像、JavascriptをJavascriptファイルに変換する際に用いるプログラムのこと。

これら3つをインストールする必要があります。webpackwebpack-cliもインストールします。

npm install -D webpack webpack-cli babel-loader @babel/core @babel/preset-env

すると、package.jsonは以下の通りになります。

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack" // buildコマンドを追加(npm run build で webpackコマンドを実行する)
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.15.0",
    "@babel/preset-env": "^7.15.0",
    "babel-loader": "^8.2.2",
    "webpack": "^5.51.1",
    "webpack-cli": "^4.8.0"
  }
}

つづいて、webpackの設定に移ります。webpack.config.jsというファイルを作成後、

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: "production",
// エントリーポイント(バンドル対象とするファイル)
  entry: "./src/index.js",
  module: {
    rules: [
      {
     // 拡張子 .js の場合
        test: /\.js$/,
        use: [
          {
            // Babel の利用する
            loader: "babel-loader",
            // Babel のオプションを指定する
            options: {
              presets: [
                // プリセッ、ES2020 を ES5 に変換
                "@babel/preset-env",
              ],
            },
          },
        ],
      },
    ],
  },
  // ES5(IE11等)向けの指定(webpack5からこの指定が必要。)
  target: ["web", "es5"],
};

引用:webpackの設定ファイル

https://ics.media/entry/16028/

npm run buildでコマンド実行をすると、新たにdistディレクトリが作成され、その配下にmain.js(デフォルト) が生成されます。

コンパイル前のファイル(アロー関数を使用):

const arr = [1, 2, 3];

const newArr = arr.map((elem) => elem * 2);
console.log(newArr);

トランスパイル後のファイル:

!function(){var n=[1,2,3].map((function(n){return 2*n}));console.log(n)}();

うまくトランスパイルされました。

ちなみに、webpack.config.jsoutputを任意に指定することで、吐き出し先の場所やトランスパイル後のファイル名を変更することができます。

var path = require("path"); // 絶対パスを返す

module.exports = {
  mode: "production",
  entry: "./src/index.js",
  output: {
    filename: "bundle.js", // トランスパイル後のファイルの名前を「bundle.js」に指定。
    path: path.resolve(__dirname, "dist"), // ./dist として返す
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: [
                "@babel/preset-env",
              ],
            },
          },
        ],
      },
    ],
  },
  target: ["web", "es5"],
};

path.resolveの挙動などに関しては、こちらが参考になりました。

どうやらwebpackの出力先の設定において、絶対パスの指定はOS間で表現が異なるためpath.resolveでないと良くないらしいそう。

これらの設定を踏まえてもう一度、npm run buildを実行すると、distフォルダ配下にbundle.jsというファイルが生成されているはずです。

webpack+Babel+jQuery

冒頭でお話しした依存関係の解消の理解を深めるために、jQueryを用いた環境構築をおこなってみましょう。

npm i jQueryを実行

{
 //省略

  "scripts": {
    "build": "webpack"
  },
  "dependencies": {
    "jquery": "^3.6.0"
  },
  "devDependencies": {
    "@babel/core": "7.14.3",
    "@babel/preset-env": "7.14.2",
    "babel-loader": "^8.2.2",
    "webpack": "^5.37.0",
    "webpack-cli": "^4.7.0"
  },
  "private": true
}

webpack.config.jsは先程のoutputを付け加えたもので進めたいと思います。

今回は jquery-validationというフォームバリデーションを簡単に行えるjQueryプラグインを使用してみます。

npm i jquery-validationをコマンド実行。その後エントリーファイル(index.js)で、

import jQuery from "jquery";
import "jquery-validation"; // ここを忘れない。

const $ = jQuery;

$(function () {
  $("form").validate({
    rules: {
      name: {
        required: true,
      },
      mail: {
        required: true,
        email: true,
      },
    },
    messages: {
      name: {
        required: "お名前を入力してください",
      },
      mail: {
        required: "メールアドレスを入力してください",
        email: "正しいメールアドレスを入力してください",
      },
    },
  });
});

distフォルダ配下にindex.htmlを作成。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <form method="post">
    <ul>
      <li>名前 <input name="name" type="text" /></li>
      <li>メール <input name="mail" type="text" /></li>
    </ul>
    <input type="submit" name="Submit" value="Submit" />
  </form>

  <script src="./bundle.js"></script>
</body>
</html>

npm run build実行後、bundle.jsに全て内容がバンドルされた状態で、新しいJSファイルが生成されます。

デモ:

このように、jQueryを使用する際に、jQueryCDNのスクリプトを読み込んだり、プラグインを使用する際の外部スクリプトを読み込む必要がありません。一つのJSファイルに全てバンドルされるので、スクリプトを読み込む順番等々を考えなくて済みます。

babel-polyfillを使って最新のECMAScript環境を構築する

ここまで紹介したBabelですが、アロー関数やクラス、letconstといった新しい構文を下位バージョンに変換しますが、実はasync / await テンプレート構文 などといった機能までは変換しません。

そのため、後者を利用するにはポリフィル*を導入する必要があります。

※ポリフィルとは

▶︎ Javascriptではバージョンが更新されるたびに、新しい構文や使用が追加されるため、ブラウザによって対応状況が異なってきます。そこで、最新のJavascriptコードに非対応の環境でも、最新の仕様が扱えるように同等の機能を模倣する仕組みを指します。

ポリフィルを導入するにあたって、@babel/polyfillをインストールする必要があります。

@babel/polyfillは現在非推奨で、本来であればcore-jsというものを使用する必要があるらしいが、IEでの利用に注意が必要なのと、調べた感じややこしそうだったので、今回は@babel/polyfillを使った例で進めようと思います。)

npm install @babel/polyfill

package.jsonは下のような状態になっていると思います。

{

 // 省略

  "scripts": {
    "build": "webpack"
  },
  "dependencies": {
    "@babel/polyfill": "^7.12.1",
  },
  "devDependencies": {
    "@babel/core": "7.14.3",
    "@babel/preset-env": "7.14.2",
    "babel-loader": "^8.2.2",
    "webpack": "^5.37.0",
    "webpack-cli": "^4.7.0"
  },
  "private": true
}

エントリーファイル(src/index.js)には下記を記載します。

import "@babel/polyfill";

今回は簡単に下記のようなサンプルコードを用意しました。

import "@babel/polyfill"; // ここを忘れない

const resources = "https://jsondata.okiba.me/v1/json/D4nDx210825022511";
async function logFetchData() {
  const res = await fetch(resources);
  const json = await res.json();
  console.log(json);
}

logFetchData();

const hoge = "ほげ";
console.log(`${hoge}です`);

npm run build を実行。ブラウザではfetchで取り込んだオブジェクトのデータが表示されているはずです。

ちなみに、トランスパイル後のbundle.jsでは下のような状態でコードが変換されることが確認できます。

bundle.js(src/index.jsをトランスパイルしたもの)

このようにpolyfillを使用することで最新の構文をレガシーなブラウザに対応できるように自動的に変換してくれます。

これで最新のECMAScript環境の構築をおこなうことができました。

おわりに

いかがだったでしょうか。

今回の内容をおさらいすると、

  • webpack:Javascript間の依存関係を解消し、複数のJSファイルやCSSファイル、画像ファイルを一つのJSファイルにまとめるもの。
  • babel:最新のJavascriptコードを古いブラウザでも動くようにレガシーな環境用のコードとしてトランスパイルするもの。最新のECMAScript環境を補うには、polyfillを用いる必要がある。

になります。

特にwebpackは奥が深いので、もっと勉強を進めて行かねばというところです😟

ここまでお読みいただきありがとうございました🙏✨


引用・出典:

ICS MEDIA
最新版で学ぶwebpack 5入門 - Babel 7でES2021環境の構築(React, Vue, Three.js, jQueryのサンプル付き) - ...
最新版で学ぶwebpack 5入門 - Babel 7でES2021環境の構築(React, Vue, Three.js, jQueryのサンプル付き) - ...ECMAScript2015(略:ES2015)以上の言語仕様でJavaScriptを書くことが、昨今のウェブのフロントエンドエンジニアの基本テクニックです。しかし、ECMAScript2015以上の仕様の...
Qiita
Babelとwebpack入門 - Qiita
Babelとwebpack入門 - Qiita 概要 Babelやらwebpack。 なんとなく理解はしているものの、 環境構築の際には、毎度他の記事を参考にして乗り切っていました。 しかし、公式を見ればさらっと構築で...
Just do IT
webpack の設定でよく見る path.resolve は何をしているのか - Just do IT
webpack の設定でよく見る path.resolve は何をしているのか - Just do ITwebpack の入門書では、webpack.config.jsにファイルの出力先として以下の記述をよく見る。 output: { path: `${__dirname}/dist`, filename: 'main.js' }, これは、「ビル...

もりけん塾に入っております!(Javascriptを鋭意勉強中)

もりた先生のブログ: kenjimorita.jp (武骨日記)
もりた先生のアカウント: twitter.com/terrace_tech

この記事を書いた人

コメント

コメントする

CAPTCHA


目次
閉じる