環境について
Vite 5.4.0
Three.js r167
(↑three.webgpu.js
と three.webgpu.min.js
のビルドが追加されたバージョン)
https://github.com/mrdoob/three.js/releases
遭遇した問題
Vite環境にて、Three.jsで WebGPURenderer
を使用した際に、以下のエラー文に遭遇しました。
[ERROR] Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)
node_modules/three/build/three.webgpu.js:36252:15:
36252 │ isAvailable = await navigator.gpu.requestAdapter();
WebGPURenderer
のインスタンスを生成した際のコードを以下に抜粋します。
import * as THREE from "three";
import { WebGPURenderer } from "three/webgpu";
const renderer = new WebGPURenderer({
canvas: document.querySelector('#myCanvas')
});
WebGPUを実際にガッツリ活用する際には WebGPURenderer
のみをインポートすることはないだろうけど、サンプルということでご容赦を。
解決した方法
vite.config.js
に以下を記述することで解決しました。
import { defineConfig } from 'vite'
export default defineConfig({
build: {
target: 'esnext',
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
});
TypeScript環境の方は、他にもランタイムやビルド時にエラーが起きるそうです。
以下を参照。
https://scrapbox.io/0b5vr/Vite%E3%81%A7Three.js%E3%81%AEWebGPURenderer%E3%81%8C%E4%BD%BF%E3%81%88%E3%81%AA%E3%81%84
本題はここまで。
(補足1) Top-level await について
エラー文に出現していた Top-level await
についての解説です。
Top-level await
は新しい機能(ES2022 で導入)であり、await 式が async 関数の外側で使えるようになる機能です。
詳しくは以下のリンクを参照。
https://www.tohoho-web.com/ex/es2022.html#top-level-await
WebGPURenderer
の実装に、Top-level await
が使われていましたが、Viteのデフォルト設定だと、ビルドターゲット環境がES2022に対応したものではありませんでした。
そこで、 vite.config.js
を編集して、ビルドターゲットを変更してあげる必要があったわけです。
(補足2) Vite の defineConfig について
import { defineConfig } from 'vite'
export default defineConfig({
build: {
target: 'esnext',
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
});
defineConfig
はIDEに自動補完を提供してくれます。
以下にVSCode環境における、自動補完表示の例を示します。
↑こちらは defineConfig
を使わない場合に、 build.target
のところをマウスホバーした際の表示。型表示のみ。
↑こちらは defineConfig
を使った場合に、 build.target
のところをマウスホバーした際の表示。プロパティに関する詳細情報が記述される。
TypeScript環境の場合は、別の方法で自動補完を利用することが可能なので、詳しくはViteの公式ドキュメントを参照。
https://ja.vitejs.dev/config/
(補足3) Vite のビルドオプションについて
build.target
のプロパティには、 esnext
という値があります。
これはネイディブの動的インポートをサポートしていることを前提としており、トランスパイルが可能な限り少なくなります。
具体的には、ミニフィケーションの互換性を担保するトランスパイルのみを実行するようです。
デフォルトは modules
という値が設定されており、 ES2022
を想定しないブラウザでの利用を想定したトランスパイルになります。
なぜ esnext
に設定しているのが、 build.target
だけではなく、 optimizeDeps.esbuildOptions.target
にもあるのかは、こちらのViteのIssueを参照。
(補足4) Vite のビルドターゲットを変えずに Top-level await をサポートする方法
このプラグインを使いましょう。
READMEを参照。