From add44fcc6aaa1860b2eb20e2a6a46663fad3ac0c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 09:54:54 +0100 Subject: [PATCH 1/4] dynamic import vite to force ESM mode --- code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts | 5 +++-- code/frameworks/svelte-vite/src/preset.ts | 2 +- .../sveltekit/src/plugins/mock-sveltekit-stores.ts | 5 +++-- code/frameworks/sveltekit/src/preset.ts | 2 +- code/frameworks/vue-vite/src/plugins/vue-docgen.ts | 4 ++-- code/frameworks/vue-vite/src/preset.ts | 2 +- code/frameworks/vue3-vite/src/plugins/vue-docgen.ts | 4 ++-- code/frameworks/vue3-vite/src/preset.ts | 5 +++-- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts index 5ee6f7e53ce..1e33174e11a 100644 --- a/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts +++ b/code/frameworks/svelte-vite/src/plugins/svelte-docgen.ts @@ -6,7 +6,6 @@ import svelteDoc from 'sveltedoc-parser'; import type { SvelteComponentDoc, SvelteParserOptions } from 'sveltedoc-parser'; import { logger } from '@storybook/node-logger'; import { preprocess } from 'svelte/compiler'; -import { createFilter } from 'vite'; import { replace, typescript } from 'svelte-preprocess'; /* @@ -59,10 +58,12 @@ function getNameFromFilename(filename: string) { return base[0].toUpperCase() + base.slice(1); } -export function svelteDocgen(svelteOptions: Record = {}): PluginOption { +export async function svelteDocgen(svelteOptions: Record = {}): Promise { const cwd = process.cwd(); const { preprocess: preprocessOptions, logDocgen = false } = svelteOptions; const include = /\.(svelte)$/; + const { createFilter } = await import('vite'); + const filter = createFilter(include); let docPreprocessOptions: Parameters[1] | undefined; diff --git a/code/frameworks/svelte-vite/src/preset.ts b/code/frameworks/svelte-vite/src/preset.ts index 220812cf7c5..2abc47c9d8b 100644 --- a/code/frameworks/svelte-vite/src/preset.ts +++ b/code/frameworks/svelte-vite/src/preset.ts @@ -26,7 +26,7 @@ export const viteFinal: NonNullable = async (confi } // Add docgen plugin - plugins.push(svelteDocgen(svelteConfig)); + plugins.push(await svelteDocgen(svelteConfig)); await handleSvelteKit(plugins, options); diff --git a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts index 873ce8bf351..62031b412bc 100644 --- a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts +++ b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts @@ -1,7 +1,8 @@ import { resolve } from 'node:path'; -import { mergeConfig, type Plugin } from 'vite'; +import type { Plugin } from 'vite'; -export function mockSveltekitStores() { +export async function mockSveltekitStores() { + const { mergeConfig } = await import('vite'); return { name: 'storybook:sveltekit-mock-stores', enforce: 'post', diff --git a/code/frameworks/sveltekit/src/preset.ts b/code/frameworks/sveltekit/src/preset.ts index 45cfe7d0a6d..bef848c9250 100644 --- a/code/frameworks/sveltekit/src/preset.ts +++ b/code/frameworks/sveltekit/src/preset.ts @@ -32,7 +32,7 @@ export const viteFinal: NonNullable = async (confi ]) ) .concat(configOverrides()) - .concat(mockSveltekitStores()); + .concat(await mockSveltekitStores()); return { ...baseConfig, plugins }; }; diff --git a/code/frameworks/vue-vite/src/plugins/vue-docgen.ts b/code/frameworks/vue-vite/src/plugins/vue-docgen.ts index e80ca52d60c..4fb6107e5bc 100644 --- a/code/frameworks/vue-vite/src/plugins/vue-docgen.ts +++ b/code/frameworks/vue-vite/src/plugins/vue-docgen.ts @@ -1,10 +1,10 @@ import { parse } from 'vue-docgen-api'; import type { PluginOption } from 'vite'; -import { createFilter } from 'vite'; import MagicString from 'magic-string'; -export function vueDocgen(): PluginOption { +export async function vueDocgen(): Promise { const include = /\.(vue)$/; + const { createFilter } = await import('vite'); const filter = createFilter(include); return { diff --git a/code/frameworks/vue-vite/src/preset.ts b/code/frameworks/vue-vite/src/preset.ts index 3030587afaa..598b325d1b0 100644 --- a/code/frameworks/vue-vite/src/preset.ts +++ b/code/frameworks/vue-vite/src/preset.ts @@ -1,6 +1,5 @@ import { dirname, join } from 'path'; import type { PresetProperty } from '@storybook/types'; -import { mergeConfig } from 'vite'; import type { StorybookConfig } from './types'; import { vueDocgen } from './plugins/vue-docgen'; @@ -21,6 +20,7 @@ export const core: PresetProperty<'core', StorybookConfig> = async (config, opti }; export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => { + const { mergeConfig } = await import('vite'); return mergeConfig(config, { plugins: [vueDocgen()], resolve: { diff --git a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts index 6bed6a1fed9..f8008fc3a4b 100644 --- a/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts +++ b/code/frameworks/vue3-vite/src/plugins/vue-docgen.ts @@ -1,10 +1,10 @@ import { parse } from 'vue-docgen-api'; import type { PluginOption } from 'vite'; -import { createFilter } from 'vite'; import MagicString from 'magic-string'; -export function vueDocgen(): PluginOption { +export async function vueDocgen(): Promise { const include = /\.(vue)$/; + const { createFilter } = await import('vite'); const filter = createFilter(include); return { diff --git a/code/frameworks/vue3-vite/src/preset.ts b/code/frameworks/vue3-vite/src/preset.ts index b987f0381c0..bc9fd7752d1 100644 --- a/code/frameworks/vue3-vite/src/preset.ts +++ b/code/frameworks/vue3-vite/src/preset.ts @@ -1,6 +1,6 @@ import { hasVitePlugins } from '@storybook/builder-vite'; import type { PresetProperty } from '@storybook/types'; -import { mergeConfig, type PluginOption } from 'vite'; +import type { PluginOption } from 'vite'; import { dirname, join } from 'path'; import type { StorybookConfig } from './types'; import { vueDocgen } from './plugins/vue-docgen'; @@ -23,8 +23,9 @@ export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets } // Add docgen plugin - plugins.push(vueDocgen()); + plugins.push(await vueDocgen()); + const { mergeConfig } = await import('vite'); return mergeConfig(config, { plugins, resolve: { From 78f1c3569f55c1500aa6ab96ab45dddabd3fcaf5 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 09:56:48 +0100 Subject: [PATCH 2/4] improve readability of list of sandbox templates --- scripts/utils/options.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/utils/options.ts b/scripts/utils/options.ts index f5340c037a8..b6e7c930b9f 100644 --- a/scripts/utils/options.ts +++ b/scripts/utils/options.ts @@ -140,11 +140,12 @@ export function getOptions( const checkStringValue = (raw: string) => { if (option.values && !option.values.includes(raw)) { - const possibleOptions = chalk.cyan(option.values.join(', ')); + const possibleOptions = chalk.cyan(option.values.join('\n')); throw new Error( dedent`Unexpected value '${chalk.yellow(raw)}' for option '${chalk.magenta(key)}'. - These are the possible options: ${possibleOptions}\n\n` + These are the possible options: + ${possibleOptions}\n\n` ); } return raw; From 3fc9be5f3f03a54f535845427c597aa92676b53c Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 28 Nov 2023 10:34:26 +0100 Subject: [PATCH 3/4] add eslint rule to enforce dynamic vite imports --- code/.eslintrc.js | 12 ++++++++++++ code/builders/builder-vite/src/vite-config.test.ts | 1 + .../sveltekit/src/plugins/config-overrides.ts | 2 +- code/ui/.storybook/main.ts | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/code/.eslintrc.js b/code/.eslintrc.js index 953ccaf79d2..ab453987a3e 100644 --- a/code/.eslintrc.js +++ b/code/.eslintrc.js @@ -34,6 +34,18 @@ module.exports = { allowIndexSignaturePropertyAccess: true, }, ], + '@typescript-eslint/no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'vite', + message: 'Please dynamically import from vite instead, to force the use of ESM', + allowTypeImports: true, + }, + ], + }, + ], }, overrides: [ { diff --git a/code/builders/builder-vite/src/vite-config.test.ts b/code/builders/builder-vite/src/vite-config.test.ts index c4f2f212be4..a373bf7dce1 100644 --- a/code/builders/builder-vite/src/vite-config.test.ts +++ b/code/builders/builder-vite/src/vite-config.test.ts @@ -1,4 +1,5 @@ import type { Options, Presets } from '@storybook/types'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports import { loadConfigFromFile } from 'vite'; import { commonConfig } from './vite-config'; diff --git a/code/frameworks/sveltekit/src/plugins/config-overrides.ts b/code/frameworks/sveltekit/src/plugins/config-overrides.ts index d132764d6e5..db5294a1324 100644 --- a/code/frameworks/sveltekit/src/plugins/config-overrides.ts +++ b/code/frameworks/sveltekit/src/plugins/config-overrides.ts @@ -1,4 +1,4 @@ -import { type Plugin } from 'vite'; +import type { Plugin } from 'vite'; export function configOverrides() { return { diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index 4800dda1e18..a15c3a4fd98 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -1,5 +1,6 @@ import path from 'path'; import pluginTurbosnap from 'vite-plugin-turbosnap'; +// eslint-disable-next-line @typescript-eslint/no-restricted-imports import { mergeConfig } from 'vite'; import type { StorybookConfig } from '../../frameworks/react-vite'; From a88b242f0cbda0390de24491a0d5d5b59273515b Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 3 Jan 2024 12:56:20 +0100 Subject: [PATCH 4/4] Remove unneeded mergeConfig --- code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts index 58855bbd9df..32f6eb0c41b 100644 --- a/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts +++ b/code/frameworks/sveltekit/src/plugins/mock-sveltekit-stores.ts @@ -2,7 +2,6 @@ import { resolve } from 'node:path'; import type { Plugin } from 'vite'; export async function mockSveltekitStores() { - const { mergeConfig } = await import('vite'); return { name: 'storybook:sveltekit-mock-stores', config: () => ({