Importing Three.js as module

Im learning three.js and are setting up my first project. Im basically running the example code from three.js website. It works fine when running three.js from a folder like:

js/ directory

but I cannot get it to run when importing it as a module. Im installing the module with:

npm i three

And running it as a local server by installing:

npm install http-server -g

and then running my file test.html on port: 8000

http-server . -p 8000

http://localhost:8000/test.html

Here is the full code in my body:

<body>
    <script>
        import * as THREE from 'three';

        const scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        var geometry = new THREE.BoxGeometry(1, 1, 1);
        var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        var cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        camera.position.z = 5;

        var animate = function () {
            requestAnimationFrame(animate);

            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;

            renderer.render(scene, camera);
        };

        animate();
    </script>
</body>

How come I cannot import the module? Im getting this errormessage in the browser:

Uncaught SyntaxError: Cannot use import statement outside a module

Using npm modules normally means you perform some sort of build which is then included into your html page. Check out the following start project that demonstrates how such a setup does look like:

In any event, if you use ES6 import statements inside a <script> tag, you have to write it like so <script type="module">.

2 Likes

You are right. But I tried
script type=“module”

But didnt worked anyway.
In getting:
TypeError: Error resolving module specifier: three .

I have to provide the full path for it to work: import * as THREE from './node_modules/three/build/three.module.js';

Do I need to use webpack to be able to define the path to the modules?

A build tool like rollup will be able to resolve import * as THREE from 'three';. But notice that this statement does not work if you put it directly in a HTML page (since the browser does not know how to resolve three).

Fors this mean that i cannot use import * if Im running my page as a local server? Or what do you mean with directly :slight_smile:

It does not matter where the app is hosted. No browser can resolve three. If you study how ES6 modules work, this topic will automatically become clear.

https://exploringjs.com/es6/ch_modules.html

2 Likes

Hi @Mugen87,
I’m trying to import Three.js as a module according to the ES6 syntax as shown here in the 2nd example: https://threejs.org/docs/#manual/en/introduction/Import-via-modules

…and receive this error:
image

But everything seems to be made according to the documentation:

So it’s not 100% clear whether Three.JS will work as a module in HTML or not. Because, documentation refers to this doc, which says that it should.

All official examples are using modules. So yes, it definitely works. The following example is one of the more simple demos that demonstrates the respective setup:

https://threejs.org/examples/webgl_geometry_cube

In your code, you do:

import * as THREE from './build/three.js';

Is this three.js version actually an ES6 module? I would normally expect this line:

import * as THREE from './build/three.module.js';
1 Like

Ah, got it! Thank you.
But, I must admit that the documentation, in this case, is confusing. Because there is a link to MDN where they say how to use ES6 modules in HTML and right under the link you’ve got the code sample. Automatically you copy and paste the code and expect it to work. And I totally forgot that there is a third .js file in the build folder. That’s why didn’t try it.

Hi Mugen87, I saw your example project and I have a question.
That is how to run the following code to start the app?

    const app = new LIB.App();
    app.init();

Yes. App.init() represents the entry point of the app and in some sense the init() functions from the official examples.

Thanks for your answer but i mean i don’t know how to run the code.
I installed rollup package and included a build file to HTML page too. But I could not image how to run the code you shared.

Can you please share your current work of progress as a git repo?

I forgot to update the latest version to github, so can I share it with you tomorrow?

Hi Mugen87, this is the git repo that I’m working on:

https://github.com/nguyenhaininh/threeJS

Just put this code in your index.html:

<script src='build/main.umd.js'></script>
<script>
    const app = new UMD.App();
    app.init();
</script>

App is defined in the namespace UMD because that’s the name you have chosen in your rollup.config.js.

1 Like

Ah, i got it!
Thank you so much.

This boilerplate demonstrates importing threejs modules using ES6 syntax in the client.
There is no need to add libs on the client to handle requires, umd, exports, defines, systemjs.
You also don’t need to bundle using webpack, rollup, parcel, browserify, bunch, fusebox or any other magic.

The boilerplate also includes a NodeJS server component and is written in typescript.
It demonstrates how to import the main three.module.js and also the orbitcontrols.

Guys do you know what am I doing wrong?

When you include a module file via a script tag, you need to add type="module" to it.

However, in app.js you can’t import modules by just using the module name like three. That only works when using a build tool like rollup that produces a bundle from your source files. Try it with this instead:

import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.114/build/three.module.js";
2 Likes