diff --git a/MIGRATION.md b/MIGRATION.md index c655a4a38ac8..d3a38d5065a0 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -21,6 +21,7 @@ - [Vite builder uses vite config automatically](#vite-builder-uses-vite-config-automatically) - [Removed docs.getContainer and getPage parameters](#removed-docsgetcontainer-and-getpage-parameters) - [Icons API changed](#icons-api-changed) + - ['config' preset entry replaced with 'previewAnnotations'](#config-preset-entry-replaced-with-preview-annotations) - [Docs Changes](#docs-changes) - [Standalone docs files](#standalone-docs-files) - [Referencing stories in docs files](#referencing-stories-in-docs-files) @@ -543,6 +544,12 @@ export interface IconsProps extends ComponentProps { Full change here: https://github.com/storybookjs/storybook/pull/18809 +#### 'config' preset entry replaced with 'previewAnnotations' + +The preset field `'config'` has been replaced with `'previewAnnotations'`. `'config'` is now deprecated and will be removed in Storybook 8.0. + +Additionally, the internal field `'previewEntries'` has been removed. If you need a preview entry, just use a `'previewAnnotations'` file and don't export anything. + ### Docs Changes The information hierarchy of docs in Storybook has changed in 7.0. The main difference is that each docs is listed in the sidebar as a separate entry, rather than attached to individual stories. @@ -672,9 +679,7 @@ import * as previewAnnotations from '../.storybook/preview'; export default function App({ Component, pageProps }) { return ( - + ); @@ -798,8 +803,7 @@ import startCase from 'lodash/startCase'; addons.setConfig({ sidebar: { - renderLabel: ({ name, type }) => - type === 'story' ? name : startCase(name), + renderLabel: ({ name, type }) => (type === 'story' ? name : startCase(name)), }, }); ``` @@ -1226,11 +1230,7 @@ After: ```js // .storybook/main.js module.exports = { - staticDirs: [ - '../public', - '../static', - { from: '../foo/assets', to: '/assets' }, - ], + staticDirs: ['../public', '../static', { from: '../foo/assets', to: '/assets' }], }; ``` @@ -1778,17 +1778,13 @@ This breaking change only affects you if your stories actually use the context, Consider the following story that uses the context: ```js -export const Dummy = ({ parameters }) => ( -
{JSON.stringify(parameters)}
-); +export const Dummy = ({ parameters }) =>
{JSON.stringify(parameters)}
; ``` Here's an updated story for 6.0 that ignores the args object: ```js -export const Dummy = (_args, { parameters }) => ( -
{JSON.stringify(parameters)}
-); +export const Dummy = (_args, { parameters }) =>
{JSON.stringify(parameters)}
; ``` Alternatively, if you want to opt out of the new behavior, you can add the following to your `.storybook/preview.js` config: @@ -2208,7 +2204,7 @@ To configure a11y now, you have to specify configuration using story parameters, ```js export const parameters = { a11y: { - element: "#storybook-root", + element: '#storybook-root', config: {}, options: {}, manual: true, @@ -2578,9 +2574,7 @@ For example, here's how to sort by story ID using `storySort`: addParameters({ options: { storySort: (a, b) => - a[1].kind === b[1].kind - ? 0 - : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }), + a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }), }, }); ``` @@ -2626,9 +2620,7 @@ Storybook 5.1 relies on `core-js@^3.0.0` and therefore causes a conflict with An { "compilerOptions": { "paths": { - "core-js/es7/reflect": [ - "node_modules/core-js/proposals/reflect-metadata" - ], + "core-js/es7/reflect": ["node_modules/core-js/proposals/reflect-metadata"], "core-js/es6/*": ["node_modules/core-js/es"] } } diff --git a/code/lib/builder-vite/src/codegen-iframe-script.ts b/code/lib/builder-vite/src/codegen-iframe-script.ts index 4a473faa437b..cc35bb9071ee 100644 --- a/code/lib/builder-vite/src/codegen-iframe-script.ts +++ b/code/lib/builder-vite/src/codegen-iframe-script.ts @@ -7,12 +7,11 @@ import type { ExtendedOptions } from './types'; export async function generateIframeScriptCode(options: ExtendedOptions) { const { presets } = options; const frameworkName = await getFrameworkName(options); - const presetEntries = await presets.apply('config', [], options); - const previewEntries = await presets.apply('previewEntries', [], options); - const absolutePreviewEntries = previewEntries.map((entry) => + const previewAnnotations = await presets.apply('previewAnnotations', [], options); + const resolvedPreviewAnnotations = previewAnnotations.map((entry) => isAbsolute(entry) ? entry : resolve(entry) ); - const configEntries = [...presetEntries, ...absolutePreviewEntries].filter(Boolean); + const configEntries = [...resolvedPreviewAnnotations].filter(Boolean); const absoluteFilesToImport = (files: string[], name: string) => files diff --git a/code/lib/builder-vite/src/codegen-modern-iframe-script.ts b/code/lib/builder-vite/src/codegen-modern-iframe-script.ts index 21c0a072e621..4b6339521a47 100644 --- a/code/lib/builder-vite/src/codegen-modern-iframe-script.ts +++ b/code/lib/builder-vite/src/codegen-modern-iframe-script.ts @@ -9,12 +9,11 @@ export async function generateModernIframeScriptCode(options: ExtendedOptions) { const frameworkName = await getFrameworkName(options); const previewOrConfigFile = loadPreviewOrConfigFile({ configDir }); - const presetEntries = await presets.apply('config', [], options); - const previewEntries = await presets.apply('previewEntries', [], options); - const absolutePreviewEntries = [...presetEntries, ...previewEntries].map((entry) => + const previewAnnotations = await presets.apply('previewAnnotations', [], options); + const resolvedPreviewAnnotations = [...previewAnnotations].map((entry) => isAbsolute(entry) ? entry : resolve(entry) ); - const configEntries = [...absolutePreviewEntries, previewOrConfigFile] + const relativePreviewAnnotations = [...resolvedPreviewAnnotations, previewOrConfigFile] .filter(Boolean) .map((configEntry) => transformAbsPath(configEntry as string)); @@ -34,7 +33,9 @@ export async function generateModernIframeScriptCode(options: ExtendedOptions) { preview.onStoriesChanged({ importFn: newModule.importFn }); }); - import.meta.hot.accept(${JSON.stringify(configEntries)}, ([...newConfigEntries]) => { + import.meta.hot.accept(${JSON.stringify( + relativePreviewAnnotations + )}, ([...newConfigEntries]) => { const newGetProjectAnnotations = () => composeConfigs(newConfigEntries); // getProjectAnnotations has changed so we need to patch the new one in @@ -56,8 +57,8 @@ export async function generateModernIframeScriptCode(options: ExtendedOptions) { import { importFn } from '${virtualStoriesFile}'; const getProjectAnnotations = async () => { - const configs = await Promise.all([${configEntries - .map((configEntry) => `import('${configEntry}')`) + const configs = await Promise.all([${relativePreviewAnnotations + .map((previewAnnotation) => `import('${previewAnnotation}')`) .join(',\n')}]) return composeConfigs(configs); } diff --git a/code/lib/builder-webpack5/src/presets/preview-preset.ts b/code/lib/builder-webpack5/src/presets/preview-preset.ts index fdd31c435caf..eb608d16687c 100644 --- a/code/lib/builder-webpack5/src/presets/preview-preset.ts +++ b/code/lib/builder-webpack5/src/presets/preview-preset.ts @@ -5,8 +5,6 @@ export const webpack = async (_: unknown, options: any) => webpackConfig(options export const entries = async (_: unknown, options: any) => { let result: string[] = []; - result = result.concat(await options.presets.apply('previewEntries', [], options)); - if (options.configType === 'DEVELOPMENT') { // Suppress informational messages when --quiet is specified. webpack-hot-middleware's quiet // parameter would also suppress warnings. diff --git a/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts index 8d666c4854bc..fd30edbfb2bc 100644 --- a/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/lib/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -82,8 +82,8 @@ export default async ( typeof coreOptions.builder === 'string' ? {} : coreOptions.builder?.options || {}; const docsOptions = await presets.apply('docs'); - const configs = [ - ...(await presets.apply('config', [], options)), + const previewAnnotations = [ + ...(await presets.apply('previewAnnotations', [], options)), loadPreviewOrConfigFile(options), ].filter(Boolean); const entries = (await presets.apply('entries', [], options)) as string[]; @@ -109,7 +109,7 @@ export default async ( ), { storiesFilename, - configs, + previewAnnotations, } // We need to double escape `\` for webpack. We may have some in windows paths ).replace(/\\/g, '\\\\'); @@ -125,21 +125,21 @@ export default async ( path.join(__dirname, 'virtualModuleEntry.template.js') ); - configs.forEach((configFilename: any) => { + previewAnnotations.forEach((previewAnnotationFilename: any) => { const clientApi = storybookPaths['@storybook/client-api']; const clientLogger = storybookPaths['@storybook/client-logger']; // NOTE: although this file is also from the `dist/cjs` directory, it is actually a ESM // file, see https://github.com/storybookjs/storybook/pull/16727#issuecomment-986485173 - virtualModuleMapping[`${configFilename}-generated-config-entry.js`] = interpolate( + virtualModuleMapping[`${previewAnnotationFilename}-generated-config-entry.js`] = interpolate( entryTemplate, { - configFilename, + previewAnnotationFilename, clientApi, clientLogger, } ); - entries.push(`${configFilename}-generated-config-entry.js`); + entries.push(`${previewAnnotationFilename}-generated-config-entry.js`); }); if (stories.length > 0) { const storyTemplate = await readTemplate( diff --git a/code/lib/builder-webpack5/src/preview/virtualModuleEntry.template.js b/code/lib/builder-webpack5/src/preview/virtualModuleEntry.template.js index b667a36248a0..6df03401a331 100644 --- a/code/lib/builder-webpack5/src/preview/virtualModuleEntry.template.js +++ b/code/lib/builder-webpack5/src/preview/virtualModuleEntry.template.js @@ -10,10 +10,10 @@ import { addArgTypesEnhancer, setGlobalRender, } from '{{clientApi}}'; -import * as config from '{{configFilename}}'; +import * as previewAnnotations from '{{previewAnnotationFilename}}'; -Object.keys(config).forEach((key) => { - const value = config[key]; +Object.keys(previewAnnotations).forEach((key) => { + const value = previewAnnotations[key]; switch (key) { case 'args': { return addArgs(value); @@ -54,8 +54,9 @@ Object.keys(config).forEach((key) => { return addStepRunner(value); } default: { - // eslint-disable-next-line prefer-template - return console.log(key + ' was not supported :( !'); + return console.log( + `Unknown key '${key}' exported by preview annotation file '{{previewAnnotationFilename}}'` + ); } } }); diff --git a/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars b/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars index 8fb2b4edf965..fddbe23fd1f0 100644 --- a/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars +++ b/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars @@ -12,7 +12,7 @@ import { importFn } from './{{storiesFilename}}'; const { SERVER_CHANNEL_URL } = global; const getProjectAnnotations = () => - composeConfigs([{{#each configs}}require('{{this}}'),{{/each}}]); + composeConfigs([{{#each previewAnnotations}}require('{{this}}'),{{/each}}]); const channel = createPostMessageChannel({ page: 'preview' }); addons.setChannel(channel); @@ -38,7 +38,7 @@ if (module.hot) { preview.onStoriesChanged({ importFn }); }); - import.meta.webpackHot.accept([{{#each configs}}'{{this}}',{{/each}}], () => { + import.meta.webpackHot.accept([{{#each previewAnnotations}}'{{this}}',{{/each}}], () => { // getProjectAnnotations has changed so we need to patch the new one in preview.onGetProjectAnnotationsChanged({ getProjectAnnotations }); }); diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index 172d0301447b..1b48ce2fc311 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -70,6 +70,7 @@ "slash": "^3.0.0", "telejson": "^6.0.8", "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", "watchpack": "^2.2.0", "ws": "^8.2.3" }, diff --git a/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-dev-posix b/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-dev-posix index 391ace7957b0..7948b46f6d30 100644 --- a/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-dev-posix +++ b/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-dev-posix @@ -3,7 +3,6 @@ exports[`cra-ts-essentials preview dev 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "NODE_MODULES/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined", "CWD/storybook-config-entry.js", ], diff --git a/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-prod-posix b/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-prod-posix index 2e4f4110322b..012fe9e3edff 100644 --- a/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-prod-posix +++ b/code/lib/core-server/src/__snapshots__/cra-ts-essentials_preview-prod-posix @@ -3,7 +3,6 @@ exports[`cra-ts-essentials preview prod 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "CWD/storybook-config-entry.js", ], "keys": Array [ diff --git a/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-dev-posix b/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-dev-posix index d57993932733..45ceee92d336 100644 --- a/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-dev-posix +++ b/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-dev-posix @@ -3,7 +3,6 @@ exports[`html-kitchen-sink preview dev 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "NODE_MODULES/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined", "CWD/storybook-config-entry.js", ], diff --git a/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-prod-posix b/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-prod-posix index db63f2b641a7..00580824683a 100644 --- a/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-prod-posix +++ b/code/lib/core-server/src/__snapshots__/html-kitchen-sink_preview-prod-posix @@ -3,7 +3,6 @@ exports[`html-kitchen-sink preview prod 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "CWD/storybook-config-entry.js", ], "keys": Array [ diff --git a/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-dev-posix b/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-dev-posix index 4735efac5fe0..6dcf0e0f0cba 100644 --- a/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-dev-posix +++ b/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-dev-posix @@ -3,7 +3,6 @@ exports[`vue-3-cli preview dev 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "NODE_MODULES/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined", "CWD/storybook-config-entry.js", ], diff --git a/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-prod-posix b/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-prod-posix index d88952382124..4ed666b00a7a 100644 --- a/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-prod-posix +++ b/code/lib/core-server/src/__snapshots__/vue-3-cli_preview-prod-posix @@ -3,7 +3,6 @@ exports[`vue-3-cli preview prod 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "CWD/storybook-config-entry.js", ], "keys": Array [ diff --git a/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev-posix b/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev-posix index eb686edb6dad..49672fbbc660 100644 --- a/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev-posix +++ b/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev-posix @@ -3,7 +3,6 @@ exports[`web-components-kitchen-sink preview dev 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "NODE_MODULES/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined", "CWD/storybook-config-entry.js", ], diff --git a/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod-posix b/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod-posix index dd79651d6668..17e5f58c2eef 100644 --- a/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod-posix +++ b/code/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod-posix @@ -3,7 +3,6 @@ exports[`web-components-kitchen-sink preview prod 1`] = ` Object { "entry": Array [ - "CWD/lib/core-client/dist/esm/globals/globals.js", "CWD/storybook-config-entry.js", ], "keys": Array [ diff --git a/code/lib/core-server/src/presets/common-preset.ts b/code/lib/core-server/src/presets/common-preset.ts index 34e5c5755871..daefd2030a70 100644 --- a/code/lib/core-server/src/presets/common-preset.ts +++ b/code/lib/core-server/src/presets/common-preset.ts @@ -1,4 +1,5 @@ import fs from 'fs-extra'; +import deprecate from 'util-deprecate'; import { CLIOptions, getPreviewBodyTemplate, @@ -15,6 +16,9 @@ import type { } from '@storybook/core-common'; import { loadCsf } from '@storybook/csf-tools'; +const warnConfigField = deprecate(() => {}, +`You (or an addon) are using the 'config' preset field. This has been replaced by 'previewAnnotations' and will be removed in 8.0`); + export const babel = async (_: unknown, options: Options) => { const { presets } = options; @@ -42,11 +46,6 @@ export const previewBody = async (base: any, { configDir, presets }: Options) => export const previewMainTemplate = () => getPreviewMainTemplate(); -export const previewEntries = (entries: any[] = []) => { - entries.push(require.resolve('@storybook/core-client/dist/esm/globals/globals')); - return entries; -}; - export const typescript = () => ({ check: false, // 'react-docgen' faster but produces lower quality typescript results @@ -89,8 +88,12 @@ export const core = async (existing: CoreConfig, options: Options): Promise { - return [...(await options.presets.apply('previewAnnotations', [], options)), ...base]; +export const previewAnnotations = async (base: any, options: Options) => { + const config = await options.presets.apply('config', [], options); + + if (config.length > 0) warnConfigField(); + + return [...config, require.resolve('@storybook/core-client/dist/esm/globals/globals'), ...base]; }; export const features = async ( diff --git a/code/yarn.lock b/code/yarn.lock index b0d4218fee01..3f17f41b0806 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8146,6 +8146,7 @@ __metadata: ts-dedent: ^2.0.0 ts-jest: ^26.4.4 typescript: ~4.6.3 + util-deprecate: ^1.0.2 watchpack: ^2.2.0 webpack: 5 ws: ^8.2.3 diff --git a/scripts/sandbox.ts b/scripts/sandbox.ts index b9f6cb1d717c..7c8ead941d7b 100644 --- a/scripts/sandbox.ts +++ b/scripts/sandbox.ts @@ -13,6 +13,7 @@ import { import prompts from 'prompts'; import type { AbortController } from 'node-abort-controller'; import command from 'execa'; +import dedent from 'ts-dedent'; import { createOptions, getOptionsOrPrompt, OptionValues } from './utils/options'; import { executeCLIStep } from './utils/cli-step'; @@ -23,7 +24,6 @@ import { ConfigFile, readConfig, writeConfig } from '../code/lib/csf-tools'; import { babelParse } from '../code/lib/csf-tools/src/babelParse'; import TEMPLATES from '../code/lib/cli/src/repro-templates'; import { servePackages } from './utils/serve-packages'; -import dedent from 'ts-dedent'; type Template = keyof typeof TEMPLATES; const templates: Template[] = Object.keys(TEMPLATES) as any; @@ -255,6 +255,11 @@ function forceViteRebuilds(mainConfig: ConfigFile) { ); } +function addPreviewAnnotations(mainConfig: ConfigFile, paths: string[]) { + const config = mainConfig.getFieldValue(['previewAnnotations']) as string[]; + mainConfig.setFieldValue(['previewAnnotations'], [...(config || []), ...paths]); +} + // paths are of the form 'renderers/react', 'addons/actions' async function addStories(paths: string[], { mainConfig }: { mainConfig: ConfigFile }) { // Add `stories` entries of the form @@ -289,11 +294,10 @@ async function addStories(paths: string[], { mainConfig }: { mainConfig: ConfigF ) ); - const config = mainConfig.getFieldValue(['config']) as string[]; const extraConfig = extraPreviewAndExistence .filter(([, exists]) => exists) .map(([p]) => path.join('..', '..', 'code', p)); - mainConfig.setFieldValue(['config'], [...(config || []), ...extraConfig]); + addPreviewAnnotations(mainConfig, extraConfig); } type Workspace = { name: string; location: string }; @@ -379,10 +383,7 @@ export async function sandbox(optionValues: OptionValues) { path.join(codeDir, rendererPath, 'template', 'components'), path.resolve(cwd, storiesPath, 'components') ); - mainConfig.setFieldValue( - ['previewEntries'], - [`.${path.sep}${path.join(storiesPath, 'components')}`] - ); + addPreviewAnnotations(mainConfig, [`.${path.sep}${path.join(storiesPath, 'components')}`]); // Link in the stories from the store, the renderer and the addons const storiesToAdd = [] as string[];