mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-17 05:02:23 +08:00
Update @storybook/nextjs
README
- Add instructions for working around Next 13 components with data fetching - Updates for accuracy - Stylistic updates
This commit is contained in:
parent
d672182dc8
commit
7b287ec114
@ -14,12 +14,12 @@
|
|||||||
- [Remote Images](#remote-images)
|
- [Remote Images](#remote-images)
|
||||||
- [Optimization](#optimization)
|
- [Optimization](#optimization)
|
||||||
- [AVIF](#avif)
|
- [AVIF](#avif)
|
||||||
- [Next.js Navigation](#nextjs-navigation)
|
|
||||||
- [Next.js Routing](#nextjs-routing)
|
- [Next.js Routing](#nextjs-routing)
|
||||||
- [Overriding defaults](#overriding-defaults)
|
- [Overriding defaults](#overriding-defaults)
|
||||||
- [Global Defaults](#global-defaults)
|
- [Global Defaults](#global-defaults)
|
||||||
- [Default Router](#default-router)
|
- [Default Router](#default-router)
|
||||||
- [Actions Integration Caveats](#actions-integration-caveats)
|
- [Actions Integration Caveats](#actions-integration-caveats)
|
||||||
|
- [Next.js Navigation](#nextjs-navigation)
|
||||||
- [Sass/Scss](#sassscss)
|
- [Sass/Scss](#sassscss)
|
||||||
- [Css/Sass/Scss Modules](#csssassscss-modules)
|
- [Css/Sass/Scss Modules](#csssassscss-modules)
|
||||||
- [Styled JSX](#styled-jsx)
|
- [Styled JSX](#styled-jsx)
|
||||||
@ -30,7 +30,7 @@
|
|||||||
- [Typescript](#typescript)
|
- [Typescript](#typescript)
|
||||||
- [Notes for Yarn v2 and v3 users](#notes-for-yarn-v2-and-v3-users)
|
- [Notes for Yarn v2 and v3 users](#notes-for-yarn-v2-and-v3-users)
|
||||||
- [FAQ](#faq)
|
- [FAQ](#faq)
|
||||||
- [Stories for pages](#stories-for-pages)
|
- [Stories for pages](#stories-for-pages-components-which-fetch-data)
|
||||||
- [Statically imported images won't load](#statically-imported-images-wont-load)
|
- [Statically imported images won't load](#statically-imported-images-wont-load)
|
||||||
- [Module not found: Error: Can't resolve [package name]](#module-not-found-error-cant-resolve-package-name)
|
- [Module not found: Error: Can't resolve [package name]](#module-not-found-error-cant-resolve-package-name)
|
||||||
- [Acknowledgements](#acknowledgements)
|
- [Acknowledgements](#acknowledgements)
|
||||||
@ -71,29 +71,52 @@
|
|||||||
Follow the prompts after running this command in your Next.js project's root directory:
|
Follow the prompts after running this command in your Next.js project's root directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx storybook init
|
npx storybook@next init
|
||||||
```
|
```
|
||||||
|
|
||||||
[More on getting started with Storybook](https://storybook.js.org/docs/react/get-started/introduction)
|
[More on getting started with Storybook](https://storybook.js.org/docs/react/get-started/install)
|
||||||
|
|
||||||
### In a project with Storybook
|
### In a project with Storybook
|
||||||
|
|
||||||
Update your `main.js` to look something like this:
|
This framework is designed to work with Storybook 7. If you’re not already using v7, upgrade with this command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx storybook@next upgrade --prerelease
|
||||||
|
```
|
||||||
|
|
||||||
Install the framework:
|
Install the framework:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn install @storybook/nextjs
|
yarn install -D @storybook/nextjs@next
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Update your `main.js` to change the framework property:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// .storybook/main.js
|
// .storybook/main.js
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
// ...
|
||||||
framework: {
|
framework: {
|
||||||
name: '@storybook/nextjs',
|
// name: '@storybook/react-webpack5', // Remove this
|
||||||
options: {};
|
name: '@storybook/nextjs', // Add this
|
||||||
}
|
options: {},
|
||||||
}
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
If you were using Storybook plugins to integrate with Next.js, those are no longer necessary when using this framework and can be removed:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// .storybook/main.js
|
||||||
|
module.exports = {
|
||||||
|
// ...
|
||||||
|
addons: [
|
||||||
|
// ...
|
||||||
|
// These can both be removed
|
||||||
|
// 'storybook-addon-next',
|
||||||
|
// 'storybook-addon-next-router',
|
||||||
|
],
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
@ -109,14 +132,13 @@ For example:
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// other config ommited for brevity
|
// ...
|
||||||
framework: {
|
framework: {
|
||||||
name: '@storybook/nextjs',
|
name: '@storybook/nextjs',
|
||||||
options: {
|
options: {
|
||||||
nextConfigPath: path.resolve(__dirname, '../next.config.js'),
|
nextConfigPath: path.resolve(__dirname, '../next.config.js'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// ...
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -174,175 +196,15 @@ export default function Home() {
|
|||||||
|
|
||||||
This format is not supported by this framework yet. Feel free to [open up an issue](https://github.com/storybookjs/storybook/issues) if this is something you want to see.
|
This format is not supported by this framework yet. Feel free to [open up an issue](https://github.com/storybookjs/storybook/issues) if this is something you want to see.
|
||||||
|
|
||||||
### Next.js Navigation
|
|
||||||
|
|
||||||
Please note that [next/navigation](https://beta.nextjs.org/docs/upgrade-guide#step-5-migrating-routing-hooks) can only be used in components/pages of the `app` directory of Next.js v13 or higher.
|
|
||||||
|
|
||||||
#### Set `nextjs.appDirectory` to `true`
|
|
||||||
|
|
||||||
If your story imports components that use `next/navigation`, you need to set the parameter `nextjs.appDirectory` to `true` in your Story:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// SomeComponentThatUsesTheRouter.stories.js
|
|
||||||
import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
component: SomeComponentThatUsesTheNavigation,
|
|
||||||
};
|
|
||||||
|
|
||||||
// if you have the actions addon
|
|
||||||
// you can click the links and see the route change events there
|
|
||||||
export const Example = {
|
|
||||||
parameters: {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// .storybook/preview.js
|
|
||||||
|
|
||||||
export const parameters = {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The parameter `nextjs.appDirectory` defaults to `false` if not set.
|
|
||||||
|
|
||||||
#### Overriding defaults
|
|
||||||
|
|
||||||
Per-story overrides can be done by adding a `nextjs.navigation` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// SomeComponentThatUsesTheNavigation.stories.js
|
|
||||||
import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
component: SomeComponentThatUsesTheNavigation,
|
|
||||||
};
|
|
||||||
|
|
||||||
// if you have the actions addon
|
|
||||||
// you can click the links and see the route change events there
|
|
||||||
export const Example = {
|
|
||||||
parameters: {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
navigation: {
|
|
||||||
pathname: '/some-default-path',
|
|
||||||
query: {
|
|
||||||
foo: 'bar',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Global Defaults
|
|
||||||
|
|
||||||
Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// .storybook/preview.js
|
|
||||||
|
|
||||||
export const parameters = {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
navigation: {
|
|
||||||
pathname: '/some-default-path',
|
|
||||||
query: {
|
|
||||||
foo: 'bar',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Default Navigation Context
|
|
||||||
|
|
||||||
The default values on the stubbed navigation context are as follows:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const defaultNavigationContext = {
|
|
||||||
push(...args) {
|
|
||||||
action('nextNavigation.push')(...args);
|
|
||||||
},
|
|
||||||
replace(...args) {
|
|
||||||
action('nextNavigation.replace')(...args);
|
|
||||||
},
|
|
||||||
forward(...args) {
|
|
||||||
action('nextNavigation.forward')(...args);
|
|
||||||
},
|
|
||||||
back(...args) {
|
|
||||||
action('nextNavigation.back')(...args);
|
|
||||||
},
|
|
||||||
prefetch(...args) {
|
|
||||||
action('nextNavigation.prefetch')(...args);
|
|
||||||
},
|
|
||||||
refresh: () => {
|
|
||||||
action('nextNavigation.refresh')();
|
|
||||||
},
|
|
||||||
pathname: '/',
|
|
||||||
query: {},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Actions Integration Caveats
|
|
||||||
|
|
||||||
If you override a function, you lose the automatic action tab integration and have to build it out yourself.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// .storybook/preview.js
|
|
||||||
|
|
||||||
export const parameters = {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
navigation: {
|
|
||||||
push() {
|
|
||||||
// The default implementation that logs the action into the action tab is lost
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package):
|
|
||||||
|
|
||||||
```js
|
|
||||||
// .storybook/preview.js
|
|
||||||
import { action } from '@storybook/addon-actions';
|
|
||||||
|
|
||||||
export const parameters = {
|
|
||||||
nextjs: {
|
|
||||||
appDirectory: true,
|
|
||||||
navigation: {
|
|
||||||
push(...args) {
|
|
||||||
// custom logic can go here
|
|
||||||
// this logs to the actions tab
|
|
||||||
action('nextNavigation.push')(...args);
|
|
||||||
// return whatever you want here
|
|
||||||
return Promise.resolve(true);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Next.js Routing
|
### Next.js Routing
|
||||||
|
|
||||||
[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the [Storybook actions tab](https://storybook.js.org/docs/react/essentials/actions) if you have the actions addon.
|
[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the Actions ctions panel if you have the [Storybook actions addon](https://storybook.js.org/docs/react/essentials/actions).
|
||||||
|
|
||||||
You should only use `next/router` in the `pages` directory of Next.js v13 or higher. In the `app` directory, it is necessary to use `next/navigation`.
|
> When using Next.js 13+, you should only use `next/router` in the `pages` directory. In the `app` directory, it is necessary to use `next/navigation`.
|
||||||
|
|
||||||
#### Overriding defaults
|
#### Overriding defaults
|
||||||
|
|
||||||
Per-story overrides can be done by adding a `nextRouter` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router.
|
Per-story overrides can be done by adding a `nextjs.router` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// SomeComponentThatUsesTheRouter.stories.js
|
// SomeComponentThatUsesTheRouter.stories.js
|
||||||
@ -352,16 +214,16 @@ export default {
|
|||||||
component: SomeComponentThatUsesTheRouter,
|
component: SomeComponentThatUsesTheRouter,
|
||||||
};
|
};
|
||||||
|
|
||||||
// if you have the actions addon
|
// If you have the actions addon,
|
||||||
// you can click the links and see the route change events there
|
// you can interact with the links and see the route change events there
|
||||||
export const Example = {
|
export const Example = {
|
||||||
parameters: {
|
parameters: {
|
||||||
nextjs: {
|
nextjs: {
|
||||||
router: {
|
router: {
|
||||||
path: '/profile/[id]',
|
path: '/profile/[id]',
|
||||||
asPath: '/profile/ryanclementshax',
|
asPath: '/profile/1',
|
||||||
query: {
|
query: {
|
||||||
id: 'ryanclementshax',
|
id: '1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -444,7 +306,7 @@ const defaultRouter = {
|
|||||||
|
|
||||||
#### Actions Integration Caveats
|
#### Actions Integration Caveats
|
||||||
|
|
||||||
If you override a function, you lose the automatic action tab integration and have to build it out yourself.
|
If you override a function, you lose the automatic actions integration and have to build it out yourself.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// .storybook/preview.js
|
// .storybook/preview.js
|
||||||
@ -453,7 +315,7 @@ export const parameters = {
|
|||||||
nextjs: {
|
nextjs: {
|
||||||
router: {
|
router: {
|
||||||
push() {
|
push() {
|
||||||
// The default implementation that logs the action into the action tab is lost
|
// The default implementation that logs the action into the Actions panel is lost
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -470,10 +332,165 @@ export const parameters = {
|
|||||||
nextjs: {
|
nextjs: {
|
||||||
router: {
|
router: {
|
||||||
push(...args) {
|
push(...args) {
|
||||||
// custom logic can go here
|
// Custom logic can go here
|
||||||
// this logs to the actions tab
|
// This logs to the Actions panel
|
||||||
action('nextRouter.push')(...args);
|
action('nextRouter.push')(...args);
|
||||||
// return whatever you want here
|
// Return whatever you want here
|
||||||
|
return Promise.resolve(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Next.js Navigation
|
||||||
|
|
||||||
|
> Please note that [next/navigation](https://beta.nextjs.org/docs/upgrade-guide#step-5-migrating-routing-hooks) can only be used in components/pages in the `app` directory of Next.js 13+.
|
||||||
|
|
||||||
|
#### Set `nextjs.appDirectory` to `true`
|
||||||
|
|
||||||
|
If your story imports components that use `next/navigation`, you need to set the parameter `nextjs.appDirectory` to `true` in your Story:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// SomeComponentThatUsesTheRouter.stories.js
|
||||||
|
import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: SomeComponentThatUsesTheNavigation,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Example = {
|
||||||
|
parameters: {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
If your Next.js project uses the `app` directory for every page (in other words, it does not have a `pages` directory), you can set the parameter `nextjs.appDirectory` to `true` in the [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) file to apply it to all stories.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// .storybook/preview.js
|
||||||
|
|
||||||
|
export const parameters = {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The parameter `nextjs.appDirectory` defaults to `false` if not set.
|
||||||
|
|
||||||
|
#### Overriding defaults
|
||||||
|
|
||||||
|
Per-story overrides can be done by adding a `nextjs.navigation` property onto the story [parameters](https://storybook.js.org/docs/react/writing-stories/parameters). The framework will shallowly merge whatever you put here into the router.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// SomeComponentThatUsesTheNavigation.stories.js
|
||||||
|
import SomeComponentThatUsesTheNavigation from './SomeComponentThatUsesTheNavigation';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: SomeComponentThatUsesTheNavigation,
|
||||||
|
};
|
||||||
|
|
||||||
|
// If you have the actions addon,
|
||||||
|
// you can interact with the links and see the route change events there
|
||||||
|
export const Example = {
|
||||||
|
parameters: {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
navigation: {
|
||||||
|
pathname: '/profile',
|
||||||
|
query: {
|
||||||
|
user: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Global Defaults
|
||||||
|
|
||||||
|
Global defaults can be set in [preview.js](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and will be shallowly merged with the default router.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// .storybook/preview.js
|
||||||
|
|
||||||
|
export const parameters = {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
navigation: {
|
||||||
|
pathname: '/some-default-path',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Default Navigation Context
|
||||||
|
|
||||||
|
The default values on the stubbed navigation context are as follows:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const defaultNavigationContext = {
|
||||||
|
push(...args) {
|
||||||
|
action('nextNavigation.push')(...args);
|
||||||
|
},
|
||||||
|
replace(...args) {
|
||||||
|
action('nextNavigation.replace')(...args);
|
||||||
|
},
|
||||||
|
forward(...args) {
|
||||||
|
action('nextNavigation.forward')(...args);
|
||||||
|
},
|
||||||
|
back(...args) {
|
||||||
|
action('nextNavigation.back')(...args);
|
||||||
|
},
|
||||||
|
prefetch(...args) {
|
||||||
|
action('nextNavigation.prefetch')(...args);
|
||||||
|
},
|
||||||
|
refresh: () => {
|
||||||
|
action('nextNavigation.refresh')();
|
||||||
|
},
|
||||||
|
pathname: '/',
|
||||||
|
query: {},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Actions Integration Caveats
|
||||||
|
|
||||||
|
If you override a function, you lose the automatic action tab integration and have to build it out yourself.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// .storybook/preview.js
|
||||||
|
|
||||||
|
export const parameters = {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
navigation: {
|
||||||
|
push() {
|
||||||
|
// The default implementation that logs the action into the Actions panel is lost
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Doing this yourself looks something like this (make sure you install the `@storybook/addon-actions` package):
|
||||||
|
|
||||||
|
```js
|
||||||
|
// .storybook/preview.js
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
|
export const parameters = {
|
||||||
|
nextjs: {
|
||||||
|
appDirectory: true,
|
||||||
|
navigation: {
|
||||||
|
push(...args) {
|
||||||
|
// Custom logic can go here
|
||||||
|
// This logs to the Actions panel
|
||||||
|
action('nextNavigation.push')(...args);
|
||||||
|
// Return whatever you want here
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -496,7 +513,7 @@ This will automatically include any of your [custom sass configurations](https:/
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// any options here are included in sass compilation for your stories
|
// Any options here are included in Sass compilation for your stories
|
||||||
sassOptions: {
|
sassOptions: {
|
||||||
includePaths: [path.join(__dirname, 'styles')],
|
includePaths: [path.join(__dirname, 'styles')],
|
||||||
},
|
},
|
||||||
@ -508,7 +525,7 @@ module.exports = {
|
|||||||
[css modules](https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css) work as expected.
|
[css modules](https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css) work as expected.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// this import works just fine in Storybook now
|
// This import works just fine in Storybook now
|
||||||
import styles from './Button.module.css';
|
import styles from './Button.module.css';
|
||||||
// sass/scss is also supported
|
// sass/scss is also supported
|
||||||
// import styles from './Button.module.scss'
|
// import styles from './Button.module.scss'
|
||||||
@ -603,10 +620,11 @@ export default function HomePage() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
Also OK for global styles in `preview.js`!
|
||||||
// preview.js
|
|
||||||
|
```js
|
||||||
|
// .storybook/preview.js
|
||||||
|
|
||||||
// Also ok in preview.js!
|
|
||||||
import 'styles/globals.scss';
|
import 'styles/globals.scss';
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
@ -659,14 +677,14 @@ Below is an example of how to add svgr support to Storybook with this framework.
|
|||||||
```js
|
```js
|
||||||
// .storybook/main.js
|
// .storybook/main.js
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// other config omitted for brevity
|
// ...
|
||||||
webpackFinal: async (config) => {
|
webpackFinal: async (config) => {
|
||||||
// this modifies the existing image rule to exclude .svg files
|
// This modifies the existing image rule to exclude .svg files
|
||||||
// since you want to handle those files with @svgr/webpack
|
// since you want to handle those files with @svgr/webpack
|
||||||
const imageRule = config.module.rules.find((rule) => rule.test.test('.svg'));
|
const imageRule = config.module.rules.find((rule) => rule.test.test('.svg'));
|
||||||
imageRule.exclude = /\.svg$/;
|
imageRule.exclude = /\.svg$/;
|
||||||
|
|
||||||
// configure .svg files to be loaded with @svgr/webpack
|
// Configure .svg files to be loaded with @svgr/webpack
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
use: ['@svgr/webpack'],
|
use: ['@svgr/webpack'],
|
||||||
@ -703,9 +721,9 @@ This is because those versions of Yarn have different package resolution rules t
|
|||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
#### Stories for pages
|
#### Stories for pages/components which fetch data
|
||||||
|
|
||||||
Next.js page files can contain imports to modules meant to run in a node environment (for use in data fetching functions). If you import from a Next.js page file containing those node module imports in your stories, your Storybook's Webpack will crash because those modules will not run in a browser. To get around this, you can extract the component in your page file into a separate file and import that component in your stories. Or, if that's not feasible for some reason, you can [polyfill those modules](https://webpack.js.org/configuration/node/) in your Storybook's [`webpackFinal` configuration](https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config).
|
Next.js page files can contain imports to modules meant to run in a node environment (for use in data fetching functions). If you import from a Next.js page file containing those node module imports in your stories, your Storybook's Webpack will crash because those modules will not run in a browser. To get around this, you can extract the component in your page file into a separate file and import that pure component in your stories. Or, if that's not feasible for some reason, you can [polyfill those modules](https://webpack.js.org/configuration/node/) in your Storybook's [`webpackFinal` configuration](https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config).
|
||||||
|
|
||||||
**Before**
|
**Before**
|
||||||
|
|
||||||
@ -713,9 +731,10 @@ Next.js page files can contain imports to modules meant to run in a node environ
|
|||||||
// ./pages/my-page.jsx
|
// ./pages/my-page.jsx
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
export default MyPage = (props) => (
|
// Using this component in your stories will break the Storybook build
|
||||||
// ...
|
export default function Page(props) {
|
||||||
);
|
return; // ...
|
||||||
|
}
|
||||||
|
|
||||||
export const getStaticProps = async () => {
|
export const getStaticProps = async () => {
|
||||||
// Logic that uses `fs`
|
// Logic that uses `fs`
|
||||||
@ -728,15 +747,57 @@ export const getStaticProps = async () => {
|
|||||||
// ./pages/my-page.jsx
|
// ./pages/my-page.jsx
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
|
// Use this pure component in your stories instead
|
||||||
import MyPage from 'components/MyPage';
|
import MyPage from 'components/MyPage';
|
||||||
|
|
||||||
export default MyPage;
|
export default function Page(props) {
|
||||||
|
return <MyPage {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
export const getStaticProps = async () => {
|
export const getStaticProps = async () => {
|
||||||
// Logic that uses `fs`
|
// Logic that uses `fs`
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Starting with Next.js 13, you can also fetch data directly within server components in the `app` directory. This does not (currently) work within Storybook for similar reasons as above. It can be worked around similarly as well, by extracting a pure component to a separate file and importing that component in your stories.
|
||||||
|
|
||||||
|
**Before**
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// ./app/my-page/index.jsx
|
||||||
|
async function getData() {
|
||||||
|
const res = await fetch(...);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using this component in your stories will break the Storybook build
|
||||||
|
export default async function Page() {
|
||||||
|
const data = await getData();
|
||||||
|
|
||||||
|
return // ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// ./app/my-page/index.jsx
|
||||||
|
|
||||||
|
// Use this component in your stories
|
||||||
|
import MyPage from './components/MyPage';
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
const res = await fetch(...);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
const data = await getData();
|
||||||
|
|
||||||
|
return <MyPage {...data} />;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Statically imported images won't load
|
#### Statically imported images won't load
|
||||||
|
|
||||||
Make sure you are treating image imports the same way you treat them when using `next/image` in normal development.
|
Make sure you are treating image imports the same way you treat them when using `next/image` in normal development.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user