Skip to content

Next 16 support#185

Merged
dividedmind merged 9 commits intomainfrom
feat/next16
Feb 26, 2026
Merged

Next 16 support#185
dividedmind merged 9 commits intomainfrom
feat/next16

Conversation

@dividedmind
Copy link
Collaborator

The biggest change in this pull request is Next 16 support. Note while both turbopack and webpack are supported, with turbopack instrumentation can be incomplete because we're only handed raw typescript in this case. A message advising the user to use webpack is shown in this case.

While working on this I also noticed a small race in ESM support for http capture, which I fixed. There's also a bunch of tooling improvements and version bumps here, the biggest of which is moving away from zero-installs (they really turned out to be more trouble than it's worth in this project).

I recommend reviewing commit-by-commit.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates project tooling and CI to support the broader Next 16 work, including faster installs via Yarn caching and a migration away from the existing ESLint config file.

Changes:

  • Enabled Yarn dependency caching in GitHub Actions via actions/setup-node@v4.
  • Removed the legacy .eslintrc.cjs ESLint configuration (likely part of a lint config migration).

Reviewed changes

Copilot reviewed 2 out of 1088 changed files in this pull request and generated 1 comment.

File Description
.github/workflows/ci.yml Adds Yarn cache configuration to speed up CI jobs.
.eslintrc.cjs Removes the legacy ESLint config file (implies config migration elsewhere).
Comments suppressed due to low confidence (1)

.eslintrc.cjs:1

  • The legacy ESLint config file is removed in this change. If this PR is migrating to ESLint flat config, ensure there is a replacement eslint.config.* (or another supported config source) and that the yarn lint script is compatible; otherwise ESLint will run without configuration and CI linting will fail.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

dividedmind and others added 9 commits February 26, 2026 16:38
Zero-installs with nodeLinker=pnpm gives few of the intended benefits
(yarn install still needs to run to extract packages) while committing
252 MB of dependency zips — including cross-platform native binaries for
@next-swc, @swc/core, and esbuild — to the repository. This bloats every
clone and grows with each dependency update.

Switch to enableGlobalCache=true so packages are stored in the user's
global yarn cache instead. CI uses explicit cache support.
In Node.js 22, the ESM loader runs in a separate thread. When an ESM
module imports `http`, the loader thread called `forceRequire()` which
patched http in the loader thread's cache and sent a BroadcastChannel
message to patch the main thread's cache. But the main thread evaluates
the ESM module body synchronously and can call into http (e.g.
`new http.ClientRequest()`) before the event loop ever processes the
BroadcastChannel message, leaving ClientRequest unpatched and http
events unrecorded.

Fix by pre-patching `node:http` and `node:https` in `register.ts`,
which runs in the main thread via `--require` before any user ESM
modules are loaded. Since the main thread's cache is now already
populated, the http/https entries are also removed from the
`forceRequire` list in `loader.ts`.
Update ts-node, @swc/core, and @types/node to versions compatible with
TypeScript 5.9. Fix code issues surfaced by stricter TS 5.9 type
checking (unnecessary assertion, unbound-method), and add skipLibCheck
to the typescript-esm test tsconfig to handle undici-types resolution
under yarn's pnpm linker.
Extend astring with a jsxGenerator that handles all JSX node types
(JSXElement, JSXFragment, JSXAttribute, JSXSpreadAttribute, etc.) so
that parse→transform→generate round-trips work on .jsx and .tsx files.

Teach acorn-walk to traverse JSX nodes by calling extend(walkBase) from
acorn-jsx-walk at instrument.ts module load time. Without this, walking
a JSX AST throws "baseVisitor[type] is not a function".

Wire both changes into the pipeline:
- transform.ts: enable jsx:true for .jsx/.tsx and pass jsxGenerator to generate()
- webpack.ts: attempt TypeScript stripping on .tsx too; stripTypeScriptTypes
  rejects JSX syntax and falls back to the original source, which meriyah
  then parses natively with jsx:true

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React elements contain deep recursive properties and user-specific backtraces
(like `_owner` stack frames) that can create excessively large AppMap files
and break CI due to snapshot instability.

This adds a check using the `$$typeof` symbol to detect React elements
during serialization. They are now compactly formatted as
`[React element <Type>]` in the string representation, and we prevent
`parameterSchema` from deeply inspecting their child properties.
Inject our webpack loader into both the webpack and Turbopack pipelines
via Next.js's loadConfig hook:

- Webpack path (--webpack or older Next.js): prepend a loader rule for
  all JS/TS/JSX/TSX extensions, guarded against double-injection when
  Next.js 16 calls the webpack callback more than once with a shared
  rules array.

- Turbopack path (Next.js 16+ default): populate result.turbopack.rules
  for each extension with condition:"node" so the loader runs on the
  server-side Node.js runtime. Merges safely with any existing rules.

Turbopack passes raw TypeScript source to webpack loaders (unlike
webpack which runs SWC first), so the loader strips type annotations
before handing off to meriyah. This relies on the JSX support added
in the previous commit for .tsx files.

Also limit object property serialization depth to 5 levels to avoid
runaway serialization of deeply nested Next.js response objects.

Emit a one-time warning when Turbopack is the active bundler (i.e. --webpack /
--no-turbopack not set) noting that the support is experimental and that files
containing TypeScript-only constructs (enum, namespace, constructor parameter
properties) cannot be parsed and will not be instrumented.

Set APPMAP_TURBOPACK_WARNED in the environment when warning so that
forked worker processes (which inherit the parent env) skip the warning.
Also deduplicates within a single process if loadConfig is called more
than once.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This ensures the tests don't interfere with each other and whatever
else might be running on the machine.
@dividedmind dividedmind merged commit b890f9a into main Feb 26, 2026
6 checks passed
@dividedmind dividedmind deleted the feat/next16 branch February 26, 2026 15:41
@appmap-releasebot
Copy link

🎉 This PR is included in version 2.25.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@appmap-releasebot
Copy link

🎉 This PR is included in version 2.25.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

1 similar comment
@appmap-releasebot
Copy link

🎉 This PR is included in version 2.25.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants