Vue/CLI と Nuxt.js で IE11 と戦うための知識
令和も3年だというのに、仕事でどうしても Internet Explorer 11 と戦わなければならないこと、あると思います。
IE 11 への対応は巷の記事で様々取り扱われていますが、どうも情報が古かったり、とっ散らかってる印象がありました。
そこで、最新の Vue 2.x の環境はどうなんだろう?と思い、Vue/CLI と Nuxt.js の最新バージョン(2021-09-22時点)の Babel によるトランスパイルと Polyfill についてまとめました。
正直、IE 11 について記事を書くのはこれが最後にしたいですね。
今後、可能な限り各 OSS のアップデートに合わせて記事を更新するようにしたいと考えています。
実際の動作や公式ドキュメントとの齟齬がありましたら、コメントにてご教示いただけますと幸いです。
前提知識
- Babel
- トランスパイル
- Polyfill
これらについては、本記事では説明しません。
私が参考にした中では、下記の記事が一番わかりやすかったです。
Babelによるトランスパイルの挙動について理解する - Qiita
上記の記事の更新日は2018年と少し古めなので、Babel自体の使い方などについてはBabel 公式ドキュメントも併せてご参照ください。
Vue/CLI のトランスパイルと Polyfill について
検証したバージョン
- vue: 2.6.14
- @vue/cli: 4.5.13
検証結果
1. browserslist を見て、その対象のブラウザ向けのトランスパイルと Polyfill を提供してくれる
こちらはVue/CLI の公式ドキュメントに記載がありました。
Vue/CLI を使う場合は、browserslist に IE 11 を含むように追加しましょう。
defaults
IE 11
npx browserslist
で対応させるブラウザの一覧が表示できます。
2. node_modules/ 配下のモジュールはトランスパイルされない
Vue/CLI はデフォルトでは、npm install
でインストールされた node_modules/ 配下のモジュールをトランスパイルしません。
そのため、node_modules/ 配下の特定のモジュールをトランスパイルしたい場合、vue.config.js を以下のようにして対応できます。
module.exports = {
transpileDependencies: [
// can be string or regex
'my-dep',
/other-dep/
]
}
参考:@vue/cli-plugin-babel - Vue CLI
modern モードでモダンブラウザとレガシーブラウザ(フォールバック用)の2種を分けてビルドできる
3.{
"script": {
"build:modern": "vue-cli-service build --modern"
}
}
これは調査をして初めて知りましたが、Vue/CLI には modern モードというビルドモードが存在します。
モダンモードのビルドは、レガシーブラウザ用のトランスパイルや Polyfill を含むソースコードを、モダンブラウザに読み込ませないビルド方法です。
ビルドコマンドに --modern
を追加すると、ビルド結果として以下のファイルが生成されます。
- app.*.js
- app-legacy.*.js
- chunk-vendors.*.js
- chunk-vendors-legacy.*.js
-legacy
がファイル名についているものは、レガシーブラウザ用のトランスパイルと Polyfill が含まれます。
ビルドで生成された index.html の中でそれぞれの .js ファイルを script タグで読み込みますが、モダンブラウザ向けの script タグには type="module"
が付与され、レガシーブラウザ向けの script タグには nomodule
が付与されます。
こうすることで、モダンブラウザとレガシーブラウザで読み込む .js ファイルを分岐させています。
Nuxt.js のトランスパイルと Polyfill について
検証したバージョン
- vue: 2.6.14
- nuxt: 2.15.8
検証結果
1. 常に IE 9 までのトランスパイルと Polyfill の提供をしてくれる
Nuxt.js の公式ドキュメントに記載の通り、ブラウザ向けには IE 9 をターゲットにしたトランスパイルと Polyfill を提供してくれるようです。
2. node_modules/ 配下のモジュールはトランスパイルされない
Vue/CLI と同様に、node_modules/ 配下のモジュールはトランスパイルされません。
トランスパイルしたい場合は、nuxt.config.js の build オプションを以下のように指定します。
build: {
transpile: [({ isLegacy }) => isLegacy && "{トランスパイルしたいモジュール名}"],
}
この isLegacy
といパラメーターは、後述の modern プロパティで登場するレガシーブラウザ向けのビルドの際に使われるパラメーターです。
modern プロパティを使うと、レガシーブラウザ向けのビルドのみモジュールがトランスパイルされるようになります。
個人的な感覚ですが、Nuxt を使って IE 11 で構文エラーになるときは、だいたい外部のモジュールがトランスパイルされてない気がします。
外部モジュールはものによりますが、IE 11 をサポートしていたり、サポートしていないけどトランスパイルすれば使えたり、トランスパイルしても使えなかったりします。
各モジュールのドキュメントをご参照ください。
modern プロパティでモダンブラウザとレガシーブラウザ(フォールバック用)の2種を分けられる
3.{
"script": {
// server (SSR)の場合
"build:modern": "nuxt build --modern=server",
"start:modern": "nuxt start --modern=server",
// clinet (SPA・SSG)の場合
"generate:modern": "nuxt generate --modern=client"
}
}
ブラウザ向けの場合、nuxt generate
に--modern=client
を指定すると、 2. にあった build プロパティの isLegacy が変化します。
4. browserslist は見てはいるけど、Vue/CLI とは違い babel のデフォルトの設定には影響しない
こちらは手元で検証した結果、browserslist を指定によらず、ビルド結果に変化が見られませんでした。
browserslist で最新の Chrome だけを指定しても、トランスパイルされるし、Polyfill も提供されるようです。
まとめ
Vue 2.x で IE 11 に対応するとき色々嘆いてたけど、Vue/CLI と Nuxt.js は割と CLI 側で結構なんとかしてくれるし、しっかり知識を持って臨めばなんとかなる。
そろそろ IE 11 とは縁を切って業務でも Vue 3.x を使いたいものです。
Discussion