Run three.js with SvelteKit
Date: 2023-05-07 | create | ctech | threejs | sveltekit |
SvelteKit has been my frontend framework of choice in recent years. Now that I'm getting back into Creative Technology, I wanted to figure out how to use creative coding libraries I love (here three.js) with my go-to tech stack.
In this post, we'll walk through how to get three.js working with a SvelteKit site.
Prerequisites
There are a few things you'll need to follow this tutorial successfully.
- A SvelteKit project - I'm going to assume you already have a SvelteKit site that you can run locally. If not, no worries - follow the offical SvelteKit get started tutorial then come back here.
- three.js install - You'll need
three
installed in your project so we can use it. Install the official three.js npm package withnpm i three
- [Optional] three.js types - I think types make all projects better. three.js types are available in the @types/three npm package
With your SvelteKit project ready to run locally with three.js installed, we can continue on with the walkthrough.
Demo
Before we get into code, I want to give you an idea of what we expect this code to do when we run it.
We'll be creating a simple three.js scene with a rotating cube and serving it with our SvelteKit site. This allows us to touch on several different three.js components (camera, objects, renderers, etc) without getting too complicated to prove everything works. It's also a common first scene in tutorials so this should be relatively easy to follow.
Here's an example running vanilla JS from the official three.js docs:
Code
HAMINIONs members have access to the full three.js + sveltekit site project files demoed here.
Implementing this code in SvelteKit is surprisingly easy.
In a framework like React we'd often need to work around the built-in renderer, using things like dangerouslySetInnerHTML
which feels bad. We still need a little bit of extra code to make it clear to SvelteKit how we want it to render but the boilerplate is minimal.
Here's the code:
routes/+page.svelte
<script lang="ts">
import { browser } from '$app/environment';
import * as THREE from "three"
if(browser) {
let camera : THREE.PerspectiveCamera;
let scene : THREE.Scene;
let renderer : THREE.WebGLRenderer;
let cube : THREE.Mesh<THREE.BoxGeometry, THREE.MeshBasicMaterial>;
const init = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
}
const render = () => {
renderer.clear()
renderer.render(scene, camera);
}
const animate = () => {
requestAnimationFrame(animate)
cube.rotation.x += 0.005
cube.rotation.y += 0.005
render()
}
init()
animate()
}
</script>
<svelte:head>
<title>SvelteKit + ThreeJS</title>
</svelte:head>
<section>
Hello World.
</section>
Note: I'm using TypeScript here hence the type declarations. If you're using plain JavaScript instead, simply remove the type declarations and everything should work fine.
Most of this code is similar to the vanilla JS embed example found above. But there are a few key differences to get this working nicely with SvelteKit which we'll dive into here:
- URLs and
+page.svelte
- The first thing to note is that this code lives in a+page.svelte
file. This is part of SvelteKit's routing system in which url routes are mapped to subdirectories of/routes
and then to a corresponding+page.svelte
in that directory. This allows us to access our scene by simply navigating our web browser to the corresponding URL.- Example: This code lives at
/routes/+page.svelte
so it's accessible atWEBSITEURL/
- Example: This code lives at
<script>
tags - If you're new to SvelteKit you may be confused by all these sections. Basically it works similarly to a vanilla HTML / JS setup where we put our JS in ascript
tag and have it run on page load.import { browser } from '$app/environment'
- We are using SvelteKit's built inbrowser
variable to determine if SvelteKit is trying to render on the server vs in the browser. Usually we like server-side rendering but for things that rely on external libraries and have dynamic content / can't be re-rendered - we actually want these to render client side. Threejs projects typically will need access to the browser window and canvas which only lives client side so we leveragebrowser
to make sure we only try to render this on the client.
Next Steps
You should now have a working three.js + sveltekit sketch! Happy coding!
- Get the full three.js + SvelteKit projects files I used to demo through the HAMINIONs membership.
- You can find some of the three.js creations I've released on IG: hamy.art
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.