Tutorial 2 - Three.js with Webpack

Overview

This tutorial describes how to setup a threejs web app using Webpack 4. To learn more about Webpack, watch the following Getting Started Guide by Gary Simon.

Setting up a Webpack 4 project

  1. Open a terminal and make a project folder.
1
2
 mkdir your_project_name
 cd your_project_name
  1. Create an empty package.json file.
touch package.json
  1. Initialise an npm project.
npm init -y

This will populate the package.json file.

  1. Edit package.json by replacing the scripts field with the following:
  1. Install webpack and it’s commandline interface.
npm i -D webpack wepack-cli webpack-dev-server

Running javascript files

By default, npm generates the package.json to run an index.js file located in a src folder. We can create this file with the following steps:

  1. Create a src folder.
mkdir src
  1. Create an empty index.js file in the src folder:
cd src
touch index.js
  1. Run serve

Creating an index.html entry point to our app

By default, webpack will only process the index.js script in src without creating any html output. In order visualise our app, we need to create an index.html file and tell webpack it’s location using the following steps:

  1. Install the html-webpack-plugin.
npm i -D webpack wepack-cli html-webpack-plugin
  1. Create a file named webpack.config.js with the following contents and place in the root project folder (click this link to download a copy of this file).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//Ensure html-webpack-plugin is pre-installed via npm.
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: [
          {
            loader: 'html-loader',
            options: {minimise: true}
          }
        ]
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: "./index.html"
    }),
  ]
};

This will tell Webpack to serve the index.html from the src folder.

  1. Create a file named index.html with the following contents and place in the src folder (click this link to download a copy of this file).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <div id="container">
    <canvas id="c"></canvas>
    <div id="labels"></div>
  </div>
</body>
</html>

<style>
html, body {
   margin: 0;
   height: 100%;
}
#c {
   width: 100%;
   height: 100%;
   display: block;
}
</style>

Visualising a rotating cube with threejs

  1. Replace index.js with the following javascript file.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
'use strict';

// Import Threejs.
var THREE = require('three');
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

// Import stats.
import * as Stats from 'stats.js';

// Scene.
var camera, scene, renderer, light;
var orbitControls;

// Stats.
var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom);

function init() {

  // Camera.
  const fov = 45;
  const aspect = window.innerWidth / window.innerHeight;
  const near = 0.1;
  const far = 2000;
  camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, 0, 500);

  const canvas = document.querySelector('#c');
  renderer = new THREE.WebGLRenderer( { canvas } );
  renderer.setClearColor(0xf0f0f0);
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  window.addEventListener('resize', onWindowResize, false);

  // Orbit controls.
  orbitControls = new OrbitControls(camera, renderer.domElement);
  orbitControls.enablePan = true;
  orbitControls.enableKeys = false;
  orbitControls.update();
  orbitControls.addEventListener('change', render);

  // Adding orbit controls to camera (expected by AMI image widgets).
  camera.controls = orbitControls;

  // Scene.
  scene = new THREE.Scene();

  // Lights.
  light = new THREE.PointLight(0xffffff, 1.5);
  light.position.set(-600, 600, 1000);
  scene.add(light);

}

// Draw Scene
function render() {
  stats.update()
  renderer.render(scene, camera);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  render()
}

// start scene
init();
render();
  1. Rerun serve