Skip to content

fix: bundle harfbuzzjs so consumers do not resolve the unpatched package - #796

Open
Nixxx19 wants to merge 1 commit into
vercel:mainfrom
Nixxx19:fix/bundle-harfbuzzjs
Open

fix: bundle harfbuzzjs so consumers do not resolve the unpatched package#796
Nixxx19 wants to merge 1 commit into
vercel:mainfrom
Nixxx19:fix/bundle-harfbuzzjs

Conversation

@Nixxx19

@Nixxx19 Nixxx19 commented Aug 31, 2026

Copy link
Copy Markdown

fixes #791
fixes #794

harfbuzzjs is left external in the published bundle, so all four dist entries end up with a bare require("harfbuzzjs") and we ship no hb.wasm. whoever installs satori gets the plain package, and its loader reads __dirname + "/hb.wasm". once a bundler moves that code __dirname isn't node_modules/harfbuzzjs anymore, so the wasm isn't where it looks. on a worker target it doesn't even get that far, it dies resolving fs.

no framework needed to see it, npm i satori@0.33.4 esbuild and put dist/index.js through esbuild with platform: 'browser':

✘ [ERROR] Could not resolve "fs"

    node_modules/harfbuzzjs/hb.js:1:820:
      1 │ ...NMENT_IS_NODE){var fs=require("fs");scriptDirectory=__dirname+"/...
        ╵                                  ~~~~

with platform: 'node' and cjs it bundles fine and then rendering aborts, ENOENT ... <outdir>/hb.wasm.

ci doesn't catch either of these because patches/harfbuzzjs@0.10.0.patch drops the fs branch and inlines the wasm, so test/browser-build.mjs has only ever bundled a harfbuzzjs that was already fixed. the patch doesn't reach anyone installing satori.

so this adds harfbuzzjs to noExternal like yoga-layout, and makes browser-build.mjs fail if a dist entry still imports it. that check does fail on main, i ran it before adding it. suite still green locally, 512 tests.

the cost is size, since the wasm is in the bundle now. index.js goes from 122 to 330 KB gzipped, standalone from 83 to 291.

the standalone number is the one worth arguing about, it had no wasm inlined before this. i went this way because shaping isn't optional since 0.33 so standalone needs the wasm regardless, and this way nobody has to touch their code. if you'd rather keep standalone small the other shape is shipping hb.wasm as a subpath export with an init like yoga has, but that breaks everyone already on satori/standalone and i didn't want to make that call inside a bug fix. happy to redo it that way.

@Nixxx19
Nixxx19 requested a review from shuding as a code owner August 31, 2026 20:33
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
satori-playground Ready Ready Preview, v0 Sep 1, 2026 6:57am UTC

@Nixxx19
Nixxx19 force-pushed the fix/bundle-harfbuzzjs branch from 6d97c70 to 74809de Compare September 1, 2026 06:57
wei added a commit to wei/socialify that referenced this pull request Sep 4, 2026
Runtime: Next.js 16.1.7→16.3.4, React/React DOM 19.2.4→19.2.8,
satori 0.25.0→0.32.0, Tailwind CSS 4.2.1→4.3.3, daisyUI 5.5.19→5.7.28,
simple-icons 16.29.0, react-icons 5.7.0, badgen 3.3.2, use-debounce 10.1.1.

Tooling: Playwright 1.62.1, Jest 30.5.1, ts-jest 29.4.12, Biome 2.5.11,
changesets CLI 2.30.0→3.0.1, @testing-library/jest-dom 6→7, postcss 8.5.27.

Package manager: pnpm 10.27.0→11.25.0. Migrates pnpm-workspace.yaml from the
removed onlyBuiltDependencies to allowBuilds, and sets verifyDepsBeforeRun:
false so `pnpm build` inside the e2e/Docker containers does not trigger a
modules purge that aborts without a TTY.

Actions: checkout v7, setup-node v7, cache v6, pnpm/action-setup v6,
action-gh-release v3, changesets/action v1→v2 (all inputs renamed, and
github-token is now an input rather than a env var).

UI drift is limited to two reviewed changes, both re-baselined:
- daisyUI 5.7 fixes `.alert:has(:nth-child(2))` to `:has(>:nth-child(2))`,
  so the toast no longer gets a phantom second grid column and is 16px
  narrower. Adds `border-0` to the two bare `.join-item` icon prefixes to
  suppress daisyUI 5.7's new unconditional join-item border.
- Next.js 16.3 shifts mobile layout just enough to change Playwright's
  scroll-into-view decision in one snapshot; rendering is unchanged.

Held back: TypeScript 7.0.2 (no JS compiler API until 7.1, so ts-jest cannot
transform), satori 0.33 (bundles harfbuzzjs wasm that cannot resolve in the
Next.js edge runtime, see vercel/satori#796).
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.

Build fails after introducing HarfBuzz 0.33 harfbuzzjs hb.wasm fails to resolve when satori is bundled (Next.js/Turbopack)

1 participant