storybookjs/storybook

[Bug]: Svelte Docgen runs on more components than necessary

Open

#32,233 创建于 2025年8月10日

在 GitHub 查看
 (2 评论) (3 反应) (1 负责人)TypeScript (89,909 star) (10,058 fork)batch import
bugdocgenhelp wantedperformance issuesev:S3svelte

描述

The Problem

Svelte Docgen works via a Vite plugin that transforms Svelte components to add a __docgen property to their default export. Computing this property is very accurate and uses the same mechanism as Svelte's language server: converting the component to TSX with svelte2tsx and using typescript to extract the props from it.

However this is also slow, as it involves spinning up TypeScript programs and what not. I'm sure there are ways to speed it up, but the biggest problem is that the docgen runs on way too many files. Using the following filter, docgen information is added to all Svelte components that are not in node_modules:

https://github.com/storybookjs/storybook/blob/19dfdec39469a8911ca675484de2d2920f4c8720/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts#L110-L114

In most real world projects, there are less components with direct stories than without, meaning that we'll run the expensive docgen on many components without it ever being read. Furthermore, we're also generating docgen for all X.stories.svelte files, which of course never makes sense.

The only components that we ever read docgen from, are those that are referenced as components in the meta, eg.:

<script module>
  import Button from './Button.svelte';
  import { defineMeta } from '@storybook/addon-svelte-csf';

  const { Story } = defineMeta({
    component: Button, // 👈 this indicates that we want to generate docgen for the Button component
    ...
  });
</script>

or regular CSF:

import Button from './Button.svelte';

export default {
  component: Button, // 👈 this indicates that we want to generate docgen for the Button component
  ...
};

The Proposed Solution

Instead of using a simple regex filter in the Vite plugin, we should make it smart again. It should run a first pass across all story files, collecting all paths to modules that are referenced as a component in meta. Then, when it's time to actually filter in the transform, we should ensure we're bailing out if the id isn't part of that list of referenced modules.

There are a few complexities here though:

  1. Regular CSF vs Svelte CSF, ideally it should work for both ways of defining stories.
  2. Component modules that aren't referenced directly, but eg. via barrel files instead, like:
// barrel.js
import Button from './Button.svelte';

export const Button;
import { Button } from './barrel.js';

export default {
  component: Button,
  ...
};

If we were naive here, we would just have barrel.js in the list of referenced components, which would mean we'd be skipping Button.svelte. We'd need to traverse the modules and imports to ensure that transitive modules where added as well.

Additional Context

Most if not all renderers suffers from this problem, but it seems that Svelte's docgen is slower than the others', so it hurts more in Svelte.

贡献者指南