JSのcreatElementでscriptを追加すると「Cannot use import statement outside a module」エラー

やりたいこと

Reactでscriptファイルを読み込むためにdocument.createElementを使って、以下のようにHTMLにscriptタグを挿入したい。

<script src="http://localhost:5173/src/wallets/window.ts" type="module"></script>

現象

Reactでscriptファイルを読み込むためにdocument.createElementを使ったところ、以下のエラー。

ターミナル:

Uncaught SyntaxError: Cannot use import statement outside a module (at window.ts:1:1)

contentScript.ts:

import { register } from './wallets/window';

export const main = () => {
  register();
  const windowScript = new URL('./wallets/window.ts', import.meta.url);

  const script = document.createElement('script');
  script.src = windowScript.href;

  document.head.prepend(script);
};

出力されたHTML:

<script src="http://localhost:5173/src/wallets/window.ts"></script>

原因

おそらくモジュールとして認識されておらず、その場合はCJSに変換さないため、エラーになっている(調査・検証していないため間違っている可能性あり)。

対応

script.type = 'module' を追加して、モジュールであることを指定する。

contentScript.ts:

import { register } from './wallets/window';

export const main = () => {
  register();
  const windowScript = new URL('./wallets/window.ts', import.meta.url);

  const script = document.createElement('script');
  script.src = windowScript.href;
  script.type = 'module'; // ←これを追加

  document.head.prepend(script);
  console.log('document.head=>',document.head);
};

出力されたHTML:

<script src="http://localhost:5173/src/wallets/window.ts" type="module"></script>

モジュール認識させる方法は、ほかにも export {} をファイルの最後尾に追加する方法や tsconfig.json を "isolatedModules": false, する方法でも解決できる。

参考

Module でないファイル

isolatedModulesが設定されている場合、すべての実装ファイルはModuleでなくてはなりません(import/exportの形式を利用しているという意味)。ファイルが Module でない場合、エラーが発生します。

function fn() {}
'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.