【javascript】IE11にも対応!Babel7を使ってES6のコードをES5に変換する方法

 このブログの構成を少しアップデートしようかと思っている今日この頃です。

 さて、最近仕事でも実際にjsをゴリゴリ書くときはなるべく脱jQueryかつES6でコーディングするようにしており、ES6の形式にも少しずつ慣れてきて使いやすさは感じてきたところなのです。特にPromiseなんかはとても便利な機能でお世話になっていますが、ここでも問題になるのがフロンエンドエンジニアにとっての敵であるIEですね。IEはES6の書式に対応していないのでES6で書かれたjsではピクリともしてくれないわけです。

 そこでES6のjavascriptのコードをES5に変換(トランスパイル)する必要があるのですが、今回は一番使われているBabelを使った変換方法を紹介したいと思います。ちなみに、環境はMacになります。

環境

 まず、今回の環境ですが前回同様下記の環境を前提に進めていきたいと思います。

今回の環境

  • Mac OSX Mojave 10.14.5
  • Node.js v10.12.0
  • NPM 6.11.3
  • Babel 7.6.2

プロジェクト作成

 まずは、簡単なプロジェクトを作成してみます。

$ mkdir es6-5

 こんな感じで今回は「es6-5」というディレクトリを作成します。

ES6でコードを記述

 続いて、簡単なコードをES6の書式にしたがって書いてみます。とりあえず「es6.js」というjavascriptファイルを作成して下記のような簡単なHelloWorldを書いてみます。

class HelloWorld {
  constructor(args) {
    this.message = args.message;
  }

  hello () {
    console.log(this.message);
  }
  
}

const hw = new HelloWorld({
  message : 'Hello World!'
});

hw.hello();

 これを実行するとコンソールに「Hello World!」と表示されると思います。

Babelをインストール

 では、このES6の書式で書かれたjavasccriptファイルをES5に変換していきたいと思いますが、今回は冒頭でも述べた通り「Babel」を使って変換してみたいと思います。

初期化(package.jsonの作成)

 まずは、下記のとおり先ほど生成したプロジェクトディレクトリに移動して、初期化(package.jsonを作成)をします。

$ cd es6-5
$ npm init

 いろいろと聞かれますが、とりあえず全てEnterで大丈夫です。

 完了すると、プロジェクトディレクトリ内に「package.json」ファイルが生成されていると思います。

 なお、質問にいちいち答えるのが面倒な場合は下記のコマンドで省略することも可能です。

$ npm init -y

 すべてYesと答えるということですね。

Babel-cliのインストール

 続いて、Babel-cliを下記コマンドを実行してインストールします。

$ npm install --save-dev @babel/core @babel/cli

 インストールが完了したらプロジェクトディレクトリに「node_modules」というディレクトリと「package-lock.json」というファイルが生成されたと思います。

 また、さきほど生成された「package.json」も下記のような記述が追加されていると思います。Babel-cliのバージョン等が記載されてありますね。

"devDependencies": {
    "@babel/cli": "^7.6.2",
    "@babel/core": "^7.6.2"
  }

 念の為、問題ないかバージョンを表示するコマンドを叩いてみます。

$ ./node_modules/.bin/babel --version
7.6.2 (@babel/core 7.6.2)

 上記のようにバージョン名が表示されていれば問題なくインストールされています。

 ちなみに、Babel-cliはグローバル環境にインストールしてもいいのですが、公式でも推奨されているようにプロジェクトごとにインストールして利用するようにしましょう。これはプロジェクトごとに用途が異なるため推奨されていることになります。

.babelrcファイルの準備

 続いて、ES6のコードをES5に変換するために「.babelrc」を作成するのですが、その前に「babel-preset-env」というプリセットをインストールします。

$ npm install --save-dev @babel/preset-env

 インストールが完了したら、再度「package.json」ファイルを開いてみて下記のように記述が追加されていることを確認します。

"devDependencies": {
    "@babel/cli": "^7.6.2",
    "@babel/core": "^7.6.2",
    "@babel/preset-env": "^7.6.2"
  }

 問題なくインストールできたら、続いて「.babelrc」ファイルを生成し、

$ vi .babelrc

 下記のコードを記述して保存します。下記コードは@babel/preset-envのデフォルトの設定が適用され市場の0.25%以上のシェアを持つブラウザに対応したjavascriptのコードに変換してくれます。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": 3
      }
    ]
  ]
}

 なお、下記のようにブラウザのバージョンを指定することも可能です。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": 11
        },
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

ES6をES5に変換してみる

 これで下準備は完了なので、実際に下記コマンドでES6のコードをES5に変換してみます。

$ ./node_modules/.bin/babel es6.js

 上記のコードを実行するとターミナル上に変換されたコードが表示されると思います。

変換してファイルに保存する

 上記の方法だとターミナル上に変換されたコードが表示されるだけなので、下記コードで名前を付けて別ファイルに保存してみます。

