Skip to content

refactor(nuxt): use rolldown/utils instead of oxc-* dependencies#34983

Merged
danielroe merged 14 commits into
mainfrom
refactor/rolldown
May 11, 2026
Merged

refactor(nuxt): use rolldown/utils instead of oxc-* dependencies#34983
danielroe merged 14 commits into
mainfrom
refactor/rolldown

Conversation

@danielroe

Copy link
Copy Markdown
Member

🔗 Linked issue

📚 Description

we can directly use rolldown re-exports in nuxt v5.

might be worth doing something in oxc-walker to move the parser to an optional peerDep so it doesn't bring in oxc-parser by default.

@danielroe danielroe requested a review from cernymatej May 6, 2026 08:33
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@github-actions github-actions Bot added 5.x ♻️ refactor Code restructuring without behavior change labels May 6, 2026
@socket-security

socket-security Bot commented May 6, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedhappy-dom@​20.9.0751008894100

View full report

@pkg-pr-new

pkg-pr-new Bot commented May 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@34983

@nuxt/nitro-server

npm i https://pkg.pr.new/@nuxt/nitro-server@34983

nuxt

npm i https://pkg.pr.new/nuxt@34983

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@34983

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@34983

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@34983

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@34983

commit: 0129524

@coderabbitai

This comment has been minimized.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/nuxt/src/core/plugins/extract-async-data-handlers.ts (1)

64-64: ⚡ Quick win

Type guard is over-broad — prefer ESTree.FunctionExpression | ESTree.ArrowFunctionExpression.

In @types/estree, Function is defined as the union FunctionDeclaration | FunctionExpression | ArrowFunctionExpression, so ESTree.Function | ESTree.ArrowFunctionExpression collapses to ESTree.Function, meaning the narrowed type includes FunctionDeclaration even though the runtime check ('ArrowFunctionExpression' || 'FunctionExpression') can never match it. Although line 66 re-checks the type and prevents runtime issues, the TypeScript type at line 64 is misleading.

