Skip to content

Conversation

@cernymatej
Copy link
Member

🔗 Linked issue

fix #33553

📚 Description

This fixes several issues with app config merging during HMR. Previously, the implementation would leave gaps in arrays where properties were removed, or fail to correctly replace arrays with objects and vice versa.

@cernymatej cernymatej requested a review from danielroe as a code owner October 23, 2025 20:58
@bolt-new-by-stackblitz
Copy link

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

@coderabbitai
Copy link

coderabbitai bot commented Oct 23, 2025

Walkthrough

This pull request modifies the deep object merging logic in the Nuxt app configuration system. Changes to deepDelete add special handling for arrays by clearing the target array and pushing all elements from the source array instead of iterating keys. Changes to deepAssign introduce stricter type checking: when nested structures have mismatched container types (array vs non-array), the target is reset to a new default value before recursive assignment. A comprehensive test suite is added to validate the _replaceAppConfig function, covering property removal, addition, array updates, type switching, element order preservation, and object reference integrity.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

The review requires careful examination of the logic changes in deepDelete and deepAssign to verify correct array handling and type mismatch resolution. The test suite is comprehensive but requires cross-referencing with the implementation to confirm all scenarios are properly covered. The spread of changes across configuration logic and tests with moderate complexity justifies a moderate review effort.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "fix(nuxt): handle arrays in app config correctly during HMR" is clear, specific, and directly related to the main changes in the changeset. It follows conventional commit format (fix:), accurately summarises the primary change (array handling in app config during hot module replacement), and would provide meaningful context to teammates scanning the project history.
Linked Issues Check ✅ Passed The code changes directly address the objectives from linked issue #33553. The modifications to deepDelete and deepAssign in packages/nuxt/src/app/config.ts implement the required semantics for handling arrays correctly during HMR (clearing arrays properly, handling type mismatches between arrays and objects). The comprehensive test suite added in packages/nuxt/test/app-config.test.ts verifies these fixes work correctly, including tests for array handling, array-to-object replacements, and preservation of references. Together, these changes fulfil the objectives to prevent errors and ensure correct merging semantics for arrays and objects during HMR.
Out of Scope Changes Check ✅ Passed All changes in this pull request are directly within scope of the linked issue #33553. The modifications to config.ts address the core problem of incorrect array merging during HMR, and the test additions in app-config.test.ts directly validate these fixes. No unrelated or tangential changes have been introduced; the changeset is focused and cohesive in addressing the specific app config HMR issues described in the linked issue.
Description Check ✅ Passed The pull request description is clearly related to the changeset, linking to issue #33553 and explaining the specific problems being addressed: gaps in arrays during removal and incorrect array-to-object and object-to-array replacements during HMR. The description provides meaningful context about what issues are being fixed, even though it is concise, and demonstrates understanding of the problem domain.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 23, 2025

Open in StackBlitz

@nuxt/kit

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

nuxt

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

@nuxt/rspack-builder

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

@nuxt/schema

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

@nuxt/vite-builder

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

@nuxt/webpack-builder

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

commit: 6ff8313

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/nuxt/src/app/config.ts (1)

48-52: Type mismatch handling correctly addresses array↔object transitions.

The explicit check for array type mismatches ensures that switching between arrays and objects during HMR works correctly, preventing type errors and ensuring proper replacement semantics.

Consider adding a test case for primitive→non-array object transitions (e.g., changing count: 42 to count: { value: 42 }). Whilst less common in app config, the current logic won't correctly replace a primitive with a non-array object because Line 51's ??= won't overwrite the existing primitive value. If this scenario is relevant, you could add:

 if (isPojoOrArray(val)) {
   const defaultVal = Array.isArray(val) ? [] : {}
-  if (Array.isArray(obj[key]) !== Array.isArray(val)) {
+  if (Array.isArray(obj[key]) !== Array.isArray(val) || !isPojoOrArray(obj[key])) {
     obj[key] = defaultVal
   } else {
     obj[key] ??= defaultVal
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08900f6 and 6ff8313.

📒 Files selected for processing (2)
  • packages/nuxt/src/app/config.ts (2 hunks)
  • packages/nuxt/test/app-config.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Follow standard TypeScript conventions and best practices

Files:

  • packages/nuxt/test/app-config.test.ts
  • packages/nuxt/src/app/config.ts
**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Write unit tests for core functionality using vitest

Files:

  • packages/nuxt/test/app-config.test.ts
🧠 Learnings (1)
📚 Learning: 2025-07-18T16:46:07.446Z
Learnt from: CR
PR: nuxt/nuxt#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-18T16:46:07.446Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Write unit tests for core functionality using `vitest`

Applied to files:

  • packages/nuxt/test/app-config.test.ts
🧬 Code graph analysis (1)
packages/nuxt/test/app-config.test.ts (1)
packages/nuxt/src/app/config.ts (1)
  • _replaceAppConfig (67-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: test-fixtures (windows-latest, built, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, webpack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, rspack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-on, js, lts/-1)
  • GitHub Check: release-pkg-pr-new
  • GitHub Check: typecheck (ubuntu-latest, bundler)
  • GitHub Check: test-size
  • GitHub Check: test-benchmark
  • GitHub Check: code
🔇 Additional comments (4)
packages/nuxt/src/app/config.ts (1)

24-28: LGTM! Array handling prevents gaps during HMR.

The new array-specific logic correctly addresses the issue where removing properties could leave gaps in arrays. By clearing and re-populating the array, you ensure the array remains contiguous and maintains its reference.

Note: Array elements are shallow-copied (spread operator), so nested objects within array elements share references with newObj. This is consistent with the overall replacement semantics of _replaceAppConfig.

packages/nuxt/test/app-config.test.ts (3)

1-23: LGTM! Well-structured test setup.

The test setup correctly mocks useNuxtApp and provides a clean state before each test. The mock structure aligns with the expected AppConfig shape.


25-99: Comprehensive test coverage for the HMR fix.

These test cases thoroughly validate the fix for the reported issues:

  • Property removal without leaving gaps
  • Array updates and element order preservation
  • Array↔object type switching (crucial for the bug fix)

The tests directly address the problems described in issue #33553.


101-123: Reference preservation tests validate efficient merging.

These tests ensure that object references are preserved when content is unchanged, which is important for:

  • Performance (avoiding unnecessary object creation)
  • Reactivity systems (preventing unnecessary re-renders)
  • Maintaining Vue's reactive tracking

The tests correctly verify that both object properties and array elements maintain their references when appropriate.

@codspeed-hq
Copy link

codspeed-hq bot commented Oct 23, 2025

CodSpeed Performance Report

Merging #33555 will not alter performance

Comparing cernymatej:fix/app-config-replacement (6ff8313) with main (08900f6)

Summary

✅ 10 untouched

@danielroe danielroe merged commit 451c817 into nuxt:main Oct 24, 2025
94 of 100 checks passed
@danielroe
Copy link
Member

❤️

@github-actions github-actions bot mentioned this pull request Oct 24, 2025
@cernymatej cernymatej deleted the fix/app-config-replacement branch October 24, 2025 08:16
@github-actions github-actions bot mentioned this pull request Oct 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AppConfig breaks during HMR

2 participants