Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug]: staticDirs fail on deep merges when multiple sources have conflicting nested folders #31873

@tomer953

Description

@tomer953

Describe the bug

Hi team,

Thanks for the improvements in #30467 - the fix addressed a major limitation in serving multiple staticDirs on the same to: path. However, there's still a subtle but impactful edge case that breaks dev consistency and is not covered by that fix.

staticDirs: [
  { from: 'a-dir', to: 'assets' }, // contains /sprite/foo.svg
  { from: 'b-dir', to: 'assets' }  // also contains /sprite/foo.svg
]

Even though both folders are mounted to /assets, and both contain a sprite/ subfolder:

In dev (Polka + Sirv):
Sirv will serve only the first match (a-dir/sprite/foo.svg), The second folder is ignored for that subpath.

First, we tried to rename similar nested folders to avoid conflicts, but I think we also have issues if the to: property isn't the exact match like others, so in this case:

staticDirs: [
  { from: 'dsm/src/assets', to: 'assets' }, // have /sprite
  { from: 'app/src/assets', to: 'assets' }, // used to have /sprite and not renamed to `app-sprite` to avoid conflicts
  { from: 'global-assets/sprites', to: 'assets/sprite' } // now this do not "hit" anymore, and all sprites here are missing
]

all the assets from global-assets/sprites are not served at all

Workaround

We now run a custom merge script before launching Storybook:
something like

	// Copy each source directory into the merged output, optionally into a subfolder
		for (const {from, subdir} of sources) {
			const sourcePath = path.resolve(from);
			const targetPath = subdir ? path.join(mergedOutput, subdir) : mergedOutput;
			await fs.copy(sourcePath, targetPath);
		}

It combines all asset sources into one merged folder

  • Deduplicates as needed
  • Ensures a consistent /assets directory
  • Serves only one merged folder via staticDirs
  • This avoids relying on Polka + Sirv's runtime behavior.

Suggested improvement

Consider adding:

  • A warning when overlapping staticDirs might conflict deeply (i.e., same to: + shared subpaths)
  • A documented recommendation to avoid merging staticDirs to the same to: unless files are fully disjoint
  • A long-term improvement: normalize dev/build behavior by merging directory trees in dev like build does (or vice versa)

Reproduction link

https://new-storybook.netlify.app/

Reproduction steps

No response

System

System:
    OS: macOS 15.5
    CPU: (14) arm64 Apple M4 Pro
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.17.0 - ~/.volta/tools/image/node/20.17.0/bin/node
    npm: 10.8.2 - ~/.volta/tools/image/npm/10.8.2/bin/npm <----- active
  Browsers:
    Chrome: 138.0.7204.50
    Safari: 18.5


storybook: 8.5.8

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions