CanvasKit: Bringing Skia to the Web (And Its Rough Edges)

The Problem

You want Skia's power. In the browser. Without plugins.

Historically, impossible. Browsers give you HTML Canvas—a simple 2D drawing API that's fine for basic graphics but lacks advanced features. No complex path operations. Limited text shaping. No hardware-accelerated effects.

Then WebAssembly arrived.

What CanvasKit Is

CanvasKit is Skia compiled to WebAssembly (WASM). The entire C++ graphics library, running in your browser at near-native speed.

It exposes Skia's API through JavaScript bindings. You get:

Download size: ~2.9MB gzipped. That's the entire graphics engine.

Who Uses CanvasKit

Flutter Web: Switched exclusively to CanvasKit renderer. Every Flutter web app uses it.

Shopify: Built react-native-skia with CanvasKit for web support. React Native apps can now use Skia across mobile and web.

AntV (Ant Group): Created @antv/g-canvaskit renderer for their graphics library.

Figma (partially): Uses custom WebGL code primarily, but leverages Skia for specific algorithms.

43+ npm packages: Various frameworks and libraries building on CanvasKit.

The First Failed Attempt: The Fiddle

Official documentation points to https://jsfiddle.skia.org/canvaskit for an online playground.

Problem: It doesn't work. As of 2024, users get 403 Forbidden after Google login. The CanvasKit fiddle has been down intermittently.

The main Skia Fiddle (fiddle.skia.org) works for C++ code, but that's not helpful for web developers trying to learn CanvasKit.

Reality: No working online playground means learning from docs and examples alone. The docs exist, but...

The Documentation Problem

CanvasKit documentation exists at https://skia.org/docs/user/modules/canvaskit/

Here's what's actually there:

Here's what's missing:

The documentation assumes you know Skia's C++ API and can translate. If you don't, good luck.

What the Docs Don't Tell You: Memory Management

Critical rule: Objects created with new or Make* methods must be deleted manually.

const paint = new CanvasKit.Paint();
// ... use paint ...
paint.delete();  // MUST call this

JavaScript's garbage collector does not clean up WASM memory. Forget to delete, memory leaks forever (until page reload).

The mistake everyone makes: Creating paths/paints inside render loops without deleting them. 100 frames = 100 leaked objects.

We'll cover proper patterns in the interactive examples.

Bundler Integration Hell

Webpack Issues

Vite Issues

The Reality

Most CanvasKit projects include a webpack.config.js or vite.config.js with cryptic workarounds. Copy-paste and pray.

React Native Skia: Shopify's Approach

Shopify built react-native-skia to bring Skia to React Native. For web support, it uses CanvasKit.

Key insight: They wrapped CanvasKit in a declarative API. Instead of imperative draw calls, you describe what to draw:

<Canvas>
  <Rect x={0} y={0} width={256} height={256} color="blue" />
</Canvas>

The library handles:

This is not a CanvasKit fork. It's a high-level API that uses CanvasKit for web and native Skia for mobile.

Worth considering if you're building in React.

Who Actually Uses CanvasKit Directly

Flutter: No choice, it's the renderer.

Custom renderers: Building design tools, canvas apps, visualization libraries.

Performance-critical apps: Need GPU acceleration HTML Canvas can't provide.

Cross-platform tools: Want identical rendering on web and desktop (via Skia).

Most developers: Use a framework on top (Flutter, react-native-skia, AntV).

The Advantages (Why We Chose It)

1. Real GPU Acceleration

CanvasKit uses WebGL/WebGPU. Complex paths render fast. Effects are hardware-accelerated. HTML Canvas can't compete.

2. Feature Parity

Need custom blend modes? Advanced text? Path boolean operations? CanvasKit has it. Canvas API doesn't.

3. Identical Rendering

Skia on desktop + CanvasKit on web = pixel-perfect match. Critical for design tools.

4. Control

Low-level API means no magic. You control clipping, layers, GPU resources. When you need performance, this matters.

The Disadvantages (Why It's Painful)

1. Size

2.9MB gzipped is significant. Your bundle is instantly larger. First load is slower.

2. Learning Curve

Not HTML Canvas. Not SVG. It's Skia's API, translated to JavaScript. Expect weeks of learning.

3. Memory Management

Manual deletion or memory leaks. No escaping it.

4. Debugging

Errors in WASM are cryptic. Stack traces are useless. console.log() is your friend.

5. Bundler Hell

Every build tool needs custom configuration. Expect half a day fighting Webpack/Vite.

Interactive Examples (Planned for This Series)

We're building interactive examples you can run in your browser:

Example 1: "Hello Rectangle"

What it shows: Basic CanvasKit setup, creating a surface, drawing a rectangle Memory lesson: Proper paint creation and deletion ~50 lines of code

Example 2: "Animating a Circle"

What it shows: Render loop, requestAnimationFrame integration, transform matrices Memory lesson: Reusing paint objects vs creating new ones ~100 lines of code

Example 3: "Path Operations"

What it shows: Creating paths, combining them (union/intersect), stroking vs filling Memory lesson: When to delete paths, when to reuse them ~150 lines of code

Example 4: "Text Rendering"

What it shows: Font loading, text shaping, paragraph layout Memory lesson: Font and paragraph object lifetimes ~200 lines of code

Example 5: "Layers and Effects"

What it shows: saveLayer(), blur effects, blend modes Memory lesson: Layer stack management, filter ownership ~200 lines of code

Each example will be fully interactive with editable code and live output. We'll highlight the lines where memory management matters.

When to Use CanvasKit

Use CanvasKit when:

Don't use CanvasKit when:

The Reality Check

CanvasKit brings Skia's power to the web. But it's not polished. Documentation is sparse. Bundler integration is messy. Memory management is manual.

We spent months learning this. We hit every edge case. We wrote workarounds for everything.

This series documents what actually works. Not what the docs say. What survives production.

Next article: Why we couldn't use Skia's Path API for Figma-style vector networks.


Key Resources


Read next: Why We Can't Use Skia's Path API