開発マシンが Windows OS の場合、Flask 開発サーバーが拡張子 .mjs のファイルを応答として返す時、応答ヘッダの Content-Type が text/plain になるので (MacOS や Linux の場合は不明)、ブラウザは受信したスクリプトのロードに失敗するということと、その解決方法を書きます。
拡張子 .mjs のファイルはモジュール機能を持つ JavaScript ファイルです。<script>
要素に type="module"
属性を含めることでそのスクリプトがモジュールであることを宣言します。詳しくは MDN の記事「JavaScript モジュール」を見てください。
html コードに含まれる <script>
要素の src="xxx.mjs"
属性の指定による要求に応じて、Flask 開発サーバーが xxx.mjs ファイルを応答として返す時、応答ヘッダに含まれる Content-Type が text/plain になります。
その結果、下の画像のようにブラウザ(Chrome の例です)は受信した .mjs ファイルのスクリプトのロードに失敗します。
上の画像のエラーメッセージに "Strict MIME type checking is enforced for module scripts per HTML spec." とあります。ブラウザは type="module" 属性を見て module scripts であると判定し、応答ヘッダに含まれる Content-Type が text/plain では HTML spec に反するのでロードしないと言っているようです。
ブラウザがスクリプトをロードできるようにするには、応答ヘッダの Content-Type を text/javascript にする必要があります。(注: application/javascript は廃止になったそうで、text/javascript を使えと言うことになっています。現在のところ、まだ Chrome などは application/javascript に対応してますが)
なぜ Flask 開発サーバーが Content-Type を text/plain に設定するかは、以下の stackoverflow の記事に書いてありますが、Windows PC の場合レジストリの設定情報を読んでくるからだそうです。
自分の環境の Windows 10 22H2 のレジストリを調べてみると、以下の通り .mjs は text/plain になってました。(ということで、諸悪の根源は Windows OS ということのようです)
レジストリをいじらなくても以下の様な設定で変更可能ということが上に紹介した stackoverflow の記事書いてあります。
import mimetypes
mimetypes.add_type('text/javascript', '.mjs')
試してみると、応答ヘッダの Content-Type は text/javascript になり、ブラウザはスクリプトをロードして期待通り動くようになりました。