fix: resolve dev server deadlock when starting embedded Storybook#1069
fix: resolve dev server deadlock when starting embedded Storybook#1069srcdev wants to merge 3 commits into
Conversation
The module awaited setupStorybook() inside Nuxt's listen hook, while @storybook-vue/nuxt's loadNuxtViteConfig() waited for the running Nuxt instance's vite:configResolved event - which cannot fire until the boot pipeline, blocked by that same listen hook, proceeds. Every `nuxt dev` with the module enabled hung on all requests. - module: capture the client Vite config during setup (before the event can fire) and share it with the framework via a well-known symbol - module: start Storybook from the listen hook without awaiting it - addon: consume the captured config instead of registering a late hook - start Storybook with ci: true so a busy port cannot block on an interactive prompt - e2e: cover the embedded (`nuxt dev`) path, previously untested Refs nuxt-modules#993 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
👷 Deploy request for nuxt-storybook pending review.Visit the deploys page to approve it
|
The playground now loads @nuxtjs/storybook from the built package, so `nuxt prepare` during install needs at least a stub dist to exist.
commit: |
vite's mergeConfig reuses nested objects by reference when a key exists on only one side of the merge. In embedded mode the merge input is the running app's resolved config, so writing noDiscovery and pushing include entries poisoned the app's own dep optimizer. Clone the objects this function writes to. Verified against the nuxt-modules#993 reproduction with an instrumented module: optimizeDeps.noDiscovery no longer flips on the live config after Storybook starts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Update: pushed two follow-up commits — a CI fix (the playground now loads the module from the built package, so the root Full transparency on scope: during that verification I also found a deeper, pre-existing issue in how embedded mode shares the app's live Vite plugin instances with Storybook's server — filed as #1072 with full forensics. It affects plugin-heavy apps once this PR makes embedded mode bootable. This PR remains a strict improvement (embedded mode is 100% deadlocked without it), and the new issue documents the remaining work. (investigated with Claude Fable 5 assistance) |
🔗 Linked issue
Refs #993 — fixes the dev-server deadlock that bricks the Nuxt app. (Deliberately not "Resolves": the residual
/_nuxtEAGAIN proxy-target errors from that issue surface once the deadlock is gone; a follow-up PR adapting #994'sdevServer.urlfix will address those.)📚 Description
As offered in #993 (comment), this fixes the startup deadlock introduced in #981:
@nuxtjs/storybookstarts Storybook inside Nuxt'slistenhook andawaits it, blocking the boot pipeline (Vite middleware never attaches).@storybook-vue/nuxt'sloadNuxtViteConfigdetects the already-running Nuxt viatryUseNuxt()and waits for itsvite:configResolvedevent — which can only fire once boot proceeds.Circular wait. With current nuxt/cli every
nuxt devwith the module enabled hangs on all requests forever; on older versions it surfaced as theEAGAINproxy errors reported in #993. Storybook's manager UI still binds its port (it starts before the preview builder hits the deadlocked promise), which disguised the boot hang as a proxy problem.The fix:
Symbol.for('@storybook-vue/nuxt:vite-config-promise')on the shared Nuxt instancelistenhook without awaiting it (failures still surface via the logger)loadNuxtViteConfigconsumes the captured promise instead of registering a hook that may already have missed the event; the previous hook registration remains as a fallback for embedding without the moduleci: truetobuildDevStandaloneso a busy port can never block the (quiet-mode) startup on an invisible interactive promptTests:
nuxt devwith the module starting Storybook), which was previously untested — the suite only exercised standalonestorybook dev. Asserts the Nuxt app responds and a story renders, across Chromium/Firefox/WebKit (15/15 with the existing tests).test/module-integration.spec.tsupdated: it previously asserted the deadlockingawaitpattern as correct.dist). I'll file that separately, along with an embedded-mode docs-index gap found during testing.Verified against the reproduction from #993 (braedenfoster/storybook-test-nuxt-4) with packed tarballs: app responds immediately, embedded Storybook fully boots (
➜ Storybook: http://localhost:6006/), stories render.(investigated and fixed with Claude Fable 5 assistance)