Skip to content

[heft-storybook-plugin] feat: storybook v8 support #4971

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

Merged
merged 5 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/heft-storybook-plugin",
"comment": "Add support for Storybook v8",
"type": "minor"
}
],
"packageName": "@rushstack/heft-storybook-plugin"
}
5 changes: 5 additions & 0 deletions heft-plugins/heft-storybook-plugin/heft-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
"longName": "--storybook",
"description": "(EXPERIMENTAL) Used by the \"@rushstack/heft-storybook-plugin\" package to launch Storybook.",
"parameterKind": "flag"
},
{
"longName": "--storybook-test",
"description": "Executes a stripped down build-storybook for testing purposes.",
"parameterKind": "flag"
}
]
}
Expand Down
46 changes: 45 additions & 1 deletion heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ enum StorybookBuildMode {
* Storybook CLI versions
*/
enum StorybookCliVersion {
STORYBOOK6 = 'storybook6',
STORYBOOK7 = 'storybook7',
STORYBOOK6 = 'storybook6'
STORYBOOK8 = 'storybook8'
}

/**
Expand Down Expand Up @@ -179,13 +180,23 @@ const DEFAULT_STORYBOOK_CLI_CONFIG: Record<StorybookCliVersion, IStorybookCliCal
watch: ['sb', 'dev'],
build: ['sb', 'build']
}
},
[StorybookCliVersion.STORYBOOK8]: {
packageName: 'storybook',
command: {
watch: ['sb', 'dev'],
build: ['sb', 'build']
}
}
};

const STORYBOOK_TEST_FLAG_NAME: '--storybook-test' = '--storybook-test';

/** @public */
export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPluginOptions> {
private _logger!: IScopedLogger;
private _isServeMode: boolean = false;
private _isTestMode: boolean = false;

/**
* Generate typings for Sass files before TypeScript compilation.
Expand All @@ -198,6 +209,8 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
this._logger = taskSession.logger;
const storybookParameter: CommandLineFlagParameter =
taskSession.parameters.getFlagParameter('--storybook');
const storybookTestParameter: CommandLineFlagParameter =
taskSession.parameters.getFlagParameter(STORYBOOK_TEST_FLAG_NAME);

const parseResult: IParsedPackageNameOrError = PackageName.tryParse(options.storykitPackageName);
if (parseResult.error) {
Expand All @@ -208,6 +221,10 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
);
}

if (storybookTestParameter.value) {
this._isTestMode = true;
}

// Only tap if the --storybook flag is present.
if (storybookParameter.value) {
const configureWebpackTap: () => Promise<false> = async () => {
Expand Down Expand Up @@ -267,6 +284,19 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
? StorybookBuildMode.WATCH
: StorybookBuildMode.BUILD;

if (buildMode === StorybookBuildMode.WATCH && this._isTestMode) {
throw new Error(`The ${STORYBOOK_TEST_FLAG_NAME} flag is not supported in watch mode`);
}
if (
this._isTestMode &&
(storybookCliVersion === StorybookCliVersion.STORYBOOK6 ||
storybookCliVersion === StorybookCliVersion.STORYBOOK7)
) {
throw new Error(
`The ${STORYBOOK_TEST_FLAG_NAME} flag is only supported in Storybook version 8 and above.`
);
}

this._logger.terminal.writeVerboseLine(`Probing for "${storykitPackageName}"`);
// Example: "/path/to/my-project/node_modules/my-storykit"
let storykitFolderPath: string;
Expand Down Expand Up @@ -408,6 +438,9 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
if (!verbose) {
storybookArgs.push('--quiet');
}
if (this._isTestMode) {
storybookArgs.push('--test');
}

if (this._isServeMode) {
// Instantiate storybook runner synchronously for incremental builds
Expand Down Expand Up @@ -490,6 +523,17 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
const originalArgv: string[] = process.argv;
const node: string = originalArgv[0];
process.argv = [node, command, ...args];
// npm_config_user_agent is used by Storybook to determine the package manager
// in a Rush monorepo it can't determine it automatically so it raises a benign error
// Storybook failed to check addon compatibility Error: Unable to find a usable package manager within NPM, PNPM, Yarn and Yarn 2
// hardcode it to NPM to suppress the error
//
// This only happens for dev server mode, not for build mode, so does not need to be in _invokeAsSubprocessAsync
//
// Storing the original env and restoring it like happens with argv does not seem to work
// At the time when storybook checks env.npm_config_user_agent it has been reset to undefined
// eslint-disable-next-line @typescript-eslint/naming-convention
process.env.npm_config_user_agent = 'npm';

// invoke command synchronously
require(command);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"cliCallingConvention": {
"title": "Specifies the calling convention of the storybook CLI based on the storybook version.",
"description": "Specify how the Storybook CLI should be invoked. Possible values: \"storybook6\" or \"storybook7\", defaults to \"storybook7\".",
"enum": ["storybook6", "storybook7"]
"enum": ["storybook6", "storybook7", "storybook8"]
},
"cliPackageName": {
"title": "The NPM package that Heft should use to launch the Storybook toolchain.",
Expand Down
Loading