-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error: CSF: missing default export #16598
Comments
hi @seanmcintyre! Thanks for filing this. Can you share your Starting in 6.4 we're statically analyzing the structure of CSF and this structure is not currently supported by the analysis. I need to think about whether/how to support it--it's technically possible, but may have some limitations. And if we choose not to support it, we should have a lot clearer error message. |
Son of a gun!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.4.0-beta.29 containing PR #16607 that references this issue. Upgrade today to the
Closing this issue. Please re-open if you think there's still more to do. |
https://github.com/vimeo/iris/blob/refactor/.storybook/main.js
|
@seanmcintyre does |
@shilman are you suggesting that CSF is not based on ES modules exporting objects with a particular API, but instead some static object structure? I must have misunderstood the docs if that's the case |
@nagromLobo CSF is based on ES modules exporting objects with a particular API That said, there are limitations. Due to implementation details, there are certain things we don't support. For example, the following is valid ESM: const bar = 'bar';
export default { title: `foo/${bar}` } However, we can't statically analyze that. So instead, you'd need to write it as: export default { title: "foo/bar" } We've tried to encode some of these constraints into linting rules: https://github.com/storybookjs/eslint-plugin-storybook |
To get storybook to play nice with typescript and our components we wrote some utils to generate the default export / individual stories. This suggests to me that that wouldn't be recommended. Practically I'm not seeing any problems (v6.4.21), though this makes me think that our storybook could run into issues in the future because we implemented this under the assumption that storybook was consuming runtime ES modules. |
@nagromLobo yes I'd recommend against it. try setting |
@shilman Is there a recommended way to get types tied to meta/stories so that we could be (relatively) confident that if a component's props changed we wouldn't be breaking any meta/stories that reference it? (the types in the storybook docs use type-casting so they loose some type information) |
For more context we are currently doing export const defineComponentMeta = <
C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any> = never
>(
meta: ComponentMeta<C> & { args: ComponentProps<C> } // force required args to be set to avoid storybook passing `undefined` by default
) => {
return meta;
}; consumed like: type ITextInput = typeof TextInput;
export default defineComponentMeta<ITextInput>({
component: TextInput,
args: {
label: 'Label',
value: '',
onChange: action('onChange'),
},
argTypes: {
value: { control: false },
},
}); Which helps us ensure that any required props are defined in |
WIP here #13747 |
Thanks for the quick responses and for pointing me to the right place! |
We did exactly the same as you did @nagromLobo, we have custom helper functions that wrap the CSF syntax and have additional requirements ( I guess the implementations based on runtime interpretation will break in V7? (Also we're using Angular Storybook, so we added some more quality of life features like a |
@NiklasPor We'll have a legacy mode so you can still use old code in V7. However, we're seeing dramatic performance improvements coming from the on-demand store + lazy compilation in webpack5, so in order to benefit from those you'll need to update your code. |
@shilman Ok, that sounds great 🚀 |
I had the same problem, took me a while to realize I had to set |
@shilman Is it not possible to evaluate the default export while statically analyzing the CSF module? We get dramatic DX imporvements by using this tiny helper for defining type safe meta/stories. import {ComponentProps, JSXElementConstructor} from 'react';
import {Meta, StoryObj} from '@storybook/react';
export function storyFactory<
C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any> = never,
>(Component: C, metaPrams: Omit<Meta<C>, 'component'>) {
return {
meta: {
...(metaPrams ?? {}),
component: Component,
},
story: (args: StoryObj<ComponentProps<typeof Component>>) => args,
};
} example usage: import {storyFactory} from 'storybook-utils';
import {MyComponent} from './MyComponent';
const {meta, story} = storyFactory(MyComponent, {
// define component level meta properties
decorators: [],
args: {}
});
// type safe stories
export const Default = story({
args: {
allConnectionsAssigned: false,
},
});
export default meta; Is there a reason why this should not be supported? As long as a function returns an object with valid meta properties, who cares how it is defined? |
The issue is still present in version v7.0.0-rc.7 though I'm actually using default export in the component
|
It's work only like this: export default { ...dynamicMeta, title: 'Buttons/TextButton' } |
I'm new to Storybook and was following the tutorial for Angular (https://storybook.js.org/tutorials/intro-to-storybook/angular/en/simple-component/). At the step after updating config and restarting StoryBook, I get a similar error. Unable to index ./src/app/components/task.stories.ts: Is the tutorial invalid with the latest version of StoryBook or does the error mean I've done something wrong? Storybook 7.6.6 for angular started |
We're in a very similar situation as the one described by @KevinMind in his comment. definition: export const storyFactory = (
Component: React.ComponentType
): {
meta: Meta<React.ComponentType>;
story: StoryObj<React.ComponentType>;
} => ({
meta: {
component: Component,
decorators: [/*...*/],
parameters: {/*...*/}
},
story: {
render: () => {
// stuff
return (
<>
{/* stuff */}
<Component />
</>
);
}
}
}); usage: const { meta, story } = storyFactory(() => (
<MyComponent {...props} />
));
export { story };
export default meta; which sadly yields:
|
@axedre that's a pretty lousy error message for your situation, but it is an error. We're looking into adding an optional factory wrapper to CSF for better typescript support and that could land late this year. When it does, you might be able to hack it in limited ways. But supporting arbitrary user defined functions is not on the roadmap and I don't see it ever being added to Storybook |
Hello @shilman , thanks for the reply.
Why is that, if I may ask? const MyComponent = (props: MyComponentProps) => (/* ... */);
const meta: Meta<MyComponentProps> = {
component: MyComponent,
decorators: [/* ... */],
parameters: {/* ... */}
};
export default meta; is considered ok, while const metaFactory = (Component: React.ComponentType<MyComponentProps>): Meta<MyComponentProps> => ({
component: Component,
decorators: [/* ... */],
parameters: {/* ... */}
});
const meta = metaFactory(MyComponent);
export default meta; is not? I'm a bit stomped, seems to me like a perfectly legit pattern, especially since |
@axedre we are statically analyzing the code, i.e. parsing the content of it without ever executing the code. We do this for performance reasons so that we can quickly generate the sidebar content without bundling all of your stories and the components etc that they depend on. This isn't possible when the contents of meta is the result of some arbitrary black box function |
agree that this is a big oversight @shilman. is the maybe a thought for an annotation/hint that helps the static analyzer include other files? |
@domastic-nate the plan is those factory functions would be provided by Storybook so that we know what's happening inside the black box and can provide the correct types |
Would love this change. Is there another issue that is opened for this plan? |
Using
6.4.0-beta.27
.This may not be a bug? Writing stories in separate files and re-exporting them from a single file yields the error:
Error: CSF: missing default export
To Reproduce
Re-export stories from a single file. Example:
System
The text was updated successfully, but these errors were encountered: