Vueでアプリを開発する際、規模にかかわらずイベントバスがめんどい拡張性を担保するため、
基本的にVuexをインストールしています。
状態管理で幸せになれる便利なVuexライブラリですが、「IE11でVuex使えない!」というケースがあるので、原因と対策をまとめてみました。
webpackを使用していることを前提としています。
また、検証用に使用したvue-cli(2.9.6)でインストールされるbabelが6系のものだったので、
babel関連のモジュール名も6系のものに合わせています。
7系を使っている場合はbabel-XXXを**@babel/xxx**に読み替えてください。
##IE11のエラー
IE11でVuexが動いていない場合、ブラウザ表示が真っ白になって(何も表示されず)、コンソールで以下のエラーが吐かれるかと思います。
SCRIPT5022: [vuex] vuex requires a Promise polyfill in this browser.
どうやら、IE11でvuexを使うにはPromiseのポリフィルが必要なようです。
##結論
いきなり結論ですが、上記のエラーの通り、Promiseのポリフィルを入れることでIE11にVuexを対応させることができます。
が、タイトルの通りbabel-plugin-transform-runtime
だとVuexライブラリ内のPromiseが変換されません。
ちなみに、**vue-cli(3.x)**ではBabel7およびpreset-envによるポリフィル注入がサポートされているため、デフォルトでIE11でもVuexが動作していることが確認できました。
言い換えると、
-
vue-cli 3.x
ではなくvue-cli 2.x
でプロジェクトを作成した - ES2015+の関数を
babel-polyfill
ではなくbabel-plugin-transform-runtime
でトランスパイルしている - そもそもES2015+(Promise)のpolyfillをどこにも置いていない
といった場合にIE11でVuexが使えないケースが起こりうるのではないかと思います。
##原因
Vuexライブラリでは内部的にPromiseが使用されています。
(actionsがPromiseを返す、とかそのあたりだと思う)
IE11はPromiseをサポートしていないため、Promiseって知らないからポリフィル入れてね、とエラーが出るわけですね。
###transform-runtime
だとダメな理由
transform-runtime
はグローバルにpolyfillを置くものではありません(グローバル汚染しないなどの利点があります)。
ES2015+の関数があれば、JSファイルごとに必要な箇所を書き換えるよ、という静的解析するものなので、
node_modules
であるVuexライブラリ内部のPromise
に関しては変換の対象外となってしまいます。
babelの設定に関しては以下の記事が参考になります。
##対処と検証
まずは実際にIE11でVuexが使えない環境を再現します。
検証用プロジェクトの作成
今回検証のために**vue-cli(2.9.6)**を使ってプロジェクトを作りました。
「Vue.js を vue-cli を使ってシンプルにはじめてみる」を参考にさせていただきました。
生成された.babelrc
を見ると、pluginsに"transform-runtime"
が使用されているようです。
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
プロジェクトを作成したら、Vuexをインストールします。
npm i -S vuex
つぎに、ストアのインスタンスを新規作成します。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
hoge: 'Storeのhogeです'
}
})
export default store
作成したストアを/src/main.js
で読み込みます。
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
+ import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
+ store,
components: { App },
template: '<App/>'
})
プロジェクト作成時にHelloWorld.vue
が作成されていると思うので、ここにStoreの情報を表示するよう変更します。
<script>
export default {
name: 'HelloWorld',
data () {
return {
- msg: 'Welcome to Your Vue.js App'
+ msg: this.$store.state.hoge
}
}
}
</script>
Vuexが使えていれば、以下のh1タグ内にStoreのhogeが表示されすはずです。
<template>
<div class="hello">
<h1>{{ msg }}</h1> //ここに表示されるはず
下記コマンドを叩いてlocalhost
で確認します。
npm run dev
ChromeなどPromiseをサポートしているブラウザでは、問題なく下記のように表示されるかと思います。
###IE11でVuexを使えるようにする
前置きが長くなりましたが、いよいよ本題です。
以下の2つのやり方のいずれかで対処することができました。
1. es6-promiseをimportする方法
es6-promise
をインストールします。
npm i -D es6-promise
main.js
にes6-promiseをimportします。
注意点として、storeのimport文より前に記述してください。
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
+ import 'es6-promise/auto'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
2. babel-polyfillをバンドル時に結合する方法
babel-polyfill
をインストールします。
npm i -D babel-polyfill
webpack.base.conf.js
を修正して、main.js
をバンドルする際にbabel-polyfill
を結合します。
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
- app: './src/main.js'
+ app: ['babel-polyfill','./src/main.js']
},
同時に、.babelrc
の"transform-runtime"
は不要になるはずなので、こちらを削除します。
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
- "plugins": ["transform-vue-jsx", "transform-runtime"],
+ "plugins": ["transform-vue-jsx"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
結果
無事、IE11でもVuexが使用できるようになりました。
参考
下記を参考にしました。
FORK Advent Calendar 2018
20日目 git cloneできない時の調べ方と対策 〜AWS CodeCommit/Mac OSの場合〜 @izanari
22日目 Apache(php-fpm + Apache 2.4)で何を設定すればいいのかわからなかったので調べてみた @Kodak_tmo