Reputation: 32247
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.
{ "type": "module }
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);
Upvotes: 2
Views: 3000
Reputation: 32247
I ended up using next/dynamic
import dynamic from 'next/dynamic';
...
const DynamicPackage = dynamic(() => import('package'), { ssr: false });
Upvotes: 1