Webpack 5 build errors after upgrading to r185 (DRACOLoader/KTX2Loader runtime assets)

After upgrading from r184 to r185, my project no longer builds with Webpack 5.

I noticed the following changes:

  • DRACOLoader: Use relative file urls by default (#33564)
  • KTX2Loader: Use relative file urls by default (#33603)
  • DRACOLoader: Add exported urls for GLTF decoder (#33691)

The PR descriptions mention that using new URL(..., import.meta.url) should allow bundlers to resolve the assets correctly, but in my case Webpack starts parsing the Emscripten runtime JavaScript files and attempts to resolve the Node.js fallback (fs and path), causing the build to fail.

Environment

  • three.js: r185
  • Webpack: 5.99.9
  • Nx: 20.7.0 (@nx/webpack)
  • Browser target
  • TypeScript

Build errors

ERROR in ../../node_modules/three/examples/jsm/libs/basis/basis_transcoder.js
Module not found: Error: Can't resolve 'fs'

ERROR in ../../node_modules/three/examples/jsm/libs/basis/basis_transcoder.js
Module not found: Error: Can't resolve 'path'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/draco_decoder.js
Module not found: Error: Can't resolve 'fs'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/draco_decoder.js
Module not found: Error: Can't resolve 'path'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/draco_wasm_wrapper.js
Module not found: Error: Can't resolve 'fs'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/draco_wasm_wrapper.js
Module not found: Error: Can't resolve 'path'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/gltf/draco_wasm_wrapper.js
Module not found: Error: Can't resolve 'fs'

ERROR in ../../node_modules/three/examples/jsm/libs/draco/gltf/draco_wasm_wrapper.js
Module not found: Error: Can't resolve 'path'

Experiment

To understand where the regression came from, I modified DRACOLoader.js locally.

I replaced:

const WASM_BIN_URL = new URL( '../libs/draco/draco_decoder.wasm', import.meta.url ).toString();
const WASM_JS_URL = new URL( '../libs/draco/draco_wasm_wrapper.js', import.meta.url ).toString();
const JS_URL = new URL( '../libs/draco/draco_decoder.js', import.meta.url ).toString();

const DRACO_GLTF_CONFIG = {
    js: new URL( '../libs/draco/gltf/draco_wasm_wrapper.js', import.meta.url ).toString(),
    wasm: new URL( '../libs/draco/gltf/draco_decoder.wasm', import.meta.url ).toString(),
};

with:

const WASM_BIN_URL = './draco_decoder.wasm';
const WASM_JS_URL = './draco_wasm_wrapper.js';
const JS_URL = './draco_decoder.js';

const DRACO_GLTF_CONFIG = {
    js: './gltf/draco_wasm_wrapper.js',
    wasm: './gltf/draco_decoder.wasm',
};

After making only this change, the project builds successfully again without any Webpack configuration changes.

This suggests that the issue is related to how Webpack treats the new URL(..., import.meta.url) references for the Emscripten JavaScript runtime files, rather than the loader implementation itself.

Since the same errors also occur for basis_transcoder.js used by KTX2Loader, I’m wondering whether this is a broader compatibility issue with Emscripten runtime .js assets and new URL(..., import.meta.url).

My questions are:

  1. Is this expected behavior with Webpack 5?
  2. Is there a recommended Webpack configuration for these loader changes?
  3. Has anyone else encountered this after upgrading to r185?
  4. Could this be considered as a three.js issue?

I’m happy to provide a minimal reproduction if that would help. Many thanks for reading.