Multi Vitamin & Mineral

Multi Vitamin & Mineral です。プログラムに関することを書いております。

ES6 を IE11 でも動くよう変換したい。そうだ、 Babel を使おう!

f:id:hiranoon:20210219022720p:plain

IE11 でも動く JavaScript に変換したい! ES2015(=ES6) 以降の JavaScript を変換して ES5 にダウングレードする方法です。この記事で利用しているのは Babel のバージョン7です。

なお、本記事ではあえて Babel 以外のツールは含めないようにしています。

前提(ヤリタイコト)

この記事では以下を前提としています。

  • IE11 でも動く JavaScript (ES5)に変換したい
  • 複数ファイルを一括で変換したい
  • できる限り簡単な環境で実施したい(余計なことをしない)
  • (おまけ)JavaScript はコンパクトにしたい(コメントを消して minify したい)

こういう変換は Babel がいっちゃん有名だろうということで Babel を使います。

この記事のコンセプトは「余計なこと」は避けたいので、 Webpack で1つのファイルにまとめたりとか、 React も変換しちゃえとか、他のツールとの組み合わせは言及しません。

Babel とは

公式サイトはこちら。

babeljs.io

その公式は「What is Babel?」というページで、 Babel は、

  • ES2015 (= ES6) 以降の新しいバージョンの JavaScript コードを、
  • 古いブラウザや環境で動く下位互換バージョンの JavaSdript コード に、
  • 変換するツール

と言っています。(私的翻訳)

「新しいバージョンの JavaScript でバリバリコーディングをして → Babel で変換して → 大体のブラウザで動く JavaScript を得る」のが目的のツールと言って良いでしょう。(その「大体のブラウザ」というのは、2021年現在では IE11 が対象になると思います。)

ブラウザで変換する(お試し利用)

Babel はブラウザだけで変換することができます。

公式サイトのヘッダーにある「Try it out」に行ってみましょう。

左サイドバーの「TARGETS」の欄に ie 11 を入力します。(このサイドバーの設定が分かりにくい!)

エディタ部の左側に以下のコードを入力するします。

const printMsg = (msg) => console.log(`print ${msg}`);

すると、エディタ部の右側に変換後のコードが表示されます。

"use strict";

var printMsg = function (msg) {
  console.log("print ".concat(msg));
};

const 、アロー関数( (xxx) => {...} )、テンプレート構文( text ${expression} )が変換されていますね。

これで事足りる人は以上で終了でOK。

とはいえ「Try it out」(お試し)ですし、毎回ブラウザに入力するのも面倒なのでローカルPCに環境を作ることにしましょう。

Babel を使おう

Babel は npm の利用を前提としているので、Node.js の実行環境は必須になります。 Node.js の環境を用意した上で、コマンドラインから動かします。

Babel の実行環境の用意

前述の通り、 npm が必要になります。この記事では、 Windows10 で、 VSCode と GitBash を使った例で説明しています。

前提環境

前提となる環境です。今回の記事の内容は以下のバージョンで行っています。

ツール バージョン
Windows 10
Visual Studio Code (VSCode) 1.53.2
Node.js v14.15.5
npm 6.14.11
git (git bash を使います) 2.27.0.windows.1

これだけじゃ困る人は以下の記事で。

multimineral-tech.com

フォルダの用意

以下のようなフォルダ構成を作りたいと思います。

./exec-babel
├─dist
└─src     

任意の場所に任意のフォルダ(ここでは exec-babel とします)を作り、 VSCode から開きます。

そしたら、 VSCode のターミナル(Ctrl + @ で表示される)から以下を入力します。

$ mkdir src
$ mkdir dist

npm の利用開始

npm が使える環境にしましょう。以下のコマンドを打ちます。( npm init だけだと色々聞かれます。回答するのが面倒なのでこの例で -y オプションを付けています。すると全部 Yes と回答したのと同じ結果になります。)

$ npm init -y

package.json ファイルが生成されます。

Babel のインストール

