やりたいこと
Viteの環境でnpm run buildを行いビルドをしたところ正しく動作しなかったことのまとめです・
前提として開発環境にあったテンプレートを使用しています。(テンプレートなしだと構成などで苦戦したため)
(随時更新)
ビルド時エラー
await
awaitを使用した場合に以下のエラーが出てビルドに失敗しました。
ERROR: Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)
これは古いブラウザではTop-level(main thread)でawaitを使用することが許されていないため互換性の問題でエラーになるようです。
上にあるようにawaitをTop-levelで使用しなければ問題ありません。(awaitを使用すること自体は問題ありません)
解決策
awaitをやめる
可能であればawaitをやめ、thenやallなどで実装することで対応できます。
Top-level以外で実行する
onclickなどTop-level以外で実行するように実装することで対応できます。
設定ファイルの変更
設定ファイルを変更することでawaitをTop-levelで使用してもエラーにならないようにします。
ビルドされたコードは古いブラウザで動作しない可能性があります。
編集するファイルはdefineConfigを修正している設定ファイルです。初期はvite.configのようです。私の環境(Phaser3のTemplate)ではvite/config.prod.mjsでした。
以下の設定を追記します。esbuildの設定がすでにある場合supportedのみを追加します。
export default defineConfig({
esbuild: {
supported: {
'top-level-await': true
},
}
})
実行時エラー
constructor.name
constructor.nameを使用しているコードがビルド後に動作しませんでした。
任意のクラス.constructor.nameはクラス名設定されているのですが、ビルド時にクラス名が変更され意図していた動作をしませんでした。(私の場合は匿名クラスになっていてconstructor.nameに空文字が入っていました)
解決策
constructor.nameは使用しない。
空文字でなくても、バージョンアップなどで設定される名前が変わる可能性があるためクラス名を使用するのは避けたほうがよさそうです。
クラスに名前をもつ変数を一つ追加するのが簡単で安全です。(ほかに同等の変数があればそちらを使用)
import()関数
バンドル対象のファイルからimportすると失敗します。(バンドルされてパスが変わるので当たり前なのですがdevでは動作するので気が付きませんでした。)
以下のようなエラーがコンソールに表示されます。
Failed to fetch dynamically imported module:
解決策
dynamicではなくStaticのimport文で読み込むことで解決します。
結果
テンプレートを使用しないとフォルダ構成などで苦戦しましたが開発環境にあったテンプレートを使用することで今のところ上記の問題しか起きていません。
コメント