せっかなくので、やってみた。

日々のあんなこと、こんなこと、せっかくなのでやってみた

ParcelのビルドでIE11対応しつつasyncを使いたい

ES6のasync/awaitを使用しているプロジェクトでずっとchromeで開発していたのですが、ある日IE11で動作確認するとエラーで動かない事が分かりました。
エラー発生行をデバッガー見ると、アロー演算子の箇所でエラーになっています。
JSのビルドにはParcelを使用していたので、普通にIE11でも動くようトランスパイルされていると思ったのですが、そうではないみたいです。

ググってみると、.babelrcのbrowsersの項目に対応ブラウザを記述する必要があるようなので、以下の様に「,"ie 11"」を追加してみました。

{
  "presets": [
    [
      "env", {
        "targets": {
          "browsers": ["last 2 Chrome versions", "ie 11"]
        }
      }
    ]
  ]
}

すると、今度はchromeでも別のエラーが発生するようになってしまいました。

Uncaught ReferenceError: regeneratorRuntime is not defined

ググってみるとasync/awaitを使用しているとトランスパイルがうまくできなくて発生する様でした。
.babelrcの"ie 11"の設定を外すと問題無く動くのは、chromeが元々async/await対応しているためっぽいです。

IE11でも動作するようしたいので、色々調べたのですが、babel7.4以降とそれより前で対応方法が変わってしまい、私の環境で動作する情報が見つかりませんでした。
現在インストールされているbabelとparcelを確認すると以下となっています。

parcel 1.12.4
babel 6.26.3

babelが結構古いので、1から環境を作り直すことにしました。

まずは、現在のbabel、node関連のファイル、ディレクトリをバックアップ

mv .babelrc .babelrc.bak
mv node_modules node_modules.bak
mv package.json package.json.bak
mv package-lock.json package-lock.json.bak

次に、公式の手順で、parcelをインストール(npmを使うのでここからはDOSで実行)

cd プロジェクトディレクトリ
npm install parcel-bundler
npm init -y

ついでにnpxもインストール

npm instal npx

parcelでビルド

npx parcel watch xxxx\bundle.js -d xxxx/js --public-url .

ビルドは通りますが、この状態でも"regeneratorRuntime is not defined"は解消されませんでした。

こちらの記事を参考に追加でモジュールをインストール

qiita.com

npm install -D @babel/preset-env
npm install core-js

エントリポイントのJS(bundle.js)に以下を追加

import 'core-js/stable';
import 'regenerator-runtime/runtime';

以下の様に.babelrcにも@babel/preset-envの項目を追加(なくても動くっぽい?)

  "presets": [
    [
      "env", {
        "targets": {
          "browsers": ["last 2 Chrome versions", "ie 11"]
        }
      },
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

これでやっと"regeneratorRuntime is not defined"は解消されました!が、
今度は以下のエラーが。

vue.runtime.esm.js:619 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

このプロジェクトではVue.jsも使用していたのですが、どうもVueには完全ビルドとランタイムビルドでモジュールの使い方に違いがある様です。

qiita.com

多分単一コンポーネントを使っているから完全ビルドが必要なのかな?と思いつつ、さらに調べると、公式でもpackage.jsonに設定を追加するよう、記述がありました。

jp.vuejs.org

ということでpackage.jsonに以下を記述(環境作り直す前のpackage.jsonにはこの記述がありました。)

  "alias": {
    "vue": "./node_modules/vue/dist/vue.common.js"
  }

再度parcelでビルドしてIE11、chromeで問題無く動作しました!最終的にpackage.jsonの各モジュールのバージョンは以下になりました。

  "dependencies": {
    "axios": "0.21.0",
    "core-js": "3.7.0",
    "js-cookie": "2.2.1",
    "npx": "10.2.2",
    "vue": "2.6.12",
    "vue-hot-reload-api": "2.3.4"
  },
  "devDependencies": {
    "@babel/core": "7.12.3",
    "@babel/preset-env": "7.12.1",
    "@vue/component-compiler-utils": "3.2.0",
    "babel-preset-env": "1.7.0",
    "vue-template-compiler": "2.6.12"
  },
  "alias": {
    "vue": "./node_modules/vue/dist/vue.common.js"
  }

IE対応が入るとホントややこしくなります。