Babel 基本 #1

Babelとは何か

BabelはJavaScriptコンパイラ

新しい構文で書かれたJavaScriptを古いブラウザでも動作するように変換するのがBabel。

Babelの主な仕事

  • JavaScriptコードを変換する

  • ポリフィル(最近の機能をサポートしていない古いブラウザでも、新しい機能を使えるようにする)機能

  • ソースコード変換

使い方

ES2015+の構文で書かれたJavaScriptを現在のブラウザで動作するコードにコンパイルする例

  1. パッケージのインストール
yarn add -D @babel/core @babel/cli @babel/preset-env
yarn add @babel/polyfill
  1. babel.config.jsonの作成

    プロジェクトのルートディレクトリ直下に作成する。

    設定の内容はサンプル

{
  "presets": [
    [
      "@babel/env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage",
        "corejs": "3.6.4"
      }
    ]
  ]
}
  1. srcディレクトリのコードをコンパイルして、libディレクトリに出力する例
npx babel src --out-dir lib

Core Library

Babelのコア機能は@babel/coreに含まれている。

実際に@babel/coreを使ってコンパイルするコードを書くこともできる

// Babelのコア機能を読み込む
const babel = require('@babel/core');

// JSコードとコンパイルオプションを用意
const code = `
console.log("Hello, world");
`;

const options = {};

// コンパイル!
const result = babel.transform(code, options);

// 結果を表示
console.log(result);

// 表示結果
// {
//   metadata: {},
//   options: {
//     cloneInputAst: true,
//     babelrc: false,
//     configFile: false,
//     passPerPreset: false,
//     envName: 'development',
//     cwd: 'D:\\Users\\owner\\Desktop\\work\\babel-sample',
//     root: 'D:\\Users\\owner\\Desktop\\work\\babel-sample',
//     plugins: [
//       [Plugin], [Plugin], [Plugin],
//       [Plugin], [Plugin], [Plugin],
//       [Plugin], [Plugin], [Plugin],
//       [Plugin], [Plugin], [Plugin],
//       [Plugin], [Plugin], [Plugin],
//       [Plugin], [Plugin], [Plugin],
//       [Plugin]
//     ],
//     presets: [],
//     parserOpts: {
//       sourceType: 'module',
//       sourceFileName: undefined,
//       plugins: [Array]
//     },
//     generatorOpts: {
//       filename: undefined,
//       auxiliaryCommentBefore: undefined,
//       auxiliaryCommentAfter: undefined,
//       retainLines: undefined,
//       comments: true,
//       shouldPrintComment: undefined,
//       compact: 'auto',
//       minified: undefined,
//       sourceMaps: false,
//       sourceRoot: undefined,
//       sourceFileName: 'unknown'
//     }
//   },
//   ast: null,
//   code: '"use strict";\n\nconsole.log("Hello, world");',
//   map: null,
//   sourceType: 'script'
// }

CLI Tool

@babel/cliはターミナルからbabelを使えるようにするツール。

以下のようにコマンドからbabelのコンパイルが行える。

./node_modules/.bin/babel src --out-dir lib
# or
npx babel src --out-dir lib

これはsrcディレクトリにある全てのJavaScriptファイルを解析し、指定した変換を適用して、各ファイルをlibディレクトリに出力するコマンド。

(※このコマンドでは変換方法を指示してないので、出力コードは入力コードと同じになる)

どのような変換を行うかは、オプションで指定する事ができる。

変換(Plugins & Presets)

コードの変換機能はプラグインとして提供される。

アロー関数で書かれた処理を、functionに変換する指示をする例

  1. pluginを導入する
yarn add -D @babel/plugin-transform-arrow-functions
  1. コマンドのpluginsオプションで①で導入したpluginを指定する
npx babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
// 変換前
const hello = () => console.log("Hello World");

// 変換後
const hello = function hello() {
  return console.log("Hello World");
};

このようにして、Babelに変換方法を指示する事もできるが、1つ1つプラグインを指定するのではなく

プラグインがセットになった「プリセット」を指定する事もできる。

(プラグインと同様に独自のプリセットを作成することもできる。)

プリセットの使用例として、envプリセットを使う例

  1. プリセットの導入
yarn add -D @babel/preset-env
  1. コマンドでプリセットを指定する
npx babel src --out-dir lib --presets=@babel/env

オプションはコマンドで指定するのではなく、設定ファイルを用意する事でも行える。

設定ファイル

設定ファイルはプロジェクトルート直下にbabel.config.jsonという名前で作成する。

{
"presets": [
  [
  "@babel/env",
    {
      "targets": {
        "edge": "17",
        "firefox": "60",
        "chrome": "67",
        "safari": "11.1"
        }
      }
    ]
  ]
}

上記の設定では、プリセットにenvを使用し、ターゲットに指定したブラウザで動作しないコードの変換のみを行うという設定。

Polyfill

※Babel 7.4からpolyfillは非推奨となったそう、以下の記事に詳しく書かれている。 aloerina01.github.io

なので、以下の文章読むより、上記の記事を見たほうがよい。

ポリフィルは、PromiseやWeakMapなどの新しいビルトインの機能を使えるようにする仕組みです。

  1. Polyfillの導入
yarn add @babel/polyfill

ポリフィルは-Dオプションを指定せずにインストールする。

ポリフィルは実際に動作する上で必要なプログラム群のため。

設定ファイルのuseBuiltInsについて

{
  "presets": [
    [
      "@babel/env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage"
      }
    ]
  ]
}

useBuiltIns: "usage"を指定することで、Babelは指定した環境で足りない機能がないかどうかを、全てのコードを検査し、必要なポリフィルのみを読み込みます。

例として

Promise.resolve().finally();

このコードは以下のようになる。

require("core-js/modules/es.promise.finally");

Promise.resolve().finally();

これはEdge17には`Promise.resolve().finally()がないため。

設定ファイルのuseBuiltIns: "usage"を指定していることで、足りない機能だけが読み込まれます。