Object.defineProperties非対応環境向け webpack + babel + babel-preset-env トランスパイル設定


2019/01/03追記 この記事には改訂版があります

この記事の内容は古くなったため、改訂版を作成しました。

Babel + rollup.js で ES3環境向けトランスパイル

本記事の手順では、Babel7での正常なトランスパイルができません。改訂版では代替案としてrollup.jsの導入を行なっています。

webpack4 + babel6での組み合わせでトランスパイルを行う際のメモとして、この記事は残しています。
新規導入の際はこの記事を利用しないでください。

目標

moduleのimportを使用したjavascriptを、現行のwebpackとbabelを使用して、es3相当にトランスパイルします。

前提とする環境

本記事で前提とする環境は以下の通りです。バージョンが異なる場合、この記事の内容は適用できない場合があります。記事を読む前にバージョンをご確認ください。

  • macOS : 10.13
  • webpack : 4.10.2
  • babel : 6.23.0
  • babel-preset-env : 1.7.0

なぜそんな古い規格を?

es3はブラウザ上からはすっかり消滅しましたが、アプリケーションに組み込まれた独自のjavascriptエンジンではまだ存在します。
私の場合、Adobe CCの各アプリのバッチ処理のためjsを使用しています。このjsエンジンが非常に古いため、es3相当のコードしか実行できません。
importを利用できれば、共通処理をくくり出せるため、バッチの生産性が高くなります。
どうにかしてimportを使用できる状況でコードを書き、Adobe CC上で実行できるようにトランスパイルします。

構成

使用するパッケージは以下の通りです。
npmからインストールしてください。

▼package.json

"devDependencies": {
    "babel": "^6.23.0",
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
    "babel-plugin-transform-es3-property-literals": "^6.22.0",
    "babel-preset-env": "^1.7.0",
    "webpack": "^4.10.2",
    "webpack-cli": "^3.0.1"
}

babelの設定

babelの設定は以下の通りです。
"env", { "loose" : true }でLoose modeを有効にすると、Object.definePropertiesを使用しないようにトランスパイルが行われます。
また、transform-es3-*プラグインでオブジェクトのプロパティ名をstringに、呼び出しを連想配列に置き換えます。

▼.babelrc

{
    "presets": [
        [ "env", { "loose" : true } ]
    ],
    "plugins": [
        "transform-es3-member-expression-literals",
        "transform-es3-property-literals"
    ]
}

この設定では最低限、importと最低限のトランスパイルが実行されるだけとなります。
その他のes2015以降の機能を利用したい場合は、対応するbabel-pluginを追加してください。
例として、Object.assignを使用したい場合はbabel-plugin-transform-object-assignを追加します。

webpackの設定

あとはbabel-loaderを使用したwebpackを行えば、import処理を含めたトランスパイルが行われます。

▼webpack.config.js


const path = require("path");

module.exports = {
    entry: entryfile,
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name]',
    },

    module: {
        rules: [{
            test: /\.js$/,           
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader'
            }
        }]
    }
}