🛠️ Proposed fix
-            const fetcherFunction = callExpression.arguments.find((fn): fn is ESTree.Function | ESTree.ArrowFunctionExpression => fn.type === 'ArrowFunctionExpression' || fn.type === 'FunctionExpression')
+            const fetcherFunction = callExpression.arguments.find((fn): fn is ESTree.FunctionExpression | ESTree.ArrowFunctionExpression => fn.type === 'ArrowFunctionExpression' || fn.type === 'FunctionExpression')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/core/plugins/extract-async-data-handlers.ts` at line 64,
The type guard used when finding the fetcher function is too broad because it
returns ESTree.Function which includes FunctionDeclaration; update the predicate
to narrow to ESTree.FunctionExpression | ESTree.ArrowFunctionExpression so the
found value's static type matches the runtime check. Concretely, change the type
predicate on callExpression.arguments.find (the arrow that assigns
fetcherFunction) to use "fn is ESTree.FunctionExpression |
ESTree.ArrowFunctionExpression" and keep the existing runtime type checks that
compare fn.type to 'ArrowFunctionExpression' or 'FunctionExpression'.
packages/nuxt/src/pages/utils.ts (1)

257-262: 💤 Low value

Unsafe access to internal error property via any cast.

The codeframe property is not part of the official TransformResult API surface in rolldown v1.0.0-rc.16 (errors are typed as plain Error[]). Casting to any to access this internal property is fragile—if rolldown's internal structure changes, this will silently return undefined. Use optional chaining with a fallback, or narrow the error type with a small interface to make the assumption explicit and catch breakage at compile time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/pages/utils.ts` around lines 257 - 262, The logger
currently unsafely accesses an internal `codeframe` via an any cast on
`transformed.errors` and `error` in the block that logs transformation issues
for `fnName`; replace the cast with a safe access pattern — either narrow the
error type by creating a small interface (e.g., interface { codeframe?: string
}) and type-guard the error before using `codeframe`, or use optional chaining
with a fallback message when logging (access `error?.codeframe ?? '<no
codeframe>'`) so the `logger.warn` call for `transformed.errors` is safe and
typesafe.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/nuxt/src/core/plugins/extract-async-data-handlers.ts`:
- Line 64: The type guard used when finding the fetcher function is too broad
because it returns ESTree.Function which includes FunctionDeclaration; update
the predicate to narrow to ESTree.FunctionExpression |
ESTree.ArrowFunctionExpression so the found value's static type matches the
runtime check. Concretely, change the type predicate on
callExpression.arguments.find (the arrow that assigns fetcherFunction) to use
"fn is ESTree.FunctionExpression | ESTree.ArrowFunctionExpression" and keep the
existing runtime type checks that compare fn.type to 'ArrowFunctionExpression'
or 'FunctionExpression'.

In `@packages/nuxt/src/pages/utils.ts`:
- Around line 257-262: The logger currently unsafely accesses an internal
`codeframe` via an any cast on `transformed.errors` and `error` in the block
that logs transformation issues for `fnName`; replace the cast with a safe
access pattern — either narrow the error type by creating a small interface
(e.g., interface { codeframe?: string }) and type-guard the error before using
`codeframe`, or use optional chaining with a fallback message when logging
(access `error?.codeframe ?? '<no codeframe>'`) so the `logger.warn` call for
`transformed.errors` is safe and typesafe.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 53cf8fd4-e670-4251-81eb-949d8456755d

📥 Commits

Reviewing files that changed from the base of the PR and between 8da842d and 98c6cd6.

⛔ Files ignored due to path filters (2)
  • packages/nuxt/package.json is excluded by !**/package.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (13)
  • packages/nuxt/src/compiler/plugins/keyed-function-factories.ts
  • packages/nuxt/src/compiler/plugins/keyed-functions.ts
  • packages/nuxt/src/compiler/types.ts
  • packages/nuxt/src/compiler/utils.ts
  • packages/nuxt/src/components/plugins/lazy-hydration-macro-transform.ts
  • packages/nuxt/src/components/plugins/tree-shake.ts
  • packages/nuxt/src/core/plugins/extract-async-data-handlers.ts
  • packages/nuxt/src/core/plugins/plugin-metadata.ts
  • packages/nuxt/src/core/utils/parse-utils.ts
  • packages/nuxt/src/core/utils/parse.ts
  • packages/nuxt/src/pages/plugins/page-meta.ts
  • packages/nuxt/src/pages/utils.ts
  • packages/nuxt/test/compiler.test.ts

@cernymatej cernymatej left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

moving oxc-parser to peer deps in oxc-walker sounds good

out of curiosity, what was the reasoning for moving the parse utils to rolldown? does the underlying rust parser differ from the one in oxc-parser, or is it only for convenience?

Comment thread packages/nuxt/src/pages/utils.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nuxt/src/core/utils/parse.ts`:
- Line 7: The call creating transformResult uses transformSync('', input, {
tsconfig: false, ...oxcOptions?.transform.options, ...options }) which allows
oxcOptions?.transform.options or options to override tsconfig:false; change the
object merge so tsconfig: false is applied after the spreads (e.g.
{...oxcOptions?.transform.options, ...options, tsconfig: false}) or otherwise
ensure tsconfig:false is the last property so transformSync always receives
tsconfig disabled; update the call site where transformResult is created and
keep the symbol names transformSync, transformResult,
oxcOptions?.transform.options and options in mind.

In `@packages/nuxt/src/pages/utils.ts`:
- Line 287: The current search in pageExtractArgument.properties only matches
keys where property.key.type === 'Identifier', skipping quoted string keys like
'path'; update the predicate used in the find so it also accepts
property.key.type === 'Literal' (or 'StringLiteral' depending on ESTree variant)
and normalize both forms to the same identifier name (e.g., extract the string
value from Literal or the name from Identifier) before comparing to key; apply
the same change to the equivalent check in the later block (the code around the
other find at lines 305-314) so quoted definePageMeta keys are treated the same
as identifier keys and not marked dynamic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4352c006-4dec-406d-9257-39246687d0df

📥 Commits

Reviewing files that changed from the base of the PR and between 98c6cd6 and bc3c2e0.

⛔ Files ignored due to path filters (3)
  • packages/nuxt/package.json is excluded by !**/package.json
  • packages/vite/package.json is excluded by !**/package.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (2)
  • packages/nuxt/src/core/utils/parse.ts
  • packages/nuxt/src/pages/utils.ts

