Skip to content
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

Vue: Fix out of memory error when using vue-component-meta #28589

Merged
merged 5 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,26 @@ export async function vueComponentMeta(tsconfigPath = 'tsconfig.json'): Promise<

const exportName = exportNames[index];

// we remove nested object schemas here since they are not used inside Storybook (we don't generate controls for object properties)
// and they can cause "out of memory" issues for large/complex schemas (e.g. HTMLElement)
// it also reduced the bundle size when running "Storybook build" when such schemas are used
(['props', 'exposed'] as const).forEach((key) => {
meta[key].forEach((value) => {
if (typeof value.schema !== 'object') return;

// we need to use Object.defineProperty here since schema is a getter so we can not set it directly
Object.defineProperty(value, 'schema', {
configurable: true,
enumerable: true,
value: {
kind: value.schema.kind,
type: value.schema.type,
// note that value.schema.schema is not included here (see comment above)
},
});
});
});

const exposed =
// the meta also includes duplicated entries in the "exposed" array with "on"
// prefix (e.g. onClick instead of click), so we need to filter them out here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"value": {
"name": "object",
"required": false,
"value": {
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
},
},
Expand All @@ -183,12 +178,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"value": {
"name": "object",
"required": false,
"value": {
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
},
},
Expand Down Expand Up @@ -279,12 +269,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"type": {
"name": "object",
"required": true,
"value": {
"foo": {
"name": "string",
"required": true,
},
},
"value": {},
},
},
"literalFromContext": {
Expand Down Expand Up @@ -325,12 +310,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"type": {
"name": "object",
"required": true,
"value": {
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
},
"nestedIntersection": {
Expand All @@ -347,16 +327,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"type": {
"name": "object",
"required": true,
"value": {
"additionalProp": {
"name": "string",
"required": true,
},
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
},
"nestedOptional": {
Expand All @@ -377,22 +348,12 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
{
"name": "object",
"required": false,
"value": {
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
{
"name": "object",
"required": false,
"value": {
"nestedProp": {
"name": "string",
"required": true,
},
},
"value": {},
},
],
},
Expand All @@ -411,13 +372,7 @@ exports[`extractArgTypes (vue-docgen-api) > should extract props for component 1
"type": {
"name": "object",
"required": false,
"value": {
"recursive": {
"name": "other",
"required": true,
"value": "MyNestedRecursiveProps",
},
},
"value": {},
},
},
"stringArray": {
Expand Down
13 changes: 4 additions & 9 deletions code/renderers/vue3/src/docs/extractArgTypes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { VueDocgenInfo, VueDocgenInfoEntry, VueDocgenPlugin } from '@storybook/vue3-vite';
import type { ExtractedProp } from 'storybook/internal/docs-tools';
import {
convert,
Expand All @@ -6,7 +7,6 @@ import {
type ArgTypesExtractor,
} from 'storybook/internal/docs-tools';
import type { SBType, StrictArgTypes, StrictInputType } from 'storybook/internal/types';
import type { VueDocgenInfo, VueDocgenInfoEntry, VueDocgenPlugin } from '@storybook/vue3-vite';

type PropertyMetaSchema = VueDocgenInfoEntry<'vue-component-meta', 'props'>['schema'];

Expand Down Expand Up @@ -283,17 +283,12 @@ export const convertVueComponentMetaProp = (
};
}

// recursively/deeply convert all properties of the object
case 'object':
return {
name: 'object',
value: Object.entries(schema.schema ?? {}).reduce<Record<string, SBType>>(
(obj, [propName, propSchema]) => {
obj[propName] = convertVueComponentMetaProp(propSchema);
return obj;
},
{}
),
// while Storybook generates simple JSON object controls, nested schemas don't have specialized controls
// so we don't need to recursively map the object schema here
value: {},
required,
};

Expand Down