mash
mash

Reputation: 23

Uncaught SyntaxError: Cannot use import statement outside a module

https://www.youtube.com/watch?v=1TeMXIWRrqE

<!DOCTYPE html>
<html>
<head>
	<title>Three.js</title>
	<style type="text/css">
		html, body {margin: 0; padding: 0; overflow: hidden}
	</style>
</head>
<body>
  <div id="webgl"></div>
	<script src="three.js"></script>
    <script src="GLTFLoader.js"></script>
	<script>
        
    let scene,camera,renderer;
    function init(){
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xdddddd);
    
    camera = new THREE.PerspectiveCamera(40,window.innerWidth/window.innerHeight,1,5000);
    
    hlight = new THREE.AmbientLight(0x404040,100);
    scene.add(hlight);
    
    renderer = new THREE.WebGLRenderer({antialias:true});
    renderer.setSize(window.innerWidth,window.innerHeight);
    document.getElementById('webgl').appendChild(renderer.domElement);
    
    let loader = new THREE.GLTFLoader();  //THE ERROR WITH THIS, I TRIED WITHOUT THREE. ONLY GLTLOADER() BUT DID NOT WORK 
    loader.load('scene.gltf', function(gltf){
        scene.add(gltf.scene);
        renderer.render(scene,camera);
    });
}
init();
    </script>
      
</body>
</html>
https://sketchfab.com/3d-models/1972-datsun-240k-gt-non-commercial-use-only-b2303a552b444e5b8637fdf5169b41cb //https://www.youtube.com/watch?v=1TeMXIWRrqE This is tutorial for GLTFLOADER , i imported same 3d file as well and written same code, but when i open the file on local server, i get 2 errors in console: 1) "GLTFLoader.js:9 Uncaught SyntaxError: Cannot use import statement outside a module" 2) "(index):29 Uncaught TypeError: THREE.GLTFLoader is not a constructor." Although in youtube video it opens with him immediatly!! :( I would be greatful if anybody can hep me out with this. THANK YOU SO MUCH

GLTFLoader.js:9 Uncaught SyntaxError GLTFLoader.js:9 Uncaught SyntaxError

(index):29 Uncaught TypeError (index):29 Uncaught TypeError

Upvotes: 1

Views: 16012

Answers (2)

charmi shah
charmi shah

Reputation: 1

I faced a similar issue, this is how I solved it.

In your HTML, the order matters when adding other scripts as it needs certain things from Three.js.

It should be

   <script src="../build/three.min.js"></script>
   <script src="three.js-master/examples/js/controls/OrbitControls.js"></script>
   <script src="three.js-master/examples/js/loaders/GLTFLoader.js"></script>

I would suggest trying to import from your local javascript folder instead of using from jsm. I hope this will solve your issue.

Upvotes: 0

user128511
user128511

Reputation:

Here's a newer tutorial. The bottom of this article explains what changed.

The short version is three.js changed to prefer using es6 modules so instead of

<script src="three.js"></script>
<script src="GLTFLoader.js"></script>
<script>

let scene,camera,renderer;
function init(){
  ...
  THREE.GLTFLoader.load(...

you'd do this

<script type="module">
import * as THREE from './build/three.module.js';
import {GLTFLoader} from './examples/jsm/loaders/GLTFLoader.js';

let scene,camera,renderer;
function init(){
  ...
  GLTFLoader.load(...

But to use it like that requires you copy the three.js files to the same folder structure.

someFolder
 |
 ├-build
 | |
 | +-three.module.js
 |
 +-examples
   |
   +-jsm
     |
     +-controls
     | |
     | +-OrbitControls.js
     | +-TrackballControls.js
     | +-...
     |
     +-loaders
     | |
     | +-GLTFLoader.js
     | +-...
     |
     ...

If you want to use the old method <script> tag style then you need to make sure you use the files from the js folder, not the jsm folder

Note: You must use this folder structure because the files in the examples/jsm folder like GLTFLoader.js refer to various other files like three.module.js via relative but hard coded paths. For example in GLTFLoader.js there is a line which is effectively

import {stuff} from "../../../build/three.module.js";

A couple of advantages to the new style are

  1. the various modules can pull in the other parts they need.

    In the past to use one extra part you might need to add 1 to 10 other <script> tags. Now you just need 1 import and that part can pull in the other 1 to 10 parts on it's own

  2. If you build your page with a web builder it can strip out the parts you are not using.

Rumor is there are plans to get rid of the <script> method completely at some point in the future.


Just to try to make it clear both why ES6 modules are better and why you need to keep the same structure.

In pre r105 to use the EffectComposer you'd do this

<script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>

You run and you'd get an error

THREE.EffectComposer relies on THREE.CopyShader

So you'd dig around to find it, it's not in the same folder as EffectsComposer.js. When you finally find it you add it

<script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
<script src="threejs/examples/js/shaders/CopyShader.js"></script>

Run again and get another error THREE.EffectComposer relies on THREE.ShaderPass so again digging around you add that

<script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
<script src="threejs/examples/js/shaders/CopyShader.js"></script>
<script src="threejs/examples/js/postprocessing/ShaderPass.js"></script>

That sucked.

Now as of r105 using es6 modules you can just do

import {EffectComposer} from './threejs/examples/jsm/postprocessing/EffectComposer.js';

Which is arguably much nicer. You won't get the other errors because the ES6 module version EffectComposer.js can reference the files it needs, its dependencies, itself. At the top of EffectComposer.js are the references to its dependencies.

import {
    Clock,
    LinearFilter,
    Mesh,
    OrthographicCamera,
    PlaneBufferGeometry,
    RGBAFormat,
    Vector2,
    WebGLRenderTarget
} from "../../../build/three.module.js";
import { CopyShader } from "../shaders/CopyShader.js";
import { ShaderPass } from "../postprocessing/ShaderPass.js";
import { MaskPass } from "../postprocessing/MaskPass.js";
import { ClearMaskPass } from "../postprocessing/MaskPass.js";

But, as you can see above, EffectsComposer.js expects that three.module.js is in a folder called build 3 subfolders down from itself. It expects CopyShader.js is in a folder called shaders one folder down from itself. Etc...

In other words, it needs the same folder structure.

Upvotes: 5

Related Questions