Skip to content

Replace direct node js types imports#319

Open
reaktivo wants to merge 1 commit into
kozakdenys:masterfrom
reaktivo:fix/browser-node-type-imports
Open

Replace direct node js types imports#319
reaktivo wants to merge 1 commit into
kozakdenys:masterfrom
reaktivo:fix/browser-node-type-imports

Conversation

@reaktivo
Copy link
Copy Markdown

@reaktivo reaktivo commented May 7, 2026

Problem

When attempting to integrate this library into a project I noticed I started receiving compilation errors due to dependencies in Node specific types, although my project is web only.

src/types/index.ts, src/core/QRCodeStyling.ts, and src/core/QRSVG.ts all contain top-level imports from jsdom and canvas, this prevents the library from being compiled correctly on projects with skipLibCheck set to true.

import { DOMWindow, JSDOM } from "jsdom";   // types/index.ts
import nodeCanvas from "canvas";            // types/index.ts
import { Canvas as NodeCanvas, Image } from "canvas"; // QRCodeStyling.ts
import { Image } from "canvas";             // QRSVG.ts

These are Node.js-only packages. Their presence as unconditional top-level imports causes two problems for browser consumers:

  1. Bundlers fail or warn — webpack/vite/rollup try to resolve jsdom and canvas and either error out or produce warnings about missing Node built-ins.
  2. Generated .d.ts files reference the packages — anyone using the published type declarations needs @types/jsdom and canvas installed, even for a browser-only project.

Solution

Replace the three package imports with minimal structural (duck-type) interfaces defined inside the library itself:

Old New
DOMWindow from jsdom BrowserWindow (document + XMLSerializer + Image + XMLHttpRequest + FileReader)
typeof JSDOM from jsdom JSDOMConstructor
typeof nodeCanvas from canvas NodeCanvasFactory
Canvas from canvas NodeCanvasElement
Image from canvas NodeCanvasImage

The interfaces capture only the surface the library actually uses, so:

  • Existing Node.js usage (new QRCodeStyling({ nodeCanvas, jsdom })) continues to work — the real canvas and jsdom objects satisfy the interfaces structurally.
  • Browser bundles no longer see any reference to jsdom or canvas.
  • Published .d.ts files no longer expose the external packages.

Verification

npx tsc --noEmit   # 0 new errors (pre-existing @types/ws issue unchanged)

Importing from `jsdom` and `canvas` at the top level of src/types/index.ts,
src/core/QRCodeStyling.ts, and src/core/QRSVG.ts caused browser bundlers to
pull in — or fail to resolve — those Node.js-only packages. Replace all three
with minimal structural interfaces (BrowserWindow, NodeCanvasFactory,
NodeCanvasElement, NodeCanvasImage, JSDOMConstructor) that describe only the
surface the library actually uses, so the build is usable in a browser with
no extraneous Node.js dependencies.
@reaktivo reaktivo force-pushed the fix/browser-node-type-imports branch from 244c159 to d608fbd Compare May 7, 2026 15:34
@reaktivo reaktivo changed the title fix: replace jsdom/canvas imports with minimal duck-type interfaces Replace direct node js types imports May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant