lit-html/lit-element を IE で動かす
- カテゴリ:
- JavaScript
- IE
- コメント数:
- Comments: 0
◆ @babel/polyfill を webcomponents の polyfill より先にロードすればいい
◆ 逆だと IE11 でスタックオーバーフローする
◆ polyfill.io も使える
◆ 逆だと IE11 でスタックオーバーフローする
◆ polyfill.io も使える
前記事では lit-html も結局 webcomponents の polyfill が必要になって 入れてみたらスタックオーバーフローになって動きませんでした
その後もう少しいじっていたら なぜか動いて 元に戻したはずなのにまだ動いていたりで 何が原因なのかをいろいろ調べていると動かし方がわかったのでそのへんのまとめです
順番的に Object.assign などが必要で babel の polyfill を入れて 次に createTreeWalker が必要で webcomponents の polyfill を入れました
この状態から @babel/polyfill をなくして webcomponents の polyfill だけにしたら動きました
たぶん GoogleMaps のときと同じように polyfill の競合ではないかと思います
webcomponents の polyfill 設定後に足りていない部分だけを更新するなら問題なさそうに思うのですが 何かうまくいかない部分があるのでしょう
これで動くようになりましたが @babel/polyfill と違って webcomponents の polyfill は webcomponents の動作に必要な最低限しか機能はありません
Object.assign や Promise はあるものの String.prototype.repeat や Array.prototype.includes や Object.entries など ES2015+ の機能で使えないものが多いです
順番は webcomponents の polyfill の後でも大丈夫でした
@babel/polyfill だとダメな何かを polyfill.io の polyfill で上書きしてるので大丈夫なのかと思います
できれば DOM 系の webcomponents と JavaScript 機能の @babel/polyfill の 2 つにしたいです
あとから @babel/polyfill をロードするとスタックオーバーフローするので 先にロードしてみることにしました
バンドルするモジュール中で import するのではなく @babel/polyfill パッケージの dist フォルダに用意されている minify 済みのファイルを直接 HTML からロードします
こっちは順番が大切です
こうするとスタックオーバーフローが発生せず実行できるようになりました
test.html
test.js
webpack.config.js
特に es5-adapter は使ってないですが Chrome も動きました
しかし 原因をよく調べてみたら document.createTreeWalker ではありませんでした
エラー箇所は document.createTreeWalker ではあるものの element.content を第一引数に渡していて それが undefined のためエラーになっていました
element というのは HTMLTemplateElement のインスタンスです
IE11 は template タグに対応していないので content プロパティがありません
そのせいで document.createTreeWalker でエラーになっていました
そのため 必要なのは document.createTreeWalker の polyfill ではなく HTMLTemplateElement の polyfill でした
HTMLTemplateElement は webcomponents の機能なので webcomponents の polyfill に含まれていて このエラーは回避できていた というのが正しいです
その後もう少しいじっていたら なぜか動いて 元に戻したはずなのにまだ動いていたりで 何が原因なのかをいろいろ調べていると動かし方がわかったのでそのへんのまとめです
babel の polyfill を入れない
動かなかったときは @babel/polyfill と webcomponents の polyfill をロードしていました順番的に Object.assign などが必要で babel の polyfill を入れて 次に createTreeWalker が必要で webcomponents の polyfill を入れました
この状態から @babel/polyfill をなくして webcomponents の polyfill だけにしたら動きました
たぶん GoogleMaps のときと同じように polyfill の競合ではないかと思います
webcomponents の polyfill 設定後に足りていない部分だけを更新するなら問題なさそうに思うのですが 何かうまくいかない部分があるのでしょう
これで動くようになりましたが @babel/polyfill と違って webcomponents の polyfill は webcomponents の動作に必要な最低限しか機能はありません
Object.assign や Promise はあるものの String.prototype.repeat や Array.prototype.includes や Object.entries など ES2015+ の機能で使えないものが多いです
polyfill.io
lit-html の issue では polyfill.io を使っていたので 使ってみると @babel/polyfill があっても動きました<script src="https://polyfill.io/v3/polyfill.min.js"></script>
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
<script src="test-bundle.js"></script>
順番は webcomponents の polyfill の後でも大丈夫でした
@babel/polyfill だとダメな何かを polyfill.io の polyfill で上書きしてるので大丈夫なのかと思います
@babel/polyfill を先に読み込む
動いたもののこれだと polyfill.io と webcomponents と @babel/polyfill と polyfill を 3 重にロードしていますできれば DOM 系の webcomponents と JavaScript 機能の @babel/polyfill の 2 つにしたいです
あとから @babel/polyfill をロードするとスタックオーバーフローするので 先にロードしてみることにしました
バンドルするモジュール中で import するのではなく @babel/polyfill パッケージの dist フォルダに用意されている minify 済みのファイルを直接 HTML からロードします
<script src="node_modules/@babel/polyfill/dist/polyfill.min.js"></script>
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
<script src="test-bundle.js"></script>
こっちは順番が大切です
こうするとスタックオーバーフローが発生せず実行できるようになりました
lit-element
webcomponents を使ったプログラムが動くようになったので lit-element の方も動かせますtest.html
<script src="node_modules/@babel/polyfill/dist/polyfill.min.js"></script>
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
<script src="test-bundle.js"></script>
<foo-bar></foo-bar>
test.js
import {LitElement, html} from "lit-element"
customElements.define("foo-bar", class extends LitElement {
static get properties() {
return { now: Number }
}
constructor() {
super()
this.now = Date.now()
setInterval(() => (this.now = Date.now()), 1000)
}
render() {
return html`<h1>${this.now}</h1>`
}
})
webpack.config.js
module.exports = {
mode: "development",
entry: "./test.js",
output: {
path: __dirname,
filename: "test-bundle.js",
},
devtool: false,
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
],
},
],
},
}
特に es5-adapter は使ってないですが Chrome も動きました
createTreeWalker は問題なかった
lit-html で webcomponents の polyfill を入れたのは document.createTreeWalker が動かなかったことが原因ですしかし 原因をよく調べてみたら document.createTreeWalker ではありませんでした
エラー箇所は document.createTreeWalker ではあるものの element.content を第一引数に渡していて それが undefined のためエラーになっていました
element というのは HTMLTemplateElement のインスタンスです
IE11 は template タグに対応していないので content プロパティがありません
そのせいで document.createTreeWalker でエラーになっていました
そのため 必要なのは document.createTreeWalker の polyfill ではなく HTMLTemplateElement の polyfill でした
HTMLTemplateElement は webcomponents の機能なので webcomponents の polyfill に含まれていて このエラーは回避できていた というのが正しいです