以下のコマンドで Babel をインストールします。

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

node_modules というフォルダが生成され、この中に Babel がダウンロードされています。

package.json の内容が以下のように変更されています。 devDependencies: の項目にインストールされたモジュールの情報が追加されています。

{
  // ...中略...
  "devDependencies": {
    "@babel/cli": "^7.12.16",
    "@babel/core": "^7.12.16",
    "@babel/preset-env": "^7.12.16"
  }
}

インストールされたのは以下の3つでした。

ツール 説明
@babel/core Babel の本体。これだけだと動かない。
@babel/cli コマンドラインから Babel を操作するツール。
@babel/preset-env 変換内容のプリセットです。

@babel/preset-env はプリセット? ちょっと分かりづらいですね。コレは後ほど簡単に説明しますが一旦次に進みます。

Babel の設定ファイルの作成

Babel の設定ファイルである babel.config.json を用意しましょう。変換したい内容を指定します。

$ touch babel.config.json

中身は「IE11対応にして!」とだけ書いておきます。

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

以上で Babel を実行する準備は完了です。

Babel の実行

それでは適当なファイルを用意して実際に変換してみます。

変換元ファイルの用意

変換元のファイルを用意します。(ここでは以下のファイルをサンプルとして用意しますが、もちろん自分で作成したファイルでOKです。)

$ touch src/printlog.js

src/printlog.js の中身は以下のようにしておきます。

// コンソールにログを出力する関数です。
const printMsg = (msg) => console.log(`print ${msg}`);

Babel で変換を行う(ファイル単位)

以下のコマンドで変換を実行します。(インストールした Babel 本体は ./node_modules/.bin/ に入ってます。)

$ ./node_modules/.bin/babel src/printlog.js --out-file dist/printlog.js

dist/printlog.js というファイルが生成されました。

"use strict";

// コンソールにログを出力する関数です。
var printMsg = function printMsg(msg) {
  return console.log("print ".concat(msg));
};

Babel で変換を行う(フォルダ単位)

以下のコマンドでも結果は同じになります。

$ ./node_modules/.bin/babel src --out-dir dist

今回は 1ファイルだけでしたが、フォルダ内に複数のファイルがあれば、一括で変換してくれます。

前回と今回ではオプションが違っています。 --out-dir でフォルダを指定した場合、変換後のファイル名は変換元と同一ファイル名になります。 --out-file であれば違うファイル名に指定できます。

  • --out-file : ファイル単位で変換
    • 変換元と変換先のファイル名を指定する(別フォルダの同一ファイル名でもOK。)
  • --out-dir : フォルダ単位で変換
    • 変換元と変換先のフォルダを指定する
    • 変換元と変換先は同じファイル名になる

こんな感じ。

npm scripts を使う

./node_modules/.bin/babel と長いコマンドを打つのは面倒です。通常は npm scripts を使うでしょう。

package.json"scripts": 内に build というタスクを追加すべく "build": "babel src --out-dir dist", の行を追記します。

{
  // ...中略...
  "scripts": {
    "build": "babel src --out-dir dist",
    // ...中略...
  },
  // ...中略...
  "devDependencies": {
    "@babel/cli": "^7.12.16",
    "@babel/core": "^7.12.16",
    "@babel/preset-env": "^7.12.16"
  }
}

package.json 内では ./node_modules/.bin/ の部分が不要になります。(npm scripts 内では ./node_modules/.bin/ がスコープに含まれるのだ。)

実行するときは以下のコマンドになります。

$ npm run build

(おまけ)minify とコメント削除もしたい

IE11 利用可能バージョンにするのに加えて、 minify とコメント削除も行ってみたいと思います。

Babel でプラスアルファを行いたい場合の一例として、参考にしていただければと思います。

minify の実施

インストールと設定変更

babel-preset-minify というツールがあったのでコレを使います。まずはインストールから。

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

設定ファイルである babel.config.json を変更します。

["@babel/preset-env"...] の並びに "minify" を追加しました。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": "11"
        }
      }
    ],
    "minify"
  ]
}
実行と結果

