静的ホスティングを有効にした AWS S3 のバケット(その他諸々の権限も設定済)に、Angular で作成した SPA を aws cli でアップロードしたら、index.html の起動時に *.js が読み込めないというエラーが Chrome の Console に出力された。
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html".
Strict MIME type checking is enforced for module scripts per HTML spec.
「Angular の tsconfig.json の設定か?」などいろいろ調べた 1 結果、アップロードされた *.js
ファイルの content-type が text/html
になっていた事が原因だった。
なぜ発生したかというと、きっかけは aws cli の s3 sync
コマンドを使っていた事。
このコマンドは既定ではファイルの種類に応じて自動的に content-type を設定してくれるという事(実際 *.ico
ファイルには image/x-icon
が設定されていた)だが、どういうわけか *.js
ファイルに期待する application/javascript
は設定されず、text/html
が設定されていた。
ちなみに動作環境は Windows10 Pro x64。macOS や Linux ではまた異なる結果なのかも知れない。
環境によって content-type が変わるのがいやだったので、*.js
ファイルについては任意の content-type を指定することにした。
こちらの解決方法に習って、次のようなコマンドにした。
■Linux/macOS
aws s3 sync <アップロード元ディレクトリ 例: ./dist/ > \
s3://<バケット名> \
--acl public-read \
--exclude "*.js" \
--delete
aws s3 sync <アップロード元ディレクトリ 例: ./dist/ > \
s3://<バケット名> \
--acl public-read \
--exclude "*" \
--include "*.js" --content-type application/javascript
■Windows
call aws s3 sync <アップロード元ディレクトリ 例: .\dist\ > ^
s3://<バケット名> ^
--acl public-read ^
--exclude "*.js" ^
--delete
call aws s3 sync <アップロード元ディレクトリ 例: .\dist\ > ^
s3://<バケット名> ^
--acl public-read ^
--exclude "*" ^
--include "*.js" --content-type application/javascript
1つ目の sync
で *.js
以外をアップロード、2つ目で *.js
のみをアップロードして content-type を明示的に application/javascript
に設定する。
--acl public-read
は、バケット全体で公開にしてあれば不要と思われるのでお好みで。
s3 sync は、変更があったものだけがアップロードされるので、正しくない content-type でアップロードされたファイル群は手動で削除してから(あるいは s3 rm
でバケット内を全削除してから)このスクリプトを実行した方が確実。