Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React: Refactor RSC out of Next #25591

Merged
merged 5 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- [Next.js](#nextjs)
- [Require Next.js 13.5 and up](#require-nextjs-135-and-up)
- [Automatic SWC mode detection](#automatic-swc-mode-detection)
- [RSC config moved to React renderer](#rsc-config-moved-to-react-renderer)
- [Angular](#angular)
- [Require Angular 15 and up](#require-angular-15-and-up)
- [Svelte](#svelte)
Expand Down Expand Up @@ -66,17 +67,17 @@
- [`createChannel` from `@storybook/postmessage` and `@storybook/channel-websocket`](#createchannel-from-storybookpostmessage-and-storybookchannel-websocket)
- [StoryStore and methods deprecated](#storystore-and-methods-deprecated)
- [From version 7.5.0 to 7.6.0](#from-version-750-to-760)
- [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated)
- [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
- [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated)
- [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop)
- [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react)
- [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated)
- [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
- [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated)
- [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop)
- [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react)
- [From version 7.4.0 to 7.5.0](#from-version-740-to-750)
- [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated)
- [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers)
- [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated)
- [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers)
- [From version 7.0.0 to 7.2.0](#from-version-700-to-720)
- [Addon API is more type-strict](#addon-api-is-more-type-strict)
- [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated)
- [Addon API is more type-strict](#addon-api-is-more-type-strict)
- [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated)
- [From version 6.5.x to 7.0.0](#from-version-65x-to-700)
- [7.0 breaking changes](#70-breaking-changes)
- [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below)
Expand Down Expand Up @@ -728,6 +729,12 @@ Similar to how Next.js detects if SWC should be used, Storybook will follow more
- If you use Next.js 14 or higher and you don't have a .babelrc file, Storybook will use SWC to transpile your code.
- Even if you have a .babelrc file, Storybook will still use SWC to transpile your code if you set the experimental `experimental.forceSwcTransforms` flag to `true` in your `next.config.js`.

##### RSC config moved to React renderer

Storybook 7.6 introduced a new feature flag, `experimentalNextRSC`, to enable React Server Components in a Next.js project. It also introduced a parameter `nextjs.rsc` to selectively disable it on particular components or stories.

These flags have been renamed to `experimentalRSC` and `react.rsc`, respectively. This is a breaking change to accommodate RSC support in other, non-Next.js frameworks. For now, `@storybook/nextjs` is the only framework that supports it, and does so experimentally.

#### Angular

##### Require Angular 15 and up
Expand Down
4 changes: 2 additions & 2 deletions code/frameworks/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -907,13 +907,13 @@ Storybook handles most [Typescript](https://www.typescriptlang.org/) configurati

If your app uses [React Server Components (RSC)](https://nextjs.org/docs/app/building-your-application/rendering/server-components), Storybook can render them in stories in the browser.

To enable this set the `experimentalNextRSC` feature flag in your `.storybook/main.js` config:
To enable this set the `experimentalRSC` feature flag in your `.storybook/main.js` config:

```js
// main.js
export default {
features: {
experimentalNextRSC: true,
experimentalRSC: true,
},
};
```
Expand Down
2 changes: 0 additions & 2 deletions code/frameworks/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"import": "./dist/font/webpack/loader/storybook-nextjs-font-loader.mjs"
},
"./dist/preview.mjs": "./dist/preview.mjs",
"./dist/rsc/preview.mjs": "./dist/rsc/preview.mjs",
"./next-image-loader-stub.js": {
"types": "./dist/next-image-loader-stub.d.ts",
"require": "./dist/next-image-loader-stub.js",
Expand Down Expand Up @@ -164,7 +163,6 @@
"./src/images/next-legacy-image.tsx",
"./src/images/next-image.tsx",
"./src/font/webpack/loader/storybook-nextjs-font-loader.ts",
"./src/rsc/preview.tsx",
"./src/rsc/server-only.ts",
"./src/swc/next-swc-loader-patch.ts"
],
Expand Down
5 changes: 1 addition & 4 deletions code/frameworks/nextjs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ export const previewAnnotations: PresetProperty<'previewAnnotations'> = (
) => {
const nextDir = dirname(require.resolve('@storybook/nextjs/package.json'));
const result = [...entry, join(nextDir, 'dist/preview.mjs')];
if (features?.experimentalNextRSC) {
result.unshift(join(nextDir, 'dist/rsc/preview.mjs'));
}
return result;
};

Expand Down Expand Up @@ -170,7 +167,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (baseConfig,
configureFastRefresh(baseConfig);
}

if (options.features?.experimentalNextRSC) {
if (options.features?.experimentalRSC) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this still be in this file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It controls a webpack configuration. Where would you imagine it living?

configureRSC(baseConfig);
}

Expand Down
14 changes: 0 additions & 14 deletions code/frameworks/nextjs/src/rsc/decorator.tsx

This file was deleted.

10 changes: 0 additions & 10 deletions code/frameworks/nextjs/src/rsc/preview.tsx

This file was deleted.

8 changes: 4 additions & 4 deletions code/lib/cli/src/sandbox-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const baseTemplates = {
},
modifications: {
mainConfig: {
features: { experimentalNextRSC: true },
features: { experimentalRSC: true },
},
extraDependencies: ['server-only'],
},
Expand All @@ -142,7 +142,7 @@ const baseTemplates = {
},
modifications: {
mainConfig: {
features: { experimentalNextRSC: true },
features: { experimentalRSC: true },
},
extraDependencies: ['server-only'],
},
Expand All @@ -159,7 +159,7 @@ const baseTemplates = {
},
modifications: {
mainConfig: {
features: { experimentalNextRSC: true },
features: { experimentalRSC: true },
},
extraDependencies: ['server-only'],
},
Expand All @@ -176,7 +176,7 @@ const baseTemplates = {
},
modifications: {
mainConfig: {
features: { experimentalNextRSC: true },
features: { experimentalRSC: true },
},
extraDependencies: ['server-only'],
},
Expand Down
4 changes: 2 additions & 2 deletions code/lib/types/src/modules/core-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,9 @@ export interface StorybookConfigRaw {
disallowImplicitActionsInRenderV8?: boolean;

/**
* Enable asynchronous component rendering in NextJS framework
* Enable asynchronous component rendering in React renderer
*/
experimentalNextRSC?: boolean;
experimentalRSC?: boolean;
};

build?: TestBuildConfig;
Expand Down
6 changes: 5 additions & 1 deletion code/renderers/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./dist/entry-preview-rsc.mjs": "./dist/entry-preview-rsc.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
Expand Down Expand Up @@ -64,13 +65,15 @@
"lodash": "^4.17.21",
"prop-types": "^15.7.2",
"react-element-to-jsx-string": "^15.0.0",
"semver": "^7.3.7",
"ts-dedent": "^2.0.0",
"type-fest": "~2.19",
"util-deprecate": "^1.0.2"
},
"devDependencies": {
"@storybook/test": "workspace:*",
"@types/babel-plugin-react-docgen": "^4",
"@types/semver": "^7.3.4",
"@types/util-deprecate": "^1.0.0",
"babel-plugin-react-docgen": "^4.2.1",
"expect-type": "^0.15.0",
Expand All @@ -97,7 +100,8 @@
"./src/index.ts",
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
"./src/entry-preview-docs.ts",
"./src/entry-preview-rsc.tsx"
],
"platform": "browser"
},
Expand Down
31 changes: 31 additions & 0 deletions code/renderers/react/src/entry-preview-rsc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react';
import semver from 'semver';
import type { Addon_DecoratorFunction } from '@storybook/types';
import type { StoryContext } from './types';

export const ServerComponentDecorator = (
Story: React.FC,
{ parameters }: StoryContext
): React.ReactNode => {
if (!parameters?.react?.rsc) return <Story />;

const major = semver.major(React.version);
const minor = semver.minor(React.version);
if (major < 18 || (major === 18 && minor < 3)) {
throw new Error('React Server Components require React >= 18.3');
}

return (
<React.Suspense>
<Story />
</React.Suspense>
);
};

export const decorators: Addon_DecoratorFunction<any>[] = [ServerComponentDecorator];

export const parameters = {
react: {
rsc: true,
},
};
3 changes: 2 additions & 1 deletion code/renderers/react/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : [])
.concat(FEATURES?.experimentalRSC ? [join(__dirname, 'entry-preview-rsc.mjs')] : []);
};

/**
Expand Down
1 change: 1 addition & 0 deletions code/renderers/react/src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
declare var STORYBOOK_ENV: 'react';
declare var FRAMEWORK_OPTIONS: any;
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;
declare var FEATURES: import('@storybook/types').StorybookConfigRaw['features'];
2 changes: 2 additions & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6346,6 +6346,7 @@ __metadata:
"@types/escodegen": "npm:^0.0.6"
"@types/estree": "npm:^0.0.51"
"@types/node": "npm:^18.0.0"
"@types/semver": "npm:^7.3.4"
"@types/util-deprecate": "npm:^1.0.0"
acorn: "npm:^7.4.1"
acorn-jsx: "npm:^5.3.1"
Expand All @@ -6358,6 +6359,7 @@ __metadata:
prop-types: "npm:^15.7.2"
react-element-to-jsx-string: "npm:^15.0.0"
require-from-string: "npm:^2.0.2"
semver: "npm:^7.3.7"
ts-dedent: "npm:^2.0.0"
type-fest: "npm:~2.19"
util-deprecate: "npm:^1.0.2"
Expand Down