๐ŸŒ Web Game Engines & Libraries

The technology that enables 2D and 3D graphics for the web is WebGL WebGL (opens in a new tab) (WebGL2 (opens in a new tab) for engines that support it). WebGPU WebGPU (opens in a new tab) is an upcoming more performant technology but is currently behind feature flags (opens in a new tab) (it may come in Chrome desktop (opens in a new tab) around May 2023!). Writing raw WebGL code would be very tedious, so there are libraries that abstract the complexity and do the heavy-lifting to provide more user-friendly APIs.

Engines and libraries

Much like any ecosystem of developer tools, there are 2 approaches: the monolithic batteries-included framework approach (those would be the engines), or the modular assemble-independent-libraries-together approach. The main engines and libraries for JavaScript game development are:

Compare on NPMTrends and Star History (requires a GH token)

About these numbers and colors

There is also Rogue Engine Rogue Engine (opens in a new tab) โ€“ an editor for Three.js, React Three Fiber Triplex (opens in a new tab) โ€“ the React Three Fiber editor, Ethereal Engine Ethereal Engine (opens in a new tab) โ€“ a full-stack solution for metaverse experiences, and many more engines and libraries (opens in a new tab).

UI libraries wrappers

You can use any of the previous libraries and engines on their own, but some of them can also be combined with UI libraries wrappers for React, Svelte, Vue, or Angular. This might seem surprising at first, but using these makes your code more declarative and conveniently abstracts some boilerplate. The main wrapper libraries are:

Three.js Three.js

Babylon.js Babylon.js

Pixi.js PixiJS

Phaser Phaser

OGL OGL

For instance, React Three Fiber (R3F), lets you add objects to a scene and control them as React components:

import { useRef, useState } from 'react'

import { Canvas, useFrame } from '@react-three/fiber'

const Box = (props) => {
  const ref = useRef(null)
  const [hovered, setHovered] = useState(false)
  const [clicked, setClicked] = useState(false)

  useFrame((_, dt) => {
    ref.current.rotation.x += dt
  })

  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={() => setClicked(!clicked)}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <boxGeometry />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

const App = () => (
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>
)

export default App

Going native with JavaScript

Now hold on to your hats, because this is where things get wild. You can also use JavaScript (well, mostly React) to create native OpenGL ES games. Expo (opens in a new tab) is a framework for React Native (opens in a new tab) (it is basically the Next.js of React Native), and they created Expo GL (opens in a new tab) and expo-three (opens in a new tab) to provide a Three.js interface for native OpenGL ES. And it can be used declaratively with React Three Fiber (opens in a new tab). I have not tried it yet but that completely blows my mind ๐Ÿคฏ.

Babylon.js is working on a similar preview feature with Babylon Native (opens in a new tab) and Babylon React Native (opens in a new tab).