How to Replace node-canvas with a CI-Friendly Alternative
node-canvas compiles against Cairo, Pango, and Pixman, so slim runners break on missing headers. The reliable fix is often to switch to an engine-bundling alternative.
The classic canvas (node-canvas) package builds a C++ addon against Cairo, Pango, Pixman, and JPEG dev libraries - a frequent CI failure when those system packages are absent. When you do not need node-canvas-specific APIs, a Skia-based alternative that bundles its engine removes the system-library build entirely.
Why it fails in CI
- node-canvas needs
libcairo2-dev,libpango1.0-dev,libjpeg-dev,libgif-dev- slim/Alpine images lack them →fatal error: cairo.h. - A source build also needs python3 + g++; missing on minimal images.
- Alpine/musl has limited prebuilt coverage, forcing a heavy source build.
Install it reliably
Either install node-canvas system libraries, or migrate to an engine-bundling alternative. @napi-rs/canvas (Skia, N-API) and skia-canvas ship prebuilt binaries with no Cairo/Pango requirement and are the lowest-friction CI choice.
# Option A: keep node-canvas (Debian/Ubuntu system libs)
apt-get update && apt-get install -y \
build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
npm ci
# Option B: migrate to a bundled-engine alternative (no system libs)
npm install @napi-rs/canvas # or: npm install skia-canvasCache & speed
For node-canvas, cache ~/.npm + ~/.cache/node-gyp and bake the Cairo/Pango libs into a custom image. For the alternatives there is nothing to compile - caching ~/.npm is enough.
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}Common errors
fatal error: cairo.h: No such file or directory→ install the Cairo/Pango dev libs, or switch to a bundled-engine alternative.Package pangocairo was not found(pkg-config) → installlibpango1.0-dev.- Heavy source build on Alpine → use
@napi-rs/canvas/skia-canvasinstead.
Key takeaways
- node-canvas needs Cairo/Pango/Pixman/JPEG dev libs plus a C++ toolchain.
- Engine-bundling alternatives (@napi-rs/canvas, skia-canvas) skip the system-library build.
- Bake the system libs into the image if you must keep node-canvas.