Scenario
I'm working on a group project and one of the project maintainers understandably wants to use Next.js. We are using three.js in the project and while leveraging the GLTFLoader I've run into something unsuspected.
SyntaxError: Cannot use import statement outside a module
Which seems due to importing the GLTFLoader like so
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
I KIND OF understand why this would happen but check this out: if I comment out the import line and refresh the browser then I see a page with no errors as expected. Now the page is hot-reloading and if I uncomment the GLTFLoader import along with the GLTFLoader code then everything works as expected!
BUT
If I refresh the page manually I'm greeted with the initial SyntaxError message & description and have to comment out & uncomment code accordingly.
Question
Why is this happening? Is this a Next.js issue rather than a Webpack issue? And ultimately, how can I get around this?
Attempts
-
import { GLTFLoader } from 'three-full'; // material.customProgramCacheKey is not a function -
import { GLTFLoader } from 'three'; TypeError: three__WEBPACK_IMPORTED_MODULE_3__.GLTFLoader is not a constructor -
new THREE.GLTFLoader(); TypeError: three__WEBPACK_IMPORTED_MODULE_3__.GLTFLoader is not a constructor -
import { GLTFLoader } from 'https://threejs.org/examples/jsm/loaders/GLTFLoader.js'; // Webpack supports "data:" and "file:" URIs by default. You may need an additional plugin to handle "https:" URIs. - package.json
{ "type": "module } - etc etc
next.config.js This seems appropriate as something may need to be added here
module.exports = {
future: {
webpack5: true,
},
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
config.module.rules.push(
// ...
// Shaders
{
test: /\.(glsl|vs|fs|vert|frag)$/,
exclude: /node_modules/,
use: ['raw-loader'],
}
);
return config;
},
};
** EDIT **
I think I found a workaround https://onion2k.hashnode.dev/loading-a-gltf-model-in-react-three-fiber
** TEMPORARY SOLUTION **
import { useGLTF } from '@react-three/drei'
const assetURL = "/asset/scene.gltf";
const Asset = useGLTF(assetURL);
scene.add(Asset.scene)
useGLTF.preload(assetURL);
next-transpile-modules.