You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It should be a first step to implement features like pdfa extensions (#1705), plug in crypto (#885), export helpers (#976) without increasing the code size
This might also be the best opportunity to introduce tree shaking as well (#1570)!
Perhaps a core/document.js which is a lean PDFDocument with no mixins applied? Each mixin becomes a higher-order class, extensions (pdfa, plug in crypto, einvoices) follow the same pattern.
A default index.js composes everything for backwards compatibility and ensuring import PDFDocument from 'pdfkit' works exactly as today.
Developers that care about bundle sizes can opt in:
import { PDFDocument } from 'pdfkit/core'
import { withImages } from 'pdfkit/mixins/images'
import { withFonts } from 'pdfkit/mixins/fonts'
const Doc = withImages(withFonts(PDFDocument))
const doc = new Doc()
Bundlers will drop anything not imported. I think we may need to set "sideEffects": false in package.json to signal to bundlers we safe to tree shake.
A few more things to consider...
Initialisation chain, mixins use a iniX() method called from the document constructor. With higher-order classes, each wrapper overrides the constructor and calls super(), allowing each layer to init itself.
Dependency order, vector mixin depends on color; images depends on color. Probably best way to go about this is have each withX automatically compose its own dependencies, e.g. withImages internally applies withColor if not already applied (detectable through a static symbols/flag on the class).
An exports map in package.json exposing pdfkit/core, pdfkit/mixins/* and possibly pdfkit/extensions/* or what they may end up being called.
Perhaps this is also an opportunity to introduce typescript definitions? I don't personally use it, but I'm sure somebody out there might want it directly from PDFKit. The higher-order class patten makes this a good opporunity to add, each withX wrapper can ship its own .d.ts rather than trying to maintain one giant declaration file. Just worth considering!
I'm happy to put together a proof of concept if you're interested, let me know !
Activity
andreiaugustin commentedon Mar 21, 2026
This might also be the best opportunity to introduce tree shaking as well (#1570)!
Perhaps a
core/document.jswhich is a leanPDFDocumentwith no mixins applied? Each mixin becomes a higher-order class, extensions (pdfa, plug in crypto, einvoices) follow the same pattern.A default
index.jscomposes everything for backwards compatibility and ensuringimport PDFDocument from 'pdfkit'works exactly as today.Developers that care about bundle sizes can opt in:
Bundlers will drop anything not imported. I think we may need to set
"sideEffects": falseinpackage.jsonto signal to bundlers we safe to tree shake.A few more things to consider...
Initialisation chain, mixins use a
iniX()method called from the document constructor. With higher-order classes, each wrapper overrides the constructor and callssuper(), allowing each layer to init itself.Dependency order,
vectormixin depends oncolor;imagesdepends oncolor. Probably best way to go about this is have eachwithXautomatically compose its own dependencies, e.g.withImagesinternally applieswithColorif not already applied (detectable through a static symbols/flag on the class).An
exportsmap inpackage.jsonexposingpdfkit/core,pdfkit/mixins/*and possiblypdfkit/extensions/*or what they may end up being called.Perhaps this is also an opportunity to introduce typescript definitions? I don't personally use it, but I'm sure somebody out there might want it directly from PDFKit. The higher-order class patten makes this a good opporunity to add, each
withXwrapper can ship its own.d.tsrather than trying to maintain one giant declaration file. Just worth considering!I'm happy to put together a proof of concept if you're interested, let me know !
blikblum commentedon Mar 21, 2026
In medium term we can make something like that, but initially this issue is only to change to named export.