ESモジュールは通常のscriptと読み込みルールが違う
type=moduleを付けたスクリプトはESモジュールとして扱われ、importでファイルを参照したり、自動で遅延実行になったりと、通常のスクリプトと挙動が変わります。読み込みの厳しさも増し、配信元やMIMEタイプの条件を満たさないと実行されません。
特につまずきやすいのが、ローカルでファイルを直接開いた場合です。file:// で開くとモジュールの取得がブロックされ、HTTP(S)で配信しないと動かないことが多いです。まずはサーバー経由で開いているかを確認するのが出発点です。
なぜCORSが関係するのか
CORS(クロスオリジン制約)は、あるサイトから別のオリジンのリソースを読み込むときの安全ルールです。ESモジュールのimportはこの制約の対象になり、別オリジンのモジュールを読むには、配信側が適切な許可ヘッダを返している必要があります。
同じサイト内(同一オリジン)の相対パスなら基本的にCORSは問題になりません。エラーが出るときは、別ドメインのモジュールを直接importしていないか、あるいはfile://で開いてオリジンが特殊扱いになっていないかを疑います。
通常のscriptは画面表示の都合上ゆるく読み込めますが、モジュールは設計上CORSを必須とするため、同じファイルでも読み込み方が変わると挙動が分かれます。
症状別チェック表
type="module"のJSが読み込めない・CORSで止まるは、症状を分けずに直そうとすると原因探しが長引きます。まず「自分だけで起きるのか」「全員で起きるのか」「特定ブラウザだけか」「差し替え後だけか」を切り分けます。
確認順序を固定すると、相対パス、ファイル名、キャッシュ、認証、外部読み込みのどこで止まっているかが見えます。修正後はローカル確認だけで終わらせず、実際の共有URLで再表示して、相手と同じ条件で直ったことを確認します。
- 自分だけ表示されない: キャッシュ、ログイン状態、ブラウザ拡張、端末幅を確認する
- 全員で表示されない: ファイル構成、相対パス、大文字小文字、アップロード漏れを見る
- 一部だけ崩れる: CSS/画像/JSごとに読み込みエラーを分ける
- 差し替え後だけ古い: URL、キャッシュ、更新対象ファイルの取り違えを確認する
止まる原因を切り分ける手順
CORSと一口に言っても、実際にはパス・MIMEタイプ・オリジンのどれかでつまずいていることがほとんどです。次の順で確認します。
- F12のConsoleでエラー文を読み、CORSなのかMIMEタイプなのか取得失敗なのかを見分ける
- Networkタブで該当JSのステータスが200か、Content-Typeがjavascript系かを確認する
- importやsrcのパスが同一オリジンの相対パスになっているか確かめる
- 別ドメインを直接importしている場合は、同梱して相対パスに変えられないか検討する
- ローカル確認はfile://をやめ、HTTP(S)配信で開き直す
MIMEタイプの不一致に注意
ESモジュールは、サーバーが返すContent-Typeがtext/plainやoctet-streamなど不適切だと、JavaScriptとして実行されずに止まります。Networkタブで該当ファイルのContent-Typeを確認し、javascript系で返っているかを見ると、MIMEタイプ起因かどうかが分かります。
拡張子は.jsでも、配信側の設定によっては正しいMIMEで返らないことがあります。配信環境がモジュール向けのMIMEタイプを適切に付けてくれるかどうかは、type=moduleを使ううえで地味に重要なポイントです。
適切に配信される環境で確認する
ESモジュールはHTTP(S)配信と正しいMIMEタイプが前提なので、ローカルで直接開くだけでは本来の挙動を確認できません。本番に近い配信環境で開いて確かめるのが確実です。
ギガサイト便はCSSやJSを含むZIPをドロップすると 〇〇.giga-site.com でHTTPS配信され、同一オリジンの相対パスでモジュールを読み込めます。file://起因のブロックを避けて、Console・Networkでステータスやmime-typeを確認しながら切り分けられます。同じURLのまま差し替えられるので、import先を直しては再検証する反復もスムーズです。
よくある質問
通常のscriptでは動くのにtype=moduleだと止まるのはなぜですか
モジュールはCORSや配信元、MIMEタイプの条件が通常のスクリプトより厳しいためです。特にfile://で直接開くとブロックされやすく、HTTP(S)配信が前提になります。
同じサイト内の相対パスでもCORSエラーになりますか
同一オリジンの相対パスなら通常CORSは問題になりません。エラーが出るなら、別ドメインを直接importしていないか、file://で開いてオリジンが特殊扱いになっていないかを確認してください。
MIMEタイプが原因かどうかはどう確認しますか
Networkタブで該当JSのContent-Typeを見ます。javascript系でなくtext/plainなどになっていると、JavaScriptとして実行されず止まります。配信側のMIME設定を確認してください。
別ドメインのモジュールをimportしたいときはどうすればよいですか
参照先が適切な許可ヘッダを返している必要があります。難しい場合は、そのファイルを自分側に取り込んでZIPに同梱し、同一オリジンの相対パスでimportする方法が確実です。
原因が分からないときはどこから確認すべきですか?
まず自分だけの問題か全員の問題かを分けます。次にシークレットウィンドウ、別ブラウザ、スマホで確認し、ファイル構成・相対パス・キャッシュ・認証設定を順に見ます。