export function transformAndMinify (input: string, options?: TransformOptions): TransformResult | MinifyResult {
const oxcOptions = tryUseNuxt()?.options.oxc
const transformResult = transformSync('', input, { ...oxcOptions?.transform.options, ...options })
const transformResult = transformSync('', input, { tsconfig: false, ...oxcOptions?.transform.options, ...options })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep tsconfig: false after the spreads.

Line 7 still lets oxcOptions?.transform.options or options overwrite the explicit tsconfig: false, so this PR’s behavioural fix is bypassed as soon as either source carries a tsconfig value.

Proposed fix
-  const transformResult = transformSync('', input, { tsconfig: false, ...oxcOptions?.transform.options, ...options })
+  const transformResult = transformSync('', input, { ...oxcOptions?.transform.options, ...options, tsconfig: false })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const transformResult = transformSync('', input, { tsconfig: false, ...oxcOptions?.transform.options, ...options })
const transformResult = transformSync('', input, { ...oxcOptions?.transform.options, ...options, tsconfig: false })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/core/utils/parse.ts` at line 7, The call creating
transformResult uses transformSync('', input, { tsconfig: false,
...oxcOptions?.transform.options, ...options }) which allows
oxcOptions?.transform.options or options to override tsconfig:false; change the
object merge so tsconfig: false is applied after the spreads (e.g.
{...oxcOptions?.transform.options, ...options, tsconfig: false}) or otherwise
ensure tsconfig:false is the last property so transformSync always receives
tsconfig disabled; update the call site where transformResult is created and
keep the symbol names transformSync, transformResult,
oxcOptions?.transform.options and options in mind.

if (fnName === 'definePageMeta') {
for (const key of extractionKeys) {
const property = pageExtractArgument.properties.find((property): property is ObjectProperty => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key)
const property = pageExtractArgument.properties.find((property): property is ESTree.ObjectProperty => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Normalise quoted definePageMeta keys as well.

This only extracts Identifier keys, so valid forms like definePageMeta({ 'path': '/foo' }) are skipped. The follow-up scan then reads property.value instead of the literal key, which marks quoted known keys as dynamic meta instead of extracting them.

Proposed fix
+        const getPropertyName = (property: ESTree.ObjectProperty) => {
+          if (property.key.type === 'Identifier') {
+            return property.key.name
+          }
+          if (property.key.type === 'Literal' && typeof property.key.value === 'string') {
+            return property.key.value
+          }
+        }
+
         for (const key of extractionKeys) {
-          const property = pageExtractArgument.properties.find((property): property is ESTree.ObjectProperty => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key)
+          const property = pageExtractArgument.properties.find((property): property is ESTree.ObjectProperty =>
+            property.type === 'Property' && getPropertyName(property) === key,
+          )
           if (!property) { continue }
-          const name = property.key.type === 'Identifier' ? property.key.name : String(property.value)
+          const name = getPropertyName(property)
+          if (!name) {
+            continue
+          }
           if (!extractionKeys.has(name as keyof NuxtPage)) {
             dynamicProperties.add('meta')
             break
           }

Also applies to: 305-314

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nuxt/src/pages/utils.ts` at line 287, The current search in
pageExtractArgument.properties only matches keys where property.key.type ===
'Identifier', skipping quoted string keys like 'path'; update the predicate used
in the find so it also accepts property.key.type === 'Literal' (or
'StringLiteral' depending on ESTree variant) and normalize both forms to the
same identifier name (e.g., extract the string value from Literal or the name
from Identifier) before comparing to key; apply the same change to the
equivalent check in the later block (the code around the other find at lines
305-314) so quoted definePageMeta keys are treated the same as identifier keys
and not marked dynamic.

@codspeed-hq

codspeed-hq Bot commented May 6, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 20 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing refactor/rolldown (0129524) with main (5015a6c)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@danielroe

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: danielroe <28706372+danielroe@users.noreply.github.com>

Copilot AI commented May 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merge conflicts have been resolved in fa6fe49. The packages/nuxt/package.json conflict was resolved by keeping the removal of oxc-minify, oxc-parser, and oxc-transform (replaced by rolldown/utils) and taking the @vue/compiler-sfc version bump from main. The pnpm-lock.yaml was regenerated via pnpm install.

@danielroe danielroe merged commit c32b704 into main May 11, 2026
46 of 48 checks passed
@danielroe danielroe deleted the refactor/rolldown branch May 11, 2026 11:13
@github-actions github-actions Bot mentioned this pull request May 11, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

5.x ♻️ refactor Code restructuring without behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants