Skip to content

chore(deps)!: update @puppeteer/browsers to 3.x - #239

Closed
JacktheRanger wants to merge 1 commit into
cloudflare:mainfrom
JacktheRanger:feat/puppeteer-browsers-v3
Closed

JacktheRanger wants to merge 1 commit into
cloudflare:mainfrom
JacktheRanger:feat/puppeteer-browsers-v3

Conversation

@JacktheRanger

Copy link
Copy Markdown

What kind of change does this PR introduce?

Dependency update. It is a breaking change because it raises the minimum Node.js version.

Did you add tests for your changes?

One existing launcher spec now also covers user.js (userDataDir option restores preferences). That spec change comes with the upstream fix ported below. The existing unit and launcher suites cover the rest of the launcher paths.

If relevant, did you update the documentation?

No. The README does not state a Node.js version, and engines carries the new requirement. See "Not included" for docs/.

Summary

Closes #238. This implements direction 1 from that issue.

Motivation

@cloudflare/puppeteer pins @puppeteer/browsers to 2.2.4. Its transitive tree brings advisories into every downstream project:

  • extract-zip: no patched release exists.
  • basic-ftp: reached via proxy-agent → pac-proxy-agent → get-uri. The fix is in 6.2.1, but get-uri still requires ^5.
  • ip-address: reached via socks.

Because the version is pinned exactly, downstream projects can only dismiss these alerts or add an overrides entry. @puppeteer/browsers 3.x removes extract-zip and makes proxy-agent an optional peer dependency, so the whole tree goes away.

