Vue.jsでIE11対応

Vue CLI3の使用を前提としています。

browserslist

package.jsonbrowerlistを修正します。

  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead",
    "ie 11"
  ]

browserlistとは、BabelAutoprefixerなどのツールがどのブラウザを対象にするか決定する設定です。複数のツールに対して開発対象ブラウザを共有できるのが特徴です。 package.jsonに記載する代わりに.browserslistrcファイルを作成して記載することもできます。

  • > 1%
    • これは世界の使用状況統計で1%より上のブラウザを対象とする設定。
  • last 2 versions
    • `設定によって対象になったブラウザの2バージョン前までを対象とする設定。
  • not dead
    • 24ヶ月以内に公式のサポートがされていないブラウザを対象から外す設定。例えば、IE 10`など
  • ie 11
    • このように特定のブラウザを対象とすることもできます。> 1%last 2 versionsでOIE 11は対象となるはずですが、念の為記載しておきます。

設定ファイルによって実際にどのブラウザが対象とされるのかを確認することができます。

$ npx browserslist
and_chr 87
and_ff 83
and_qq 10.4
and_uc 12.12
android 81
baidu 7.12
chrome 87
chrome 86
edge 87
edge 86
firefox 84
firefox 83
firefox 82
ie 11
ios_saf 14.0-14.2
ios_saf 13.4-13.7
ios_saf 12.2-12.4
kaios 2.5
op_mini all
op_mob 59
opera 72
opera 71
safari 14
safari 13.1
samsung 13.0
samsung 12.0

すべての設定方法は公式のREADMEから確認してください。

小ネタ 本当に1%のシェアのブラウザを対象とする必要があるの?

browserlistはデフォルトで"> 1%", "last 2 versions","not dead"と設定されているので大抵のブラウザでJavaScriptを動作させることが可能です。

しかし、常にトランスパイル後のファイルサイズが増大するという欠点があります。 例えば、async/awaitを利用した簡単なコード例でも、上記の設定だとファイルサイズが大きく膨れ上がっていることがわかります。

  • before
const api = async () => {
  const res = await fetch('https://example.com')
  const data = await res.json()
  return data
}

console.log(api())
  • after
"use strict";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

var api = /*#__PURE__*/function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
    var res, data;
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return fetch('https://example.com');

          case 2:
            res = _context.sent;
            _context.next = 5;
            return res.json();

          case 5:
            data = _context.sent;
            return _context.abrupt("return", data);

          case 7:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));

  return function api() {
    return _ref.apply(this, arguments);
  };
}();

console.log(api());

async/await構文が利用できるのは、ES2017からですが実は**95%**のブラウザではすでに対応済です。つまり、ほとんどのブラウザに対しても対応している構文であるにも関わらず、不要なトランスパイルによってファイルサイズを増大させてしまっているとも言えます。

実際に、対象ブラウザをシェア98%から95%にすることによって、**9%**パフォーマンスが改善したという結果が報告されている興味深い記事があります。

babel.config.js

次にbabel.config.jsの設定を変更します。

module.exports = {
  presets: [
    [
      '@vue/cli-plugin-babel/preset',
      {
        useBuitIns: 'entry',
        corejs: { version: 3 } 
      }
  ],
}

"useBuiltIns": "entry"の設定にすると、すべてのpolyfillを読み込むようになります。この場合、エントリーファイルの先頭で手動でpolyfillをimportする必要があります。 main.{j,t}sファイルが実際の記述箇所となるでしょう。

  • main.ts
import "core-js/stable";
import "regenerator-runtime/runtime";

@babel/polyfilをimportするように書いてある記事もありますが、これはBabel 7.4.0から非推奨となっています。 core-jsは様々なpolifillを含んでいるライブラリです。regenerator-runtime/runtimeではyield構文、つまりはasync/awaitをサポートします。

vue.config.js

vue.config.jsファイルでtranspileDependenciesオプションを設定します。デフォルトではBabelはnode_modules配下のファイルをトランスパイル対象に含みません。依存関係を明示的にトランスパイルするためには、このオプションのリストに追加する必要があります。

例えば、Vuetiryを利用している場合には以下のように追加します。

  • vue.config.js
// vue.config.js

module.exports = {
  transpileDependencies: ['vuetify']
}

AutoPrefixer

IE 11を完全に攻略するためにはJavaScriptだけでなくCSSも気にかける必要があるでしょう。 例えば、gridはとても強力な機能ですが、IE 11には対応していません。

IE 11でgridを適応させるためにはベンダープレフィックスを付与する必要がありますが、それを自動的に行なってくれるのがAutoPrefixerです。

Vue CLI3ではルートディレクトリにpostcss.config.js.postcssrcを設置すればよしなに読みこでくれます。

$ npm install --save-dev autoprefixer
  • postcss.config.js
module.exports = {
  plugins: {
    'autoprefixer': {
      grid: 'autoplace'
    },
  }
};

IE 11に対応しているけど表示がおかしくなるCSS

表題の通り、position: absoltedisplay: flexcalcなどIE 11で表示したときだけ表示が崩れる涙を流したくなるような現実があります。

これはもはやツールではどうしようもないので手動で確認しながら対応していく必要があります。辛い。

参考

Is your Vue app not working in IE 11? Here’s how to fix it. Babel7.4で非推奨になったbabel/polyfillの代替手段と設定方法

この記事をシェアする
Twitterで共有
Hatena

関連記事