GatsbyJS: Google AdSenseを導入するとIE11でscriptが動かない問題を解決する
GatsbyJS: v2.23.3
Google AdSenseを導入する場合は↓のscriptを取り込むわけだが……、
<script async src="http://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
GatsbyJSでやるとなぜかIE11だけエラー吐いてscriptが壊死する。ページは表示できるがscriptが全部動かなくなる、IEまたお前か。ピュアなReact Appでは起きなかったのでGatsbyJS固有の問題と思われる。
↓こんな感じで取り込んでいるとダメだった。
<Helmet
script={[
{src: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", async: "async"},
]}
/>
どうやらPolyfillが足りていないらしい。GatsbyJSはデフォルトでBabelしてるからIEもたいていは大丈夫なんだけど、完全ではないようだ。
足りないPolyfillについてはこの記事を参考にさせて頂いた。神なのか?
参考:GatsbyJSのIE 11対処方法
記事にある.babelrcは必須じゃないので私は作らなかった。デフォルトで↓の設定だからIEの需要がある限りは大丈夫かと。0.25%以下になったIEなど切り捨てる。
{
"browserslist": [">0.25%", "not dead"]
}
ただしこの対応だけでは本件は解決しない。
ウザいことにたまに正常に動くようになった。三回に一回くらいだろうか、まぁたまにでも成功するならアプローチはあっているのだろう。ぶっちゃけPolyfill事情はさっぱりわかっていないし、恥ずかしながら告白させてもらえばPolyfillという言葉自体はじめて知ったわけだが。
まぁおそらく追加したPolyfillの取り込みがdeferで、AdSenseがasyncなのが問題なのだろう。Polyfillを取り込む前にAdSenseの問題コードが実行されたらおじゃんになると推測、かんぺき勘だが私はフォースと共にあるので大丈夫。
async、deferについてはこの記事がわかりやすかった。Qiitaってすごいね。
参考:<script> タグに async / defer を付けた場合のタイミング - Qiita
ためしにAdSenseをasyncからdeferにしてみたら治った。100%大丈夫な対応ではない気がするとフォースがささやいているが、少なくとも私の環境では一度もエラーになっていないのでよしとする。私はフォースと共にあるが服従はしない。
<Helmet
script={[
{src: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", defer: "defer"},
]}
/>
でもさすがにdefer固定にするのはイヤだ。IEのためにまっとうなブラウザまで性能落としたくないので、ひと手間くわえる。
- IEの場合:Polyfill取り込み&AdSenseをdefer
- IE以外:Polyfill取り込まない&AdSenseをasync
IE判定してscript取り込む方法はコチラを参考にした。そう、Qiita。
参考:IEのために|IE判定とバベルとポリフィル - Qiita
これやるってなるとHelmetじゃ手に負えないのでhtml.jsをつくる。間違ってたらHelmetさん、すんません。
cp .cache/default-html.js src/html.js
で、よきところにこれを埋め込む。
<script type="text/javascript" dangerouslySetInnerHTML={{ __html: `
function addScript(path, sync) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = path;
script[sync] = sync;
document.getElementsByTagName("head")[0].appendChild(script);
}
var userAgent = window.navigator.userAgent.toLowerCase();
if (userAgent.indexOf("msie") !== -1 || userAgent.indexOf("trident") !== -1) {
addScript("https://polyfill.io/v3/polyfill.min.js?features=fetch%2CPromise", "defer");
addScript("//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", "defer");
} else {
addScript("//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js", "async");
}
` }} />
これで動いた。もっとまともな方法があったら教えて頂きたい。