Only the Node launcher (src/node/*) imports @puppeteer/browsers. The Workers entry point never loads it, so Workers bundles do not change.

Changes

  • packages/puppeteer-core/package.json
    • @puppeteer/browsers: 2.2.4 → ^3.2.3. I used a caret range because the exact pin is the reason downstream lockfiles could not pick up fixes. Upstream puppeteer-core pins exactly because it releases in lockstep with @puppeteer/browsers; this package does not.
    • engines.node: >=18 → >=22.12.0. This matches @puppeteer/browsers 3.x and upstream puppeteer-core 25. The CJS build calls require() on the ESM-only package, which relies on require(esm).
    • wireit build:tsc no longer depends on ../browsers:build. puppeteer-core now resolves the npm package instead of the in-repo workspace. packages/puppeteer and test/installation still declare that dependency themselves.
    • The unit script now uses "lib/cjs/**/*.test.js", the same form upstream puppeteer-core 24.x uses. On Node 22 and later, node --test fails when given a directory argument.
  • src/node/FirefoxLauncher.ts and test/src/launcher.spec.ts: port upstream puppeteer/puppeteer@9feda9c (fix(firefox): back up user.js as well puppeteer/puppeteer#12943). Since @puppeteer/browsers 2.3.1, createProfile backs up an existing user.js to user.js.puppeteer. The 22.13.1 cleanup deleted user.js and never restored that backup. The port is verbatim so later upstream merges apply cleanly.
  • .nvmrc (v20 → v22) and cf_test_smoke.yml / cf_test_full.yml (20.x → 22.x): CI should run on a supported Node.js version. publish.yml already uses Node 22.
  • Lockfiles
    • Root: adds @puppeteer/browsers@3.2.3 and its dependencies under packages/puppeteer-core/node_modules (install-strategy=nested). No existing package changes version. npm also corrected the stale version recorded for the workspace (1.2.0 → 1.4.1).
    • packages/puppeteer-cloudflare/tests/package-lock.json: only the metadata of the linked package changes.
    • The root lockfile now also contains proxy-agent@8 entries marked peer optional. npm adds them only because the in-repo 2.2.4 workspace hoists proxy-agent@6, which fails the optional peer range. A fresh downstream install does not include them (see Validation).

Not included

  • No version bump. This needs a major release, and version bumps here land as separate commits.
  • The in-repo packages/browsers (2.2.4) and packages/puppeteer stay on 2.x. Neither is published, and upgrading them means re-vendoring the 3.x source. As a result, this repo's own lockfile still contains the 2.x tree. Downstream installs do not.
  • docs/guides/system-requirements.md still says "Node 18+". docs/ is upstream Puppeteer's documentation tree, and the README links to pptr.dev.
  • Other upstream launcher changes that shipped alongside @puppeteer/browsers releases (AbortSignal support in launch, channel in connect, the getRecentLogs()-based error message, executablePath(LaunchOptions)) are features. They are not needed for compatibility.
  • The [Required] Puppeteer Unit tests CI job is unchanged. It runs npm run unit -w puppeteer-core. That name has matched no workspace since the rename to @cloudflare/puppeteer, so the step exits 0 without running anything.

Known costs

  • Node.js < 22.12 is no longer supported for the Node launcher. The Workers entry point and its bundle are unaffected, and current wrangler already requires Node ≥ 22.
  • Node 22.12.0 only: a CJS require() from outside node_modules (for example this repo's unit tests) prints an ExperimentalWarning. Consumers do not see it, because their require() comes from inside node_modules.
  • Firefox with an existing userDataDir that had no user.js: after close, the generated user.js now stays in the profile. Before, it was deleted. This is upstream's behavior since 9feda9c.
  • Linux arm64: 3.x reports the platform as linux_arm, so trimCache() no longer removes browsers cached under linux-* by 2.x.
  • With the caret range, future 3.x minor releases reach downstream projects without a release of this package.

Validation

Measured on 2026-10-02 on macOS arm64. Install and gates used Node 22.23.3 with npm 10.9.9. Runtime checks also ran on Node 22.12.0, 24.21.0 and 26.4.0.

  • Fresh clone with this diff applied: npm ci, npm run check, npm run validate-licenses, npm run build, npm run test-types, npm run lint and npm run unit all exit 0, with 89/89 unit tests passing. The worktree is clean after npm ci.
  • Unit tests: 89/89 on Node 22.12.0 and 26.4.0. For comparison, main fails both launcher test files on Node 26, because Node 26 loads yargs 17's extensionless yargs/yargs entry as ESM.
  • Mocha chrome-headless suite: Chrome 126.0.6478.182 was installed through packages/puppeteer's postinstall, which uses the in-repo 2.2.4. That means 3.x had to resolve a cache that 2.x wrote.
    • Result: 1049 passing, 10 pending, 22 failing. main fails the same 22 tests in the same environment (HiDPI screenshot and mouse sizes, and a local proxy and DNS on this machine).
    • The full suite ran before the 9feda9c port. After the port I re-ran the Launcher specs: 48 passing, 2 pending, matching expectations.
  • Downstream install: I packed this branch and installed the tarball into an empty project on Node 22.12.0.
    • The project has 22 packages, and npm audit reports 0 vulnerabilities. None of extract-zip, basic-ftp, get-uri, proxy-agent, socks or ip-address is installed.
    • The default entry loads through both ESM and CJS.
    • @cloudflare/puppeteer/internal/puppeteer-core.js launches Chrome through both ESM and CJS on Node 22.12.0, 22.23.3, 24.21.0 and 26.4.0.
  • Worker bundle: I bundled a Worker that calls puppeteer.launch(env.BROWSER) and puppeteer.limits() with wrangler deploy --dry-run. Tarballs built from main and from this branch produce byte-identical index.js (same md5). Neither the bundle nor its source map contains @puppeteer/browsers, yargs or modern-tar.
  • packages/puppeteer-cloudflare/tests: npm ci succeeds.

Does this PR introduce a breaking change?

Yes. @cloudflare/puppeteer now requires Node.js ≥ 22.12.0. Code running in Workers is unaffected. Projects that use the Node launcher (internal/puppeteer-core.js or internal/node/*) on Node < 22.12 must upgrade Node.

Other information

Draft #237 replaces this layout, and the @cloudflare/puppeteer it builds no longer depends on @puppeteer/browsers at all. If #237 lands first, this PR is superseded. It is meant for a release cut from the current layout before then.

🤖 Generated with Claude Code

@cloudflare/puppeteer pinned @puppeteer/browsers 2.2.4, whose transitive
tree (extract-zip, proxy-agent -> get-uri -> basic-ftp, socks ->
ip-address) carries advisories that cannot be fixed on the 2.x line.
3.x drops those dependencies. Only the Node launcher imports the package,
so Workers bundles are unchanged.

3.x is ESM-only and needs Node >= 22.12, so engines, .nvmrc and the
Cloudflare test workflows move to Node 22, and the unit script switches
to the glob form that Node 22's test runner needs. FirefoxLauncher ports
upstream 9feda9c so cleanup restores the user.js backup that 3.x's
createProfile writes.

Refs #238

BREAKING CHANGE: @cloudflare/puppeteer now requires Node.js >= 22.12.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@JacktheRanger

Copy link
Copy Markdown
Author

Closing as superseded by #237. The new layout drops the vendored packages/puppeteer-core, and @cloudflare/puppeteer@1.5.0-rc.0 no longer depends on @puppeteer/browsers at all.

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.

Pinned @puppeteer/browsers@2.2.4 pulls in unpatched transitive deps (extract-zip, basic-ftp) that Workers never load

1 participant