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 for events and slots #28674

Merged
merged 1 commit into from
Jul 23, 2024
Merged
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
31 changes: 17 additions & 14 deletions code/frameworks/vue3-vite/src/plugins/vue-component-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
createCheckerByJson,
type ComponentMeta,
type MetaCheckerOptions,
type PropertyMetaSchema,
} from 'vue-component-meta';
import { parseMulti } from 'vue-docgen-api';

Expand Down Expand Up @@ -52,21 +53,14 @@ export async function vueComponentMeta(tsconfigPath = 'tsconfig.json'): Promise<

// 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) => {
// it also reduced the bundle size when running "storybook build" when such schemas are used
(['props', 'events', 'slots', '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)
},
});
if (Array.isArray(value.schema)) {
value.schema.forEach((eventSchema) => removeNestedSchemas(eventSchema));
} else {
removeNestedSchemas(value.schema);
}
});
});

Expand Down Expand Up @@ -270,3 +264,12 @@ async function getTsConfigReferences(tsConfigPath: string) {
return [];
}
}

/**
* Removes any nested schemas from the given main schema (e.g. from a prop, event, slot or exposed).
* Useful to drastically reduce build size and prevent out of memory issues when large schemas (e.g. HTMLElement, MouseEvent) are used.
*/
function removeNestedSchemas(schema: PropertyMetaSchema) {
if (typeof schema !== 'object') return;
delete schema.schema;
}