fix(ContentRenderer): keep async component identity stable across re-resolves - #3835
fix(ContentRenderer): keep async component identity stable across re-resolves#3835hendrikheil wants to merge 1 commit into
Conversation
|
@hendrikheil is attempting to deploy a commit to the Nuxt Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 6 remain after this review. 📝 WalkthroughWalkthrough
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized fix keeps async content component identity stable, preventing unnecessary remounts and preview flashes; no actionable merge-blocking risk remains. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
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. Comment |
commit: |
…resolves defineAsyncComponent returns a new component type on every call, and componentsMap re-resolves whenever the rendered document changes. Vue sees a different type at the same vnode position and remounts the subtree instead of patching it. Cache the wrappers so repeated resolutions return the same instance. Ref nuxt-content/nuxt-studio#383
274d426 to
a981e06
Compare
|
Hi @hendrikheil with that change, edits in Nuxt Studio don't seem to update the live preview at all anymore? No flicker and no scroll-issues anymore as described in nuxt-content/nuxt-studio#383 but now no changes are visible in the front-end, updates are written to the file but a page reload doesn't even help to make them visible - does it work in your project? I can also share a reproduction video again if that's helpful |
🔗 Linked issue
Ref nuxt-content/nuxt-studio#383
❓ Type of change
📚 Description
defineAsyncComponentreturns a new component type on every call.resolveVueComponentcalls it in two places, and it is reached fromcomponentsMap, acomputedthat re-resolves wheneverprops.valuechanges identity:So every re-resolve hands
MDCRenderera fresh component type for each local component. Vue sees a different type at the same vnode position, so it cannot patch — it unmounts and remounts, and the async wrapper renders nothing for a tick while it re-resolves.This is what makes Studio's live preview flash the entire article on every keystroke: Studio calls
app:data:refresh,useAsyncDatahands back a new document object, and the whole rendered tree is destroyed and recreated. Because the DOM is torn down, page height momentarily collapses and the scroll position is lost too — that's the "jumps back to the top" half of nuxt-content/nuxt-studio#383.Projects that mark their content components
globaldon't hit this, becauseresolveComponentreturns a stable definition. Local components are a supported (and bundle-size-motivated) configuration, so they should behave the same.The fix caches both wrappers — a
Mapkeyed by pascal name for the loader branch, aWeakMapkeyed by the component object for thesetupbranch — so repeated resolutions return the same instance and Vue patches the tree.I also hoisted the repeated
pascalCase(component)into a local, since it's now used three times.📝 Checklist