mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-31 05:03:21 +08:00
239 lines
7.9 KiB
Markdown
239 lines
7.9 KiB
Markdown
---
|
|
title: 'Write a preset addon'
|
|
---
|
|
|
|
[Storybook preset addons](./addon-types.md#preset-addons) are grouped collections of `babel`, `webpack`, and `addons` configurations that support specific use cases in Storybook, such as TypeScript or MDX support.
|
|
|
|
This doc covers the [presets API](#presets-api) and how to use the presets mechanism for [advanced configuration](#advanced-configuration).
|
|
|
|
## Presets API
|
|
|
|
A preset is a set of hooks that are called by Storybook on initialization and can override configurations for `babel`, `webpack`, `addons`, and `entries`.
|
|
|
|
Each configuration has a similar signature, accepting a base configuration object and options, as in this Webpack example:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-webpack-preset-config.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
### Babel
|
|
|
|
The babel functions `babel` and `babelDefault` all configure babel in different ways.
|
|
|
|
All functions take a [Babel configuration object](https://babeljs.io/docs/en/configuration) as their argument and can modify it or return a new object.
|
|
|
|
For example, Storybook's Mihtril support uses plugins internally and here's how it configures babel:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-babel-configuration-example.ts.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
- `babel` is applied to the preview config, after it has been initialized by storybook
|
|
- `babelDefault` is applied to the preview config before any user presets have been applied
|
|
|
|
### Webpack
|
|
|
|
The Webpack functions `webpack`, `webpackFinal`, and `managerWebpack` configure Webpack.
|
|
|
|
All functions take a [webpack4 configuration object](https://webpack.js.org/configuration/).
|
|
|
|
For example, here is how Storybook automatically adopts `create-react-app`'s configuration if it's installed, where `applyCRAWebpackConfig` is a set of smart heuristics for modifying the input config.
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-webpackfinal-example.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
- `webpack` is applied to the preview config after it has been initialized by Storybook
|
|
- `webpackFinal` is applied to the preview config after all user presets have been applied
|
|
- `managerWebpack` is applied to the manager config
|
|
|
|
As of Storybook 6.3, Storybook can run with either `webpack4` or `webpack5` builder. If your addon needs to know which version of Webpack it's running inside, the version and the actual Webpack instance itself are both available inside your preset:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-versioned-webpack.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
### Manager entries
|
|
|
|
The addon config `managerEntries` allows you to add addons to Storybook from within a preset. For addons that require custom Webpack/Babel configuration, it is easier to install the preset, and it will take care of everything.
|
|
|
|
For example, the Storysource preset contains the following code:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-storysource-manager-entries.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
This is equivalent to [registering the addon manually](../get-started/browse-stories.md#addons) in [`main.js`](../configure/overview.md#configure-story-rendering):
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-use-manager-entries.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
### Preview entries
|
|
|
|
The addon `config` function allows you to add extra preview configuration from within a preset, for example to add parameters or decorators from an addon.
|
|
|
|
For example, the Backgrounds preset contains the following code:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-backgrounds-preset-config.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
Which in turn invokes:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-backgrounds-addon-default-params.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
This is equivalent to exporting the `backgrounds` parameter manually in `main.js`.
|
|
|
|
### Addons
|
|
|
|
For users, the name `managerEntries` might be a bit too technical, so instead both users and preset-authors can simply use the `addons` property:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-register-storysource-example.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
The array of values can support both references to other presets and addons that should be included into the manager.
|
|
|
|
Storybook will automatically detect whether a reference to an addon is a preset or a manager entry by checking if the package contains a `./preset.js` or `./register.js` (manager entry), falling back to preset if it is unsure.
|
|
|
|
If this heuristic is incorrect for an addon you are using, you can explicitly opt-in to an entry being a manager entry using the `managerEntries` key.
|
|
|
|
Here's what it looks when combining presets and manager entries in the `addons` property:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-register-presets-managerentry.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
### Entries
|
|
|
|
Entries are the place to register entry points for the preview. For example, it could be used to make a basic configure-storybook preset that loads all the `*.stories.js` files into SB, instead of forcing people to copy-paste the same thing everywhere.
|
|
|
|
## 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.
|
|
|
|
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.
|
|
|
|
If it doesn't exist yet, create a file `.storybook/main.js`:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-advanced-config-example.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
### Preview/Manager templates
|
|
|
|
It's also possible to programmatically modify the preview head/body HTML using a preset, similar to the way `preview-head.html`/`preview-body.html` can be used to [configure story rendering](../configure/story-rendering.md). The `previewHead` and `previewBody` functions accept a string, which is the existing head/body, and return a modified string.
|
|
|
|
For example, the following snippet adds a style tag to the preview head programmatically:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-preview-head.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
Similarly, the `managerHead` can be used to modify the surrounding "manager" UI, analogous to `manager-head.html`.
|
|
|
|
Finally, the preview's main page _template_ can also be overridden using the `previewMainTemplate`, which should return a reference to a file containing an `.ejs` template that gets interpolated with some environment variables. For an example, see the [Storybook's default template](https://github.com/storybookjs/storybook/blob/next/code/lib/core-common/templates/preview.ejs).
|
|
|
|
## Sharing advanced configuration
|
|
|
|
Change your `main.js` file to:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-main-import-preset-config.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
and extract the configuration to a new file `./storybook/my-preset.js`:
|
|
|
|
<!-- prettier-ignore-start -->
|
|
|
|
<CodeSnippets
|
|
paths={[
|
|
'common/storybook-preset-full-config-object.js.mdx',
|
|
]}
|
|
/>
|
|
|
|
<!-- prettier-ignore-end -->
|
|
|
|
Place your `my-preset.js` file wherever you want, if you want to share it far and wide you'll want to make it its own package.
|