From 79b590b8de663ad0280f198706f26346de4ddcb1 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Thu, 30 Mar 2023 21:31:03 +0100 Subject: [PATCH] Tweaks to the Webpack docs --- docs/addons/writing-presets.md | 4 +- docs/builders/overview.md | 6 +- docs/builders/webpack.md | 167 +++++------------- docs/configure/frameworks.md | 2 +- docs/get-started/setup.md | 2 +- docs/sharing/storybook-composition.md | 2 +- .../storybook-main-add-sass-config.js.mdx | 6 + .../storybook-main-add-sass-config.ts.mdx | 35 ++++ .../storybook-main-simplified-config.js.mdx | 6 + .../storybook-main-simplified-config.ts.mdx | 21 +++ ...torybook-main-using-existing-config.js.mdx | 9 +- ...torybook-main-using-existing-config.ts.mdx | 9 +- .../storybook-main-webpack-options.js.mdx | 24 +++ .../storybook-main-webpack-options.ts.mdx | 29 +++ 14 files changed, 186 insertions(+), 136 deletions(-) create mode 100644 docs/snippets/common/storybook-main-add-sass-config.ts.mdx create mode 100644 docs/snippets/common/storybook-main-simplified-config.ts.mdx create mode 100644 docs/snippets/common/storybook-main-webpack-options.js.mdx create mode 100644 docs/snippets/common/storybook-main-webpack-options.ts.mdx diff --git a/docs/addons/writing-presets.md b/docs/addons/writing-presets.md index e66b36bf278e..4a8eca84a871 100644 --- a/docs/addons/writing-presets.md +++ b/docs/addons/writing-presets.md @@ -173,9 +173,9 @@ Entries are the place to register entry points for the preview. For example, it ## Advanced Configuration -The presets API is also more powerful than the [standard configuration options](../builders/webpack.md#extending-storybooks-webpack-config) available in Storybook, so it's also possible to use presets for more advanced configuration without actually publishing a preset yourself. +The presets API is also more powerful than the [standard configuration options](../builders/webpack.md#override-the-default-configuration) available in Storybook, so it's also possible to use presets for more advanced configuration without actually publishing a preset yourself. -For example, some users want to configure the Webpack for Storybook's UI and addons ([issue](https://github.com/storybookjs/storybook/issues/4995)), but this is not possible using [standard Webpack configuration](../builders/webpack.md#default-configuration) (it used to be possible before SB4.1). However, you can achieve this with a private preset. +For example, some users want to configure the Webpack for Storybook's UI and addons ([issue](https://github.com/storybookjs/storybook/issues/4995)), but this is not possible using [standard Webpack configuration](../builders/webpack.md#configure) (it used to be possible before SB4.1). However, you can achieve this with a private preset. If it doesn't exist yet, create a file `.storybook/main.js`: diff --git a/docs/builders/overview.md b/docs/builders/overview.md index b668d481c5e8..ccc4fed1ba11 100644 --- a/docs/builders/overview.md +++ b/docs/builders/overview.md @@ -8,17 +8,17 @@ Storybook, at its core, is powered by builders such as Webpack and Vite. These b ## CLI basics -Before diving into setting up Storybook's builders, let's look at how the CLI configures them. When you initialize Storybook (via `npx storybook init`), the CLI automatically detects which builder to use based on your application. For example, if you're working with Vite, it will install the Vite builder. If you're working with Webpack, it installs the Webpack builder based on your current version. +Before diving into setting up Storybook's builders, let's look at how the CLI configures them. When you initialize Storybook (via `npx storybook init`), the CLI automatically detects which builder to use based on your application. For example, if you're working with Vite, it will install the Vite builder. If you're working with Webpack, it installs the Webpack 5 builder by default. Additionally, you can also provide a flag to Storybook's CLI and specify the builder you want to use: ```shell -npx storybook init --builder +npx storybook init --builder ``` ## Manual setup -Storybook uses the Webpack 4 builder by default if you don't specify one. If you want to use a different builder in your application, these docs detail how you can set up Storybook's supported builders. +Storybook uses the Webpack 5 builder by default if you don't specify one. If you want to use a different builder in your application, these docs detail how you can set up Storybook's supported builders. - [**Vite builder**](./vite.md) for bundling your stories with Vite with near-instant HMR. - [**Webpack**](./webpack.md) for bundling your stories with Webpack with improved performance diff --git a/docs/builders/webpack.md b/docs/builders/webpack.md index fe5fcf6c54d3..9d19918812f0 100644 --- a/docs/builders/webpack.md +++ b/docs/builders/webpack.md @@ -2,216 +2,135 @@ title: 'Webpack' --- -Storybook displays your components in a custom web application built using [Webpack](https://webpack.js.org/). Webpack is a complex tool, but our default configuration is intended to cover most use cases. [Addons](https://storybook.js.org/addons/) are also available that extend the configuration for other everyday use cases. +Storybook Webpack builder is the default builder for Storybook. This builder enables you to create a seamless development and testing experience for your components and provides an efficient way to develop UI components in isolation allowing you to leverage your existing Webpack configuration with Storybook. -You can customize Storybook's Webpack setup by providing a `webpackFinal` field in [`.storybook/main.js`](../configure/overview.md#configure-your-storybook-project) file. +## Configure -The value should be an async function that receives a Webpack config and eventually returns a Webpack config. +By default, Storybook provides zero-config support for Webpack and automatically sets up a baseline configuration created to work with the most common use cases. However, you can extend your Storybook configuration file (i.e., `.storybook/main.js|ts`) and provide additional options to improve your Storybook's performance or customize it to your needs. Listed below are the available options and examples of how to use them. -### Default configuration - -By default, Storybook's Webpack configuration will allow you to: - -#### Import images and other static files - -You can import images and other local files and have them built into the Storybook: - - - - - - - -#### Import JSON as JavaScript - -You can import `.json` files and have them expanded to a JavaScript object: - - - - - - - -If you want to know the exact details of the Webpack config, the best way is to run either of the following commands: - -For development mode: - - - - - - - -For production mode: - - - - - - - -### Code splitting - -Starting with Storybook 6.4, [code splitting](https://v4.webpack.js.org/guides/code-splitting/) is supported through a configuration flag. Update your Storybook configuration and add the `storyStoreV7` flag: +| Option | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `storyStoreV7` | Enabled by default.
Configures Webpack's [code splitting](https://webpack.js.org/guides/code-splitting/) feature
`features: { storyStoreV7: false }` | +| `lazyCompilation` | Enables Webpack's experimental [`lazy compilation`](https://webpack.js.org/configuration/experiments/#experimentslazycompilation)
`core: { builder: { options: { lazyCompilation: true } } }` | +| `fsCache` | Configures Webpack's filesystem [caching](https://webpack.js.org/configuration/cache/#cachetype) feature
`core: { builder: { options: { fsCache: true } } }` | -When you start your Storybook, you'll see an improvement in loading times. Read more about it in the [announcement post](https://storybook.js.org/blog/storybook-on-demand-architecture/) and the [configuration documentation](../configure/overview.md#configure-your-storybook-project). - -### Webpack 5 +### Override the default configuration -Storybook builds your project with Webpack 4 by default. If your project uses Webpack 5, you can opt into the Webpack 5 builder by installing the required dependencies (i.e., `@storybook/builder-webpack5`, `@storybook/manager-webpack5`) and update your Storybook configuration as follows: +Storybook's Webpack configuration is based on [Webpack 5](https://webpack.js.org/), allowing it to be extended to fit your project's needs. If you need to add a loader or a plugin, you can provide the `webpackFinal` configuration element in your [`.storybook/main.js|ts`](../configure/overview.md#configure-your-storybook-project) file. The configuration element should export a function that receives the baseline configuration as the first argument and Storybook's options object as the second argument. For example: -Once you are using Webpack 5, you can further opt into some features to optimize your build: +When Storybook starts, it automatically merges the configuration into its own. However, when providing the `webpackFinal` configuration element, you're responsible for merging the configuration yourself. We recommend that you handle the changes to the `config` object responsibly, preserving both the `entry` and `output` properties. -#### Lazy Compilation +#### Working with Webpack plugins -Storybook supports Webpack's experimental [lazy compilation](https://webpack.js.org/configuration/experiments/#experimentslazycompilation) feature, via the `lazyCompilation` builder flag: +Another way to customize your Storybook configuration is to add a custom plugin or loader to help with code optimization, asset management, or other tasks. Nevertheless, since Storybook relies on the `HtmlWebpackPlugin` to generate the preview page, we recommend that you append the changes to the `config.plugins` array rather than overwriting it. For example: -This feature applies in development mode, and will mean your Storybook will start up faster, at the cost of slightly slower browsing time when you change stories. +Additionally, when working with Webpack loaders that don't explicitly include specific file extensions (i.e., via the `test` property), you should `exclude` the `.ejs` file extension for that loader. -#### Filesystem Caching +### Import a custom Webpack configuration -Storybook supports Webpack's [filesystem caching](https://webpack.js.org/configuration/cache/#cachetype) feature, via the `fsCache` builder flag: +If you already have an existing Webpack configuration file that you need to reuse with Storybook, you can import it and merge it into the default configuration. For example: - - - -This feature will mean build output is cached between runs of Storybook, speeding up subsequent startup times. - -### Extending Storybook’s Webpack config - -To extend the above configuration, use the `webpackFinal` field of [`.storybook/main.js`](../configure/overview.md#configure-your-storybook-project). - -The value should export a `function`, which will receive the default config as its first argument. The second argument is an options object from Storybook, and this will have information about where config came from, whether we're in production or development mode, etc. - -For example, if you wanted to add [Sass](https://sass-lang.com/) support, you can adjust your configuration as such: - - - - -Storybook uses the config returned from the above function to render your components in Storybook's "preview" iframe. Note that Storybook has an entirely separate Webpack config for its UI (also referred to as the "manager"), so the customizations you make only apply to the rendering of your stories, i.e., you can completely replace `config.module.rules` if you want. +
+💡 Projects scaffolded based on generators may require that you import their specific Webpack configuration files. We suggest reading your generator's documentation for more information. -Nevertheless, edit `config` with care. Make sure to preserve the following config options: +
-- **entry** -- **output** +### Debug Webpack configuration -Furthermore, `config` requires the `HtmlWebpackplugin` to generate the preview page, so rather than overwriting `config.plugins` you should probably append to it (or overwrite it with care), see [the following issue](https://github.com/storybookjs/storybook/issues/6020) for examples on how to handle this: +If you intend to debug the Webpack configuration used by Storybook, you can use the Storybook CLI to help you. If you're running in [development mode](../api/cli-options.md#dev), you can use the following command: -Finally, if your custom Webpack config uses a loader that does not explicitly include specific file extensions via the `test` property, in that case, it is necessary to `exclude` the `.ejs` file extension from that loader. - -If you're using a non-standard Storybook config directory, you should put `main.js` there instead of `.storybook` and update the `include` path to ensure it resolves to your project root. - -### Using your existing config - -Suppose you have an existing Webpack config for your project and want to reuse this app's configuration. In that case, you can import your main Webpack config into Storybook's [`.storybook/main.js`](../configure/overview.md#configure-your-storybook-project) and merge both: - -The following code snippet shows how you can replace the loaders from Storybook with the ones from your app's `webpack.config.js`: +Additionally, if you're generating a [static build](../api/cli-options.md#build) of your Storybook, you can use the following command: -
+## What about Webpack 4 support? -💡 Projects initialized via generators (e.g, Vue CLI) may require that you import their own Webpack config file (i.e., /projectRoot/node_modules/@vue/cli-service/webpack.config.js) to use a certain feature with Storybook. For other generators, make sure to check the documentation for instructions. +Support for Webpack 4 has been removed and is no longer being maintained. If you're upgrading your Storybook, it will automatically use Webpack 5 and attempt to migrate your configuration. However, if you're working with a custom Webpack configuration, you may need to update it to work with Webpack 5. The migration process is necessary to ensure that your project runs smoothly with the latest version of Storybook. You can follow the instructions provided on the Webpack [website](https://webpack.js.org/migrate/5/) to update your configuration. -
+## Troubleshooting -### TypeScript Module Resolution +### TypeScript modules are not resolved within Storybook -When working with TypeScript projects, the default Webpack configuration may fail to resolve module aliases defined in your [`tsconfig` file](https://www.typescriptlang.org/tsconfig). To work around this issue you may use [`tsconfig-paths-webpack-plugin`](https://github.com/dividab/tsconfig-paths-webpack-plugin#tsconfig-paths-webpack-plugin) while [extending Storybook's Webpack config](#extending-storybooks-webpack-config) like: +Storybook's default Webpack configuration provides support for most project setups without the need for any additional configuration. Nevertheless, depending on your project configuration, or the framework of choice, you may run into issues with TypeScript modules not being resolved within Storybook when aliased from your [`tsconfig` file](https://www.typescriptlang.org/tsconfig). If you encounter this issue, you can use [`tsconfig-paths-webpack-plugin`](https://github.com/dividab/tsconfig-paths-webpack-plugin#tsconfig-paths-webpack-plugin) while [extending Storybook's Webpack config](#override-the-default-configuration) as follows: -
-💡 Learn more about Storybook's built-in TypeScript support or see this issue for more information. -
+### Pre-bundled assets do not show in the Storybook UI + +As Storybook relies on [esbuild](https://esbuild.github.io/) to build its internal manager, support for bundling assets with the `managerWebpack` will no longer have an impact on the Storybook UI. We recommend removing existing `managerWebpack` configuration elements from your Storybook configuration file and bundling assets other than images or CSS into JavaScript beforehand. #### Learn more about builders diff --git a/docs/configure/frameworks.md b/docs/configure/frameworks.md index c05f16210bdb..d130e27f54ef 100644 --- a/docs/configure/frameworks.md +++ b/docs/configure/frameworks.md @@ -39,7 +39,7 @@ Every modern web application has unique requirements and relies on various tools | Option | Description | Framework | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | | `nextConfigPath` | Sets the default path for the NextJS configuration file
`framework: { name: '@storybook/nextjs', options: { nextConfigPath: '../next.config.js'} }` | NextJS | -| `builder` | Configures [Webpack 5](../builders/webpack.md#webpack-5) builder options for NextJS
`core: { builder: { name:'webpack5', options: { lazyCompilation: true} }}` | NextJS | +| `builder` | Configures [Webpack 5](../builders/webpack.md) builder options for NextJS
`core: { builder: { name:'webpack5', options: { lazyCompilation: true} }}` | NextJS | | `fastRefresh` | Enables [fast refresh mode](https://www.npmjs.com/package/react-refresh) for React
`framework: { name: '@storybook/react-webpack5', options: { fastRefresh: false } }` | React | | `strictMode` | Enables React's [strict mode](https://reactjs.org/docs/strict-mode.html)
`framework: { name: '@storybook/react-webpack5', options: { strictMode: false } }` | React | | `legacyRootApi` | Requires React 18. Toggles support for React's [legacy root API](https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis)
`framework: { name: '@storybook/react-webpack5', options: { legacyRootApi: true } }` | React | diff --git a/docs/get-started/setup.md b/docs/get-started/setup.md index 78f02eb5070b..550b1f6e59df 100644 --- a/docs/get-started/setup.md +++ b/docs/get-started/setup.md @@ -107,7 +107,7 @@ If you are using CSS-in-JS, chances are your styles are working because they’r
@import CSS into components -Storybook allows you to import CSS files in your components directly. But in some cases you may need to [tweak its Webpack configuration](../builders/webpack.md#extendingstorybooks-webpack-config). Angular components require [a special import](../configure/styling-and-css.md#importing-css-files). +Storybook allows you to import CSS files in your components directly. But in some cases you may need to [tweak its Webpack configuration](../builders/webpack.md#override-the-default-configuration). Angular components require [a special import](../configure/styling-and-css.md#importing-css-files).
diff --git a/docs/sharing/storybook-composition.md b/docs/sharing/storybook-composition.md index d0331506b573..af4092edc2e6 100644 --- a/docs/sharing/storybook-composition.md +++ b/docs/sharing/storybook-composition.md @@ -68,7 +68,7 @@ You can also compose Storybooks based on the current development environment (e.
-💡 Similar to the other fields available in Storybook’s configuration file, the `refs` field can also be a function that accepts a config parameter containing Storybook’s configuration object. Check the [Webpack documentation](../builders/webpack.md#extending-storybooks-webpack-config) to learn more about it. +💡 Similar to the other fields available in Storybook’s configuration file, the `refs` field can also be a function that accepts a config parameter containing Storybook’s configuration object. Check the [Webpack documentation](../builders/webpack.md#override-the-default-configuration) to learn more about it.
diff --git a/docs/snippets/common/storybook-main-add-sass-config.js.mdx b/docs/snippets/common/storybook-main-add-sass-config.js.mdx index a193248f4c3a..abdf13c264ef 100644 --- a/docs/snippets/common/storybook-main-add-sass-config.js.mdx +++ b/docs/snippets/common/storybook-main-add-sass-config.js.mdx @@ -5,6 +5,12 @@ import * as path from 'path'; // Export a function. Accept the base config as the only param. export default { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], webpackFinal: async (config, { configType }) => { // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION' // You can change the configuration based on that. diff --git a/docs/snippets/common/storybook-main-add-sass-config.ts.mdx b/docs/snippets/common/storybook-main-add-sass-config.ts.mdx new file mode 100644 index 000000000000..099939c045f7 --- /dev/null +++ b/docs/snippets/common/storybook-main-add-sass-config.ts.mdx @@ -0,0 +1,35 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) +import type { StorybookConfig } from '@storybook/your-framework'; + +// your app's webpack.config.js +import custom from '../webpack.config.js'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + webpackFinal: async (config, { configType }) => { + // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION' + // You can change the configuration based on that. + // 'PRODUCTION' is used when building the static version of storybook. + + // Make whatever fine-grained changes you need + config.module.rules.push({ + test: /\.scss$/, + use: ['style-loader', 'css-loader', 'sass-loader'], + include: path.resolve(__dirname, '../'), + }); + + // Return the altered config + return config; + }, +}; + +export default config; +``` diff --git a/docs/snippets/common/storybook-main-simplified-config.js.mdx b/docs/snippets/common/storybook-main-simplified-config.js.mdx index 0063084b3b91..7c769e100b14 100644 --- a/docs/snippets/common/storybook-main-simplified-config.js.mdx +++ b/docs/snippets/common/storybook-main-simplified-config.js.mdx @@ -2,6 +2,12 @@ // .storybook/main.js export default { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], webpackFinal: async (config) => { config.plugins.push(...); return config; diff --git a/docs/snippets/common/storybook-main-simplified-config.ts.mdx b/docs/snippets/common/storybook-main-simplified-config.ts.mdx new file mode 100644 index 000000000000..04ede18a5e0b --- /dev/null +++ b/docs/snippets/common/storybook-main-simplified-config.ts.mdx @@ -0,0 +1,21 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + webpackFinal: async (config) => { + config.plugins.push(...); + return config; + }, +}; + +export default config; +``` diff --git a/docs/snippets/common/storybook-main-using-existing-config.js.mdx b/docs/snippets/common/storybook-main-using-existing-config.js.mdx index 9092f6a0b850..6f190418e0c0 100644 --- a/docs/snippets/common/storybook-main-using-existing-config.js.mdx +++ b/docs/snippets/common/storybook-main-using-existing-config.js.mdx @@ -1,10 +1,15 @@ ```js // .storybook/main.js -// your app's webpack.config.js -import custom from '../webpack.config.js'; +import custom from '../webpack.config.js'; // 👈 Custom Webpack configuration being imported. export default { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], webpackFinal: async (config) => { return { ...config, diff --git a/docs/snippets/common/storybook-main-using-existing-config.ts.mdx b/docs/snippets/common/storybook-main-using-existing-config.ts.mdx index edb13f5241c6..4271590758a2 100644 --- a/docs/snippets/common/storybook-main-using-existing-config.ts.mdx +++ b/docs/snippets/common/storybook-main-using-existing-config.ts.mdx @@ -4,10 +4,15 @@ // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) import type { StorybookConfig } from '@storybook/your-framework'; -// your app's webpack.config.js -import custom from '../webpack.config.js'; +import custom from '../webpack.config.js'; // 👈 Custom Webpack configuration being imported. const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], webpackFinal: async (config) => { return { ...config, diff --git a/docs/snippets/common/storybook-main-webpack-options.js.mdx b/docs/snippets/common/storybook-main-webpack-options.js.mdx new file mode 100644 index 000000000000..94c354b21042 --- /dev/null +++ b/docs/snippets/common/storybook-main-webpack-options.js.mdx @@ -0,0 +1,24 @@ +```js +// .storybook/main.js + +export default { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + features: { + storyStoreV7: false, + }, + core: { + builder: { + name: '@storybook/builder-webpack5', + options: { + fsCache: true, + lazyCompilation: true, + }, + }, + }, +}; +``` diff --git a/docs/snippets/common/storybook-main-webpack-options.ts.mdx b/docs/snippets/common/storybook-main-webpack-options.ts.mdx new file mode 100644 index 000000000000..6a5dd3e765d1 --- /dev/null +++ b/docs/snippets/common/storybook-main-webpack-options.ts.mdx @@ -0,0 +1,29 @@ +```ts +// .storybook/main.ts + +// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-webpack5) +import type { StorybookConfig } from '@storybook/your-framework'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + features: { + storyStoreV7: false, + }, + core: { + builder: { + name: '@storybook/builder-webpack5', + options: { + fsCache: true, + lazyCompilation: true, + }, + }, + }, +}; + +export default config; +```