Skip to content
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 10.2.5

- Angular: fix --loglevel options in docs and descriptions - [#33726](https://github.com/storybookjs/storybook/pull/33726), thanks @theRuslan!
- Builder-Vite: Add plugin to enforce Storybook's output directory in Vite build configuration - [#33740](https://github.com/storybookjs/storybook/pull/33740), thanks @valentinpalkovic!
- Core: Invalidate cache on Storybook version upgrade - [#33717](https://github.com/storybookjs/storybook/pull/33717), thanks @copilot-swe-agent!

## 10.2.4

- CSF-Factories: Fix codemod for preview files without exports - [#33673](https://github.com/storybookjs/storybook/pull/33673), thanks @kasperpeulen!
Expand Down
23 changes: 23 additions & 0 deletions code/builders/builder-vite/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,29 @@ export async function build(options: Options) {

const finalConfig = (await presets.apply('viteFinal', config, options)) as InlineConfig;

// Add a plugin to enforce Storybook's outDir after all other plugins.
// This prevents frameworks like Nitro from redirecting
// build output to their own directories (e.g., .output/public/).
// The 'enforce: post' ensures this runs after all other config hooks.
finalConfig.plugins?.push({
name: 'storybook:enforce-output-dir',
enforce: 'post',
config: (config) => ({
...config,
build: {
outDir: options.outputDir,
},
}),
// configEnvironment is a new method in Vite 6
// It is used to configure configs based on the environment
// E.g. Nitro uses this method to set the output directory to .output/public/
configEnvironment: () => ({
build: {
outDir: options.outputDir,
},
}),
});

if (options.features?.developmentModeForBuild) {
finalConfig.plugins?.push({
name: 'storybook:define-env',
Expand Down
107 changes: 107 additions & 0 deletions code/core/src/common/utils/resolve-path-in-sb-cache.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { join } from 'node:path';

import { beforeEach, describe, expect, it, vi } from 'vitest';

import * as pkg from 'empathic/package';

import versions from '../versions';
import { resolvePathInStorybookCache } from './resolve-path-in-sb-cache';

vi.mock('empathic/package', () => ({
cache: vi.fn(),
}));

vi.mock('../versions', () => ({
default: {
storybook: '10.3.0-alpha.1',
},
}));

describe('resolvePathInStorybookCache', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('should include version in the cache path when using empathic cache', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

const result = resolvePathInStorybookCache('test-file', 'test-sub');

expect(result).toContain(versions.storybook);
expect(result).toBe(join(mockCacheDir, versions.storybook, 'test-sub', 'test-file'));
});

it('should include version in the cache path when falling back to cwd', () => {
vi.mocked(pkg.cache).mockReturnValue(undefined);
const cwd = process.cwd();

const result = resolvePathInStorybookCache('test-file', 'test-sub');

expect(result).toContain(versions.storybook);
expect(result).toBe(
join(cwd, 'node_modules', '.cache', 'storybook', versions.storybook, 'test-sub', 'test-file')
);
});

it('should use default sub directory when not provided', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

const result = resolvePathInStorybookCache('test-file');

expect(result).toBe(join(mockCacheDir, versions.storybook, 'default', 'test-file'));
});

it('should handle empty file or directory name', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

const result = resolvePathInStorybookCache('', 'test-sub');

// Note: path.join() normalizes away the trailing slash for empty strings
expect(result).toBe(join(mockCacheDir, versions.storybook, 'test-sub'));
});

it('should create consistent paths for the same version', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

const result1 = resolvePathInStorybookCache('file1', 'sub1');
const result2 = resolvePathInStorybookCache('file2', 'sub1');

expect(result1).toContain(versions.storybook);
expect(result2).toContain(versions.storybook);
// Verify both paths share the same base directory by comparing parent directories
const parent1 = result1.substring(0, result1.lastIndexOf(join('sub1', 'file1')));
const parent2 = result2.substring(0, result2.lastIndexOf(join('sub1', 'file2')));
expect(parent1).toBe(parent2);
});

it('should handle different subdirectories', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

const result1 = resolvePathInStorybookCache('test-file', 'dev-server');
const result2 = resolvePathInStorybookCache('test-file', 'telemetry');

expect(result1).toBe(join(mockCacheDir, versions.storybook, 'dev-server', 'test-file'));
expect(result2).toBe(join(mockCacheDir, versions.storybook, 'telemetry', 'test-file'));
});

it('should use "unknown" as version when storybook version is not available', () => {
const mockCacheDir = '/mock/node_modules/.cache/storybook';
vi.mocked(pkg.cache).mockReturnValue(mockCacheDir);

// Mock the versions module to return a falsy value
vi.mocked(versions).storybook = '' as any;

const result = resolvePathInStorybookCache('test-file', 'test-sub');

expect(result).toContain('unknown');
expect(result).toBe(join(mockCacheDir, 'unknown', 'test-sub', 'test-file'));

// Reset the mock
vi.mocked(versions).storybook = '10.3.0-alpha.1';
});
});
16 changes: 13 additions & 3 deletions code/core/src/common/utils/resolve-path-in-sb-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@ import { join } from 'node:path';

import * as pkg from 'empathic/package';

import versions from '../versions';

/**
* Get the path of the file or directory with input name inside the Storybook cache directory:
*
* - `node_modules/.cache/storybook/{directoryName}` in a Node.js project or npm package
* - `.cache/storybook/{directoryName}` otherwise
* - `node_modules/.cache/storybook/{version}/{directoryName}` in a Node.js project or npm package
* - `.cache/storybook/{version}/{directoryName}` otherwise
*
* The cache directory includes the Storybook version to ensure that upgrading Storybook
* automatically invalidates the cache, preventing stale cache issues.
*
* @param fileOrDirectoryName {string} Name of the file or directory
* @param sub {string} Optional subdirectory name (defaults to 'default')
* @returns {string} Absolute path to the file or directory
*/
export function resolvePathInStorybookCache(fileOrDirectoryName: string, sub = 'default'): string {
let cacheDirectory = pkg.cache('storybook');
cacheDirectory ||= join(process.cwd(), 'node_modules', '.cache', 'storybook');

return join(cacheDirectory, sub, fileOrDirectoryName);
// Include the storybook version in the cache path to automatically invalidate
// cache when upgrading to a new version
const version = versions.storybook || 'unknown';

return join(cacheDirectory, version, sub, fileOrDirectoryName);
}
2 changes: 1 addition & 1 deletion code/frameworks/angular/build-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"description": "Controls level of logging during build. Can be one of: [trace, debug, info (default), warn, error, silent].",
"pattern": "(trace|debug|info|warn|error|silent)"
},
"logfile": {
Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/angular/start-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"description": "Controls level of logging during build. Can be one of: [trace, debug, info (default), warn, error, silent].",
"pattern": "(trace|debug|info|warn|error|silent)"
},
"logfile": {
Expand Down
3 changes: 2 additions & 1 deletion code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,6 @@
"Dependency Upgrades"
]
]
}
},
"deferredNextVersion": "10.2.5"
}
4 changes: 2 additions & 2 deletions docs/api/cli-options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Options include:
| `--exact-port` | Attempts to run Storybook on the exact port number specified.<br />If the port is already in use, Storybook will exit with an error message.<br />`storybook dev -p 9009 --exact-port` |
| `-h`, `--host [string]` | Host to run Storybook.<br />`storybook dev -h my-host.com` |
| `-c`, `--config-dir [dir-name]` | Storybook configuration directory.<br />`storybook dev -c .storybook` |
| `--loglevel [level]` | Controls level of logging during build.<br />Available options: `silly`, `verbose`, `info` (default), `warn`, `error`, `silent`<br />`storybook dev --loglevel warn` |
| `--loglevel [level]` | Controls level of logging during build.<br />Available options: `trace`, `debug`, `info` (default), `warn`, `error`, `silent`<br />`storybook dev --loglevel warn` |
| `--https` | Serve Storybook over HTTPS. Note: You must provide your own certificate information.<br />`storybook dev --https` |
| `--ssl-ca` | Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)<br />`storybook dev --ssl-ca my-certificate` |
| `--ssl-cert` | Provide an SSL certificate. (Required with --https)<br />`storybook dev --ssl-cert my-ssl-certificate` |
Expand Down Expand Up @@ -85,7 +85,7 @@ Options include:
| `-V`, `--version` | Output the version number.<br />`storybook build -V` |
| `-o`, `--output-dir [dir-name]` | Directory where to store built files.<br />`storybook build -o /my-deployed-storybook` |
| `-c`, `--config-dir [dir-name]` | Storybook configuration directory.<br />`storybook build -c .storybook` |
| `--loglevel [level]` | Controls level of logging during build.<br />Available options: `silly`, `verbose`, `info` (default), `warn`, `error`, `silent`.<br />`storybook build --loglevel warn` |
| `--loglevel [level]` | Controls level of logging during build.<br />Available options: `trace`, `debug`, `info` (default), `warn`, `error`, `silent`.<br />`storybook build --loglevel warn` |
| `--quiet` | Suppress verbose build output.<br />`storybook build --quiet` |
| `--debug` | Outputs more logs in the CLI to assist debugging.<br />`storybook build --debug` |
| `--debug-webpack` | Display final webpack configurations for debugging purposes.<br />`storybook build --debug-webpack` |
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/frameworks/angular.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ These are common options you may need for the Angular builder:
| `"initialPath"` | URL path to be appended when visiting Storybook for the first time. <br /> `"initialPath": "docs/configure-your-project--docs"` |
| `"webpackStatsJson"` | Write Webpack Stats JSON to disk. <br /> `"webpackStatsJson": true` |
| `"previewUrl"` | Disables the default storybook preview and lets you use your own. <br /> `"previewUrl": "iframe.html"` |
| `"loglevel"` | Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent]. <br /> `"loglevel": "info"` |
| `"loglevel"` | Controls level of logging during build. Can be one of: [trace, debug, info (default), warn, error, silent]. <br /> `"loglevel": "info"` |
| `"sourceMap"` | Configure [sourcemaps](https://angular.dev/reference/configs/workspace-config#source-map-configuration.). <br /> `"sourceMap": true` |
| `"experimentalZoneless"` | Configure [zoneless change detection](https://angular.dev/guide/zoneless). <br /> `"experimentalZoneless": true` |

Expand Down
2 changes: 1 addition & 1 deletion docs/versions/latest.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"10.2.4","info":{"plain":"- CSF-Factories: Fix codemod for preview files without exports - [#33673](https://github.com/storybookjs/storybook/pull/33673), thanks @kasperpeulen!\n- CSF: Fix false positive detection of Zod v4 .meta() as CSF Factory - [#33666](https://github.com/storybookjs/storybook/pull/33666), thanks @kasperpeulen!\n- CSFFactories: Add non-interactive mode and --glob flag - [#33648](https://github.com/storybookjs/storybook/pull/33648), thanks @kasperpeulen!\n- CSFFactories: Preserve leading comments when adding imports - [#33645](https://github.com/storybookjs/storybook/pull/33645), thanks @kasperpeulen!\n- Codemod: Fix csf-2-to-3 failing due to quoted filenames - [#33646](https://github.com/storybookjs/storybook/pull/33646), thanks @kasperpeulen!\n- Codemod: Fix glob pattern handling on Windows - [#33714](https://github.com/storybookjs/storybook/pull/33714), thanks @kasperpeulen!\n- Manager: Remove deprecated `active` prop warning in ZoomButton - [#33697](https://github.com/storybookjs/storybook/pull/33697), thanks @yatishgoel!\n- Next.js: Alias AppRouterContext to shared runtime to fix Link navigation - [#33419](https://github.com/storybookjs/storybook/pull/33419), thanks @pallaprolus!"}}
{"version":"10.2.5","info":{"plain":"- Angular: fix --loglevel options in docs and descriptions - [#33726](https://github.com/storybookjs/storybook/pull/33726), thanks @theRuslan!\n- Builder-Vite: Add plugin to enforce Storybook's output directory in Vite build configuration - [#33740](https://github.com/storybookjs/storybook/pull/33740), thanks @valentinpalkovic!\n- Core: Invalidate cache on Storybook version upgrade - [#33717](https://github.com/storybookjs/storybook/pull/33717), thanks @copilot-swe-agent!"}}
Loading