LoginSignup
4

More than 3 years have passed since last update.

posted at

updated at

type="module"がsafariで上手く読み込めなかった時の対応

概要

今まで何も考えず</body>前にJSを読み込ませてたのですが、最近のベストプラクティスとしてheadタグに

// モダンブラウザ用
<script type="module" src="js/main.js"></script>

// IE11などレガシーブラウザ用
<script nomodule src="js/nomodule.main.js" defer></script>

のように読み込むというプラクティスを発見し、実践した。
その際にsafariでのみ読み込みエラーが発生したため、その解決方法の備忘録です。

解説

type="module"での読み込みに関しては下記の記事の解説が分かりやすかったため
一読をおすすめします。
モダンブラウザに最適化した JavaScript を提供する
ライブラリ以外はとりあえず type="module" にしよう

nomoduleに関しては下記。
ES Modules への橋渡しとしての nomodule 属性

ひとまずざっくり説明すると、type="module"はモダンブラウザのために最適化された読み込み方式(deferとかでタイミング調整しなくても良い)で、type="module"に対応していないブラウザはnomoduleの方を自動的に読んでくれます。
逆に言えばnomodule"のJSはtype="module"対応ブラウザでは読み込まれないため、複数のpolyfillを読み込んで肥大化したファイルを読み込む必要がなくなります。便利。
なのでWebpackでそのあたりを出し分ければモダンブラウザで無駄のないJSファイルを配信できますね。

ハマったポイント

ここでタイトルの内容に入ります。
モダンブラウザに最適化した JavaScript を提供する
の記事内にありますが、type="module"でJSを読み込む場合、CROS通信(ざっくり言うと外部通信的な)扱いとなってしまい、MacOS、iOSのsafariでのみ
Blocked https://example.com/js/hoge.js from asking for credentials because it is a cross-origin request.
とアラートが出て読み込みができない問題が発生しました。

解決方法

ご紹介記事の中にもありますが、.htaccessなどサーバーサイドでAccess-Control-Allow-Origin: https://example.comのようにCROS通信を許可する方法があります。(セキュリティー上問題があるようなので、ワイルドカードでの指定はやめたほうが良さそう。)
ですが、実案件ではクライアントのサーバー設定をイジれないケースもあり、上記の方法では解決できませんでした。
また、Access-Control-Allow-Originの設定先を開発環境URLにしていて、公開したときに書き換え忘れて読み込めない!のような自体も想定できます。

いろいろ調べた結果、下記のように<script>タグにcrossorigin属性をつけることでサーバーサイドをイジる必要なく解決しました。

// crossorigin属性を追加
<script type="module" src="js/main.js" crossorigin="use-credentials"></script>

crossoriginの詳しい解説はこちら

crossorigin="anonymous"としても読み込みをされますが、こちらは実際に外部のCDNなどから読み込む場合に使用したほうが良さそう?なのでcrossorigin="use-credentials"としました。(『ちげぇよ馬鹿野郎!』というご指摘があれば教えていただけると助かります…)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4