Getting Started with Three.js + TypeScript

Back

For a long time, Three.js has been a fascination of mine: the beautiful graphics, the engaging animations, the quirky colors and effects, the interactive experiences. Yet, I struggle to even get started.

The examples on the Three.js website are an inadequate way to start a proper project. Everything inside a single index.html file? Loading from a CDN? Where's the dependency management? The build system? The live reload?

Of course, these examples are great as for showcasing specific features. They’re not so great for anything more substantial. So after hitting my head against the wall with the same infrastructure-related problems time and again, I decided to do the only logical thing.

Create (yet another) Three.js + TypeScript boilerplate project.

In this blog post, I’ll walk you through my starter and how to use it, so you don’t have to spend hours debugging why a model or texture isn’t loading. I’ve done that for you. And if not, let me know.

Three.js + TypeScript + Vite Starter Project

I present you with the simple-threejs-typescript-starter! A name that really rolls off the tongue. You can find the repository here:

https://github.com/mayacoda/simple-threejs-typescript-starter

What do you get?

All the hard parts of setting up a project, solved ✅

Hard parts include:

Why TypeScript and Vite?

TypeScript is a superset of JavaScript that enables strong typing and better tooling.

I personally prefer the type safety and autocompletion it offers. With a modern IDE and a library as expansive as Three.js, TypeScript can act as a map through uncharted territory. It’s also very useful for setting up larger projects, but we'll get into that in a later post.

Vite is the new build tool which has been proving itself quite well. It's fast and very simple to use. This project doesn't include any special configuration, everything works out of the box.

Structure of the Boilerplate

The project is composed of the scaffolding and an example to showcase scene creation, model and texture loading, and creating a render loop.

The example is located under /src/example and its assets live under /public/space_dog

There are also a few quality of life utilities under /utils/ which you may or may not need. These can be removed freely.

⚡️

The important part is the /src/main.ts file which acts as the entry point for your project and the single canvas element inside the index.html.

Setting up your local project

To use this boilerplate, you'll have to clone the repository in your own project, in this case one called my-threejs-project, and install its dependencies.


_3
git clone https://github.com/mayacoda/simple-threejs-typescript-starter my-threejs-project
_3
cd my-threejs-project
_3
yarn install

If you are on GitHub, create a new repository using this repository as a template by clicking the green Use this template button in the top right.

Use this template button

After you have cloned the project locally, you can start the development server using


_1
yarn dev

Your server will be running at http://localhost:3000 and you can open the browser to see the example.

3D render of a cartoon dog with a space helmet floating against a starry background
🗑

After you’ve explored the boilerplate project, you’ll probably want to remove the sample scene and get to making your own. You can do this by running the command yarn remove-example which will remove all the example code and assets.

Asset handling

Because Vite does cache-busting by default, it can be a bit difficult to load assets required for Three.js. The simplest solution is to store all assets in the /public directory. Everything in this directory gets copied to the project root when you run yarn build.

These assets are therefore always available, even if Vite doesn't register that they're being used in the project. This feature can be especially useful for loading models and textures with Three.js, as Three.js loaders dynamically fetch assets referenced in other assets (e.g. texture maps referenced in MTL files).

Debug GUI

The project uses lil-gui for UI controls. The UI is loaded only when the application is running in debug mode, and you can do this by adding ?debug=true to the URL.

To add UI controls, you can access the single lil-gui instance with the getDebugUI function. The controls will only show up with the flag, so you can also debug in production ✨


_12
import { getDebugUi } from '../utils/debug-ui'
_12
_12
const gui = getDebugUi()
_12
_12
gui.addColor(light, 'color').name('ambient light color')
_12
_12
gui
_12
.add(light, 'intensity')
_12
.min(0)
_12
.max(1)
_12
.step(0.0001)
_12
.name('ambient light intensity')

Final Thoughts

I hope this little starter is useful for you. As I develop more Three.js things, I plan on updating it accordingly. In the meantime, happy coding!

👋

Follow me on Twitter @maya_ndljk or on GitHub @mayacoda for more Three.js related stuff.

2023 © Maya Nedeljković Batić.