$ ./node_modules/.bin/babel es6.js -o es5.js

 これを実行すると「es5.js」というファイルがプロジェクトディレクトリに生成されていると思うので実際に開いてみて変換されているか確認してみます。

"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var HelloWorld =
/*#__PURE__*/
function () {
  function HelloWorld(args) {
    _classCallCheck(this, HelloWorld);

    this.message = args.message;
  }

  _createClass(HelloWorld, [{
    key: "hello",
    value: function hello() {
      console.log(this.message);
    }
  }]);

  return HelloWorld;
}();

var hw = new HelloWorld({
  message: 'Hello World!'
});
hw.hello();

 変換されていることが確認できますね。このように変換したjavascriptファイルを利用すればIE11でも動作するようになります。

ついでにminifyもしてみる

 基本的には上記の変換コードで問題なく動作すると思いますが、せっかくなのでminify化して軽量化までしてみます。

Babelを使ってminifi化するためには、まず下記コマンドで「babel-preset-minify」をインストールします。

$ npm install babel-preset-minify --save-dev

 インストールしたら、下記コマンドを実行することでES5に変換しつつminify化したファイルを生成することができます。

$ ./node_modules/.bin/babel es6.js --presets minify -o es5.min.js

Promiseとかも使いたいよね

 ということで、今回はこんな感じで終わりといきたいところですが、そこはさすがはIEさん。これではまだ不完全なんですね。

 ES6ではPromiseをはじめ様々な機能が新たに含まれた(プラグインとしては古くから存在している)のですが、これらの機能を使おうとなるともう一手間対処してあげないといけません。

 Promiseを使いたい場合、一番手っ取り早いのは、下記のPolyfillファイルをかましてあげる方法です。


 先ほど変換したES5のファイルを読み込む前にこやつを読み込んであげることで、IE11でもPromiseが動作してくれるようになります。

Webpackでバンドルしてみる

 上記の方法でもいいのですが、せっかくBabelを使っているので面倒ですが少し踏み込んでWebpackもインストールしてコンパイルする方法も試してみたいと思います。

 まず、PromiseがIE11でも動くようにするために必要なものを下記コマンドを実行してインストールします。

$ npm install --save-dev core-js regenerator-runtime webpack webpack-cli babel-loader

 インストールが完了したら、「package.json」ファイルを開いて「scripts」に「"build": "webpack"」という記述を追加してnpmでbuildするときにwebpackを使えるようにします。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },

 さらに、「webpack.config.js」を作成し、

$ vi webpack.config.js

 下記のように記述して、ES6からES5に変換された「es5.js」を「bundle.js」というファイルにコンパイルするようにします。

const path = require('path');

module.exports = {
  mode: "development",
  entry: path.resolve(__dirname, "es5.js"),
  output: {
    path: path.resolve(__dirname),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: "babel-loader",
          }
        ]
      }
    ]
  }
};

 続いて、「.babelrc」ファイルの「useBuiltIns」が「entry」になっている場合は、「usage」に変更しておきます。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

 ここまできたら、改めて下記コマンドでES6をES5に変換します。

$ ./node_modules/.bin/babel es6.js -o es5.js

 そうすると更新された「es5.js」ファイルに新たにいくつかのrequire文が挿入されたと思います。これらのファイルがIE11等でPromiseを動作させるために必要なモジュールになります。

require("core-js/modules/es.object.define-property");
require("core-js/modules/es.object.to-string");
require("core-js/modules/es.promise");
require("core-js/modules/web.timers");

 そして、最後に下記コマンドでこの出来上がった「es5.js」をwebpackでビルドしてあげてコンパイルします。

$ npm run build

 そうすると「bundle.js」というファイルが生成されるので、このファイルを実際に使用することでIE11でもPromise(他のIE11非対応の機能も可)を動作させることができます。

まとめ

 ということで、今回はES6の書式で書かれたjavascriptファイルをIE11でも動作するようにBabelを使ってES5に変換する方法や、Promise等のIE11で利用できない機能を使えるようにする方法を紹介させていただきました。

 まだIE11には対応しないといけないことが多いと思いますが、IE11のためにこんな面倒なことをしないといけないので早いとこIEのシェアが0になってくれるとありがたいですね(笑)。

 てことで、今回はここまで!また!

お仕事のご相談・ご依頼
お気軽にお問い合わせください!

お仕事の依頼はこちら

著者プロフィール

Taka

東京、奄美大島を拠点にサーフィンとスノーボードが好きなフリーランスのWebクリエイターです。普段はプログラム書いたりデザインしたり映像作ったりしています。いろいろな人の話しを聞くのが好きなので、このブログを通して多くの人と繋がりが出来たら嬉しいです。noteとInstagramもやっているのでフォローしてくれたらありがたいです!

人気記事

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です