Error: The import statement is invalid when used outside of a module

Click here to watch the video

<!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 initialize(){
    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();  
    loader.load('scene.gltf', function(gltf){
        scene.add(gltf.scene);
        renderer.render(scene,camera);
    });
}
initialize();
    </script>
      
</body>
</html>
View the 3D model on Sketchfab If anyone can assist with solving the errors I encountered while following a GLTFLOADER tutorial, it would be greatly appreciated. Thank you!

Encountered Error: GLTFLoader.js:9 Uncaught SyntaxError https://i.sstatic.net/apJnn.jpg

Uncaught TypeError at line 29: (index) https://i.sstatic.net/sa1xp.jpg

Answer №1

Check out this more recent tutorial. At the end of this post, you'll find information on the updates.

In summary, three.js now emphasizes 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 should use

<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(...

To implement it like that, you need to copy the three.js files to match the folder structure shown.

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

If you prefer the old method with <script> tags, make sure to use files from the js folder, not the jsm folder.

Note: It's important to maintain this folder structure because files in the examples/jsm folder, like GLTFLoader.js, reference other files with relative but hardcoded paths. For example, in GLTFLoader.js, there's a line that looks like:

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

Some benefits of the new format include

  1. Modules can pull in their needed parts easily. In the past, one additional part could require multiple <script> tags, now it's just 1 import that handles everything.

  2. Your webpage builder can strip out unused parts with ease.

There are talks about phasing out the <script> approach entirely in the future.


Let's clarify why ES6 modules are better and how the consistent folder structure is crucial.

Prior to r105, to use EffectComposer, you'd do

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

You'd encounter an error

THREE.EffectComposer relies on THREE.CopyShader

You'd have to manually add dependencies like

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

Now, thanks to es6 modules from r105 onwards, you can simply write

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

which is much cleaner. The ES6 module version of EffectComposer.js manages its own dependencies, making the process seamless. Check the top of EffectComposer.js for references to its requirements.

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";

As seen above, EffectsComposer.js expects certain folders to be in specific locations, affirming the importance of maintaining consistent folder structure.

Answer №2

I encountered a similar problem, and here is how I managed to resolve it.

When working with your HTML file, the sequence in which you include other scripts is crucial as Three.js requires specific dependencies.

The correct order 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>

It is advisable to try importing from your local JavaScript directory instead of using jsm. Hopefully, this approach will help you resolve the issue at hand.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming MongoDB array into a string within the database

I am facing an issue with parsing arrays from Mongo/Express. The array from the body appears to be correct when I check the response in the node console. However, the problem arises when I attempt to save the body to the Mongo database using the insert.one ...

A prompt box in Internet Explorer using the InternetExplorer.Application in PowerShell

I'm having trouble adding a value to the pop-up window. Here is the code: <!DOCTYPE html> <html> <body> <h2>PS Prompt test</h2> <button onclick="Function()" id="test">send value</button> <p id="demo"&g ...

Having difficulty completing the text field and submitting it automatically

My goal is to automatically fill in the "Reason for Access" text box with the word "TEST" using Tampermonkey. I am new to using Tampermonkey and UserScript, so I appreciate your patience. Currently, I am facing an issue where the "Reason for Access" field ...

Analyzing the latest "barchart.com" website

Is there a way to extract data daily from barchart.com, specifically the close/open/high prices? I can't find the values in the page code or the JavaScript script that loads it. Maybe downloading the Excel file using the "download" button is easier, b ...

Failure occurs when attempting to utilize external .js and .css files

As I embark on creating a website using Bootstrap, I stumbled upon a registration page code that consists of three files - HTML, CSS, and .js. registration.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> ...

Retrieve the URL with a GET request and remove a specific object

Currently, I am working on developing a CRUD (Create, Read, Update, Delete) App using Express and LowDB. So far, I have successfully implemented the create and read functions, but I am facing issues with the delete function. This is an example of what th ...

React Navigation - CSS file identified as "text/html" after introducing a dynamic route parameter (/userId)

Our customized stylesheet "styles.css" seems to be incorrectly identified with the MIME type "text/html", even though it is specified as: rel="stylesheet" type="text/css" This issue only arises when navigating to routes with a variable parameter such as ...

When initializing React Native, the Android, iOS, and app folders seem to be missing

https://i.sstatic.net/bkmvE.png Where have my android, ios, and app folders gone? Also, why are the index js files missing? I am currently working with React Native version 0.1.10 on a Windows 7 operating system. ...

Retrieve the file from Amazon S3 and download it

I'm having an issue with downloading a file from a directory outside of the root. Whenever I try, it defaults to looking in the root directory. I need users to be able to download these files on my site. The file was initially uploaded to Amazon S3 a ...

Different ways to implement the Vue search select feature in various form structures

I am facing an issue with showing select options of my product in multiple forms. Whenever I choose one option in one form, all the other select forms also change automatically. How can I make each select form unique? Here is what I have tried: My selec ...

What is the best way to pass a variable between clusters in a Node.js application?

I have implemented clusters in my express application, where the master node has a caching system with a variable that needs to be shared across worker nodes. I am looking for a way to achieve this without using a physical datastore. Can the following ap ...

Wheelnav.js implementing a dynamic bouncing animation

I'm currently in the process of working on a pie menu with wheelnav.js and everything is going smoothly so far. However, I can't seem to find any information in the wheelnav.js documentation on how to eliminate the bouncing effect when a menu cho ...

Unusual behavior: Django app not triggering Ajax XHR onload function

I'm currently working on a Django app that features user posts, and I'm in the process of implementing a 'like' / voting system. Initially, I set up this functionality using complete page refreshes combined with a redirect after the vot ...

Django AJAX call for data retrieval

Can someone assist me, please? I'm trying to update content on a page without refreshing when a button is clicked. Currently, my approach involves using the jQuery cookie plugin to save the button's id into a cookie and then reading that value in ...

Struggling to grasp the concept within this particular Array.map callback

Within my React component, I am exploring the concept of the this keyword and its context with the following code snippet. While this example may seem simple, it is part of my efforts to enhance my comprehension. const NAVBAR_ITEM_TITLES = ["Home" ...

Finding a quicker route to fulfill a commitment

When dealing with asynchronous behavior in a function, I often find myself creating a deferred and returning a promise. For example: var deferred = $q.defer(); //...some async operation return deferred.promise; However, sometimes I want to skip the async ...

Guide to generating a continuous flow of numbers in real time with Node.js using sockets, followed by capturing and displaying the data on an HTML page

What is the best method to generate an endless stream of numbers using nodejs and web sockets (preferably socket.io) on a backend server, then display them on an HTML page using JavaScript? ...

Why isn't my script responding to mouse events like mouseenter, mouseover, or any other mouse event?

const element = document.getElementById("box"); element.addEventListener("mouseenter", handleMouse); function handleMouse(event) { console.log("Event type: " + event.type); } ...

Two entities positioned on opposite extremes

Is there a way to design a div with two elements (text and image) positioned on opposite sides? The length of the text varies as it's a list of months for selection. Ideally, the text should appear on the left side of the div as a "p" element, while t ...

Adjusting the heights of all elements with identical ids simultaneously

I found the following code: <div xmlns="http://www.w3.org/1999/xhtml" style="z-index: 1; position: absolute; top: 90px; left: 90px; background: none repeat scroll 0% 0% black; width: 800px;" id="mainDiv"> <div style="width: 405px;" class= ...