以下のコマンドで実行します。

$ npm run build

dist/printlog.js が以下のように生成されました。

"use strict";// コンソールにログを出力する関数です。
var printMsg=function(a){return console.log("print ".concat(a))};

不要なスペース・改行が削除され、変数名も簡素化されています。

コメント削除の実施

設定変更

コメント削除は Babel の機能に搭載されていますので他のツールのインストールは不要です。設定ファイルである babel.config.json の変更のみ行います。

"presets": の並びに "comments": false を追加しました。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": "11"
        }
      }
    ],
    "minify"
  ],
  "comments": false
}
実行と結果

以下のコマンドで実行します。

$ npm run build

dist/printlog.js が以下のように生成されました。

"use strict";var printMsg=function(a){return console.log("print ".concat(a))};

コメントが削除されました。

補足と注意点

@babel/preset-env とは?

「Babel の実行環境の用意」の項では、 @babel/preset-env がちょっと分かりづらいかな? と書きました。それについてです。

@babel/preset-env は、 IE11 などの環境毎に変換すべき内容を提供してくれるモノです。

例えば、 IE11 で動かすための JavaScript が欲しければ、

「IE11 が対応したい(目的)。使える JavaScript のバージョンを調べよう。ええと、 ES5 だと分かったな。だから ES5 に変換すると指定してやるか、、、(手段)」

なんて調べた上で、設定ファイル内に ES5 と指定する必要がありそうです。そんな気がします。ですが、 @babel/preset-env さんがいれば、

「IE11 で動くよう、ヨシナに変換しといて!(目的&手段)」

とだけ指定すればOKになります。

IE11 だけならそこまで大変でもないんでしょうね。でも、環境が変わりゆく中で適切な変換内容を調べるのは結構骨が折れるモノです。ですので、「目的」だけ伝えればOKっていうのは中々便利なものです。 @babel/preset-env はそういうツールです。

Babel のバージョンについて

Babel の最新バージョンは、 2021年2月現在では「7」です。「Babel 7」では @babel/core@babel/cli@babel/preset-env をインストールして使いました。

Babel の旧バージョンはちょっと違っているんですよね。 babel-clbabel-preset-env のようなモジュール名になっています。先頭に @babel/ がついていないものは古いです。もし、 @babel/ がついていないモジュールを使っている解説記事があれば「古い内容かも知れない!?」と疑ってください。

ですが、今回使った babel-preset-minify のような @babel/ 化していないモジュールもありますのでご注意を。( minify を( Webpack ではなく) Babel で行う需要は低いんでしょうかね。だから Babel 7 化(?)されずに取り残されているのかな?)

あとがき

現時点で Babel だけを使う簡単な記事があってもいいかな、と思って書き始めました。

そう思った理由は以下。

  • 公式サイトを見るのがスジなのでしょう。が、「ちょっと変換したいだけ」という場合にはノイズが多すぎて(公式だからそりゃそうだ)読むのに時間が掛かる。
  • 公式サイトは英語なので読むのに時間がかかる。(英語力の問題。。。)
  • ネットで調べた「簡単な記事」のほとんどが Babel 6 以前の古い情報だった。
  • 「簡単な記事」では Babel だけでなく Webpack を使っているパターンが紹介されがちであった。

本格的に使い始める場合は、当該記事のような簡単な内容を知った上で、公式サイトを参照されると良いかと思います。

babeljs.io

今回は IE11 対応の JavaScript を生成することを目的としました。ですが、そろそろ IE11 も切り捨てていい頃かも知れないと思っています。 Microsoft 365 の IE11 サポートは、2021年8月17日 まで。本家でもそんな感じですからね。

最後に、「Babel って、普通は Webpack と一緒に使うよな」とは思っています。 Babel で変換したファイルをさらに1つのファイルにまとめたい場面の方が多いでしょう。今回の記事では、1つのファイルにまとめないニッチな需要を満たせたのなら幸いです。