Next.js seemingly erroneous message "SyntaxError: Cannot use import statement outside a module"

Viewed 1824

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);
1 Answers

I ended up using next/dynamic

import dynamic from 'next/dynamic';

...

const DynamicPackage = dynamic(() => import('package'), { ssr: false });
Related