Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
/nuxtPublic

fix(nuxt): invalidate module cache on composable export type changes#33671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
Flo0806 wants to merge1 commit intonuxt:main
base:main
Choose a base branch
Loading
fromFlo0806:fix/composable-export-type-change-hmr

Conversation

@Flo0806
Copy link
Collaborator

🔗 Linked issue

Fixes:#33468

Description

When changing a composable's export type during development (e.g., switching between export default and export function), the dev server crashes with(0, __vite_ssr_import_2__.default) is not a function.

This happens becauseVite's HMR doesn't invalidate the module cache when export types change. The old import statement tries to use the new export type, causing a runtime error.

Solution

Added a Vite plugin in the imports module that:

  1. Detects export type changes - Compares old and new exports incomposables usingscanDirExports
  2. Recursively invalidates module cache - Clears the module and all its importers in bothclient andSSR Vite servers
  3. Triggers full reload - Forces a full page reload instead of attempting HMR (which would fail)

The plugin runs in thehandleHotUpdate hook before Vite's HMR logic executes, ensuring proper cache invalidation. For normal code changes without export type modifications, HMR continues to work as usual.

Works with both Vite's newEnvironment API andlegacy mode by tracking all Vite server instances via thevite:serverCreated hook.

Testing

Tested by switching between:
export default function() { return 'default' }
and
export function useName() { return 'named' }

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz CodeflowRun & review this pull request inStackBlitz Codeflow.

@pkg-pr-new
Copy link

Open in StackBlitz

@nuxt/kit

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

nuxt

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

@nuxt/rspack-builder

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

@nuxt/schema

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

@nuxt/vite-builder

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

@nuxt/webpack-builder

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

commit:549663a

@coderabbitai
Copy link

Walkthrough

This change introduces HMR handling for composables directory files in Nuxt. The implementation tracks Vite servers (client and SSR) and registers a new Vite plugin (nuxt:composables-hmr) that detects when an export type changes (default versus named export) within updated composables files. When an export type change is detected, the plugin recursively invalidates affected modules across all tracked Vite servers and triggers a full page reload. If no export type change occurs, the standard HMR flow continues.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

  • The Vite server tracking mechanism and vite:serverCreated hook registration require verification of correct lifecycle management
  • The export type comparison logic needs careful review to ensure accurate detection of default versus named export changes
  • Module invalidation across client and SSR contexts must be validated to prevent inconsistent behaviour
  • The page reload triggering logic should be examined for any potential race conditions or unintended side effects
  • Integration with the existing HMR pipeline and overall module configuration flow requires thorough understanding

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title accurately summarises the main change: fixing module cache invalidation when composable export types change during development.
Description check✅ PassedThe description is well-detailed and directly relates to the changeset, explaining the problem, solution, and implementation approach.
Linked Issues check✅ PassedThe PR successfully addresses issue#33468 by implementing export type change detection and module cache invalidation to prevent dev server crashes.
Out of Scope Changes check✅ PassedAll changes in the imports module are directly scoped to fixing the composable export type change issue; no extraneous modifications detected.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for usingCodeRabbit! 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.

Copy link

@coderabbitaicoderabbitaibot 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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between8539fe4 and549663a.

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

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

Follow standard TypeScript conventions and best practices

Files:

  • packages/nuxt/src/imports/module.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CRRepo: nuxt/nuxt PR: 0File: .github/copilot-instructions.md:0-0Timestamp: 2025-07-18T16:46:07.446ZLearning: Applies to **/*.vue : Use `<script setup lang="ts">` and the composition API when creating Vue components
Learnt from: huang-julienRepo: nuxt/nuxt PR: 29366File: packages/nuxt/src/app/components/nuxt-root.vue:16-19Timestamp: 2024-12-12T12:36:34.871ZLearning: In `packages/nuxt/src/app/components/nuxt-root.vue`, when optimizing bundle size by conditionally importing components based on route metadata, prefer using inline conditional imports like:```jsconst IsolatedPage = route?.meta?.isolate ? defineAsyncComponent(() => import('#build/isolated-page.mjs')) : null```instead of wrapping the import in a computed property or importing the component unconditionally.
📚 Learning: 2024-11-05T15:22:54.759Z
Learnt from: GalacticHypernovaRepo: nuxt/nuxt PR: 26468File: packages/nuxt/src/components/plugins/loader.ts:24-24Timestamp: 2024-11-05T15:22:54.759ZLearning: In `packages/nuxt/src/components/plugins/loader.ts`, the references to `resolve` and `distDir` are legacy code from before Nuxt used the new unplugin VFS and will be removed.

Applied to files:

  • packages/nuxt/src/imports/module.ts
🧬 Code graph analysis (1)
packages/nuxt/src/imports/module.ts (1)
packages/kit/src/ignore.ts (1)
  • isIgnored (14-34)
⏰ 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). (1)
  • GitHub Check: code

Comment on lines +119 to +128
// Check if export type changed (default ↔ named)
letexportTypeChanged=false
for(constnewImportofnewImports){
constoldImport=oldImports.find(i=>(i.as||i.name)===(newImport.as||newImport.name))
if(oldImport&&oldImport.name!==newImport.name){
exportTypeChanged=true
break
}
}

Choose a reason for hiding this comment

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

⚠️ Potential issue |🟠 Major

Detection misses default↔named switches when the alias changes

Line 120: if the export flips betweendefault and named while you also rename the symbol (e.g.export default function useKey()export function useKeyRenamed()),oldImport is never found soexportTypeChanged staysfalse. The module cache is left untouched and the original(…).default is not a function crash still reproduces. Please deriveexportTypeChanged from the presence of aname === 'default' entry before versus after (and only fall back to the alias comparison when that check is inconclusive) so we catch these alias-renaming cases as well. Otherwise the fix remains incomplete.

@codspeed-hq
Copy link

CodSpeed Performance Report

Merging#33671 willnot alter performance

ComparingFlo0806:fix/composable-export-type-change-hmr (549663a) withmain (8539fe4)

Summary

✅ 10 untouched


// Vite plugin to detect and handle export type changes BEFORE HMR
nuxt.hook('vite:configResolved',(viteConfig)=>{
if(!viteConfig.plugins){return}
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldnt we initialise the list here and push the plugin in anyway?

Copy link
CollaboratorAuthor

Choose a reason for hiding this comment

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

viteConfig.plugins? I guess no. Because it isreadonly and thevite:configResolved hook is called after Vite's config resolution, which always includes a plugins array. The early return is defensive programming - ifplugins doesn't exist, something is fundamentally wrong with the Vite setup and we shouldn't proceed.

@danielroe
Copy link
Member

danielroe commentedNov 7, 2025
edited
Loading

this may also be an approach which also works for some linked issues:

Flo0806 reacted with eyes emoji

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

Reviewers

@coderabbitaicoderabbitai[bot]coderabbitai[bot] left review comments

@danielroedanielroeAwaiting requested review from danielroedanielroe is a code owner

+1 more reviewer

@HigherOrderLogicHigherOrderLogicHigherOrderLogic left review comments

Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Changing exports in files tracked by unimport crashes dev server in certain cases

3 participants

@Flo0806@danielroe@HigherOrderLogic

[8]ページ先頭

©2009-2025 Movatter.jp