Upgrade Storybook to version 9
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
+64
-3
@@ -35,15 +35,76 @@ const config: StorybookConfig = {
|
||||
stories,
|
||||
addons: [
|
||||
getAbsolutePath('@storybook/addon-links'),
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@storybook/addon-interactions'),
|
||||
getAbsolutePath('@storybook/addon-themes'),
|
||||
getAbsolutePath('@storybook/addon-storysource'),
|
||||
getAbsolutePath('@storybook/addon-docs'),
|
||||
],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/react-vite'),
|
||||
options: {},
|
||||
},
|
||||
viteFinal: async config => {
|
||||
// Add Node.js polyfills for browser compatibility
|
||||
//
|
||||
// When upgrading from Storybook 8 to 9 with the react-vite framework,
|
||||
// Node.js polyfills are no longer automatically included by Vite.
|
||||
// This causes "ReferenceError: process is not defined" errors in the browser
|
||||
// when code tries to access Node.js globals like `process` and `util`.
|
||||
//
|
||||
// The @vitest/mocker (included with Storybook 9) expects MSW v2 APIs,
|
||||
// but we want to keep MSW v1 for the rest of the monorepo to avoid
|
||||
// breaking changes. This configuration provides the necessary polyfills
|
||||
// and handles the MSW compatibility issue specifically for Storybook.
|
||||
//
|
||||
// These polyfills provide browser-compatible versions of Node.js globals:
|
||||
// - process: Node.js process object with env
|
||||
// - global -> globalThis: Maps Node.js global to browser's globalThis
|
||||
//
|
||||
// Without these, Backstage components that rely on Node.js APIs will fail
|
||||
// to load in Storybook's browser environment.
|
||||
config.define = {
|
||||
...config.define,
|
||||
global: 'globalThis',
|
||||
'process.env': '{}',
|
||||
process: '{ env: {}, browser: true }',
|
||||
};
|
||||
|
||||
config.resolve = {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve?.alias,
|
||||
// Provide Node.js polyfills for browser
|
||||
process: 'process/browser',
|
||||
util: 'util',
|
||||
buffer: 'buffer',
|
||||
stream: 'stream-browserify',
|
||||
// Fix MSW v2 imports for @vitest/mocker compatibility
|
||||
// @vitest/mocker expects MSW v2 APIs but we want to keep MSW v1 for the rest of the monorepo
|
||||
'msw/browser': join(__dirname, 'msw-browser-shim.js'),
|
||||
'msw/core/http': join(__dirname, 'msw-http-shim.js'),
|
||||
},
|
||||
};
|
||||
|
||||
// Optimize dependencies for better performance
|
||||
config.optimizeDeps = {
|
||||
...config.optimizeDeps,
|
||||
include: [
|
||||
...(config.optimizeDeps?.include || []),
|
||||
'process/browser',
|
||||
'util',
|
||||
'buffer',
|
||||
'stream-browserify',
|
||||
],
|
||||
// Exclude MSW to prevent optimization conflicts with our shims
|
||||
exclude: [
|
||||
...(config.optimizeDeps?.exclude || []),
|
||||
'msw',
|
||||
'msw/browser',
|
||||
'msw/core/http',
|
||||
],
|
||||
};
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// MSW v2 browser compatibility shim for @vitest/mocker
|
||||
// This provides MSW v2 exports using MSW v1 APIs to maintain compatibility
|
||||
// while keeping the rest of the monorepo on MSW v1
|
||||
|
||||
try {
|
||||
// Try to import from MSW v1
|
||||
const { setupWorker, rest } = require('msw');
|
||||
|
||||
// Export in MSW v2 format expected by @vitest/mocker
|
||||
module.exports = {
|
||||
setupWorker,
|
||||
// MSW v2 uses 'http' instead of 'rest', but we provide both for compatibility
|
||||
http: rest,
|
||||
rest, // Keep rest for any MSW v1 code
|
||||
};
|
||||
} catch (error) {
|
||||
// Fallback if MSW is not available - provide minimal mock
|
||||
console.warn(
|
||||
'MSW not available, providing minimal mock for @vitest/mocker compatibility',
|
||||
);
|
||||
module.exports = {
|
||||
setupWorker: () => ({
|
||||
start: () => Promise.resolve(),
|
||||
stop: () => {},
|
||||
use: () => {},
|
||||
resetHandlers: () => {},
|
||||
}),
|
||||
http: {
|
||||
get: () => {},
|
||||
post: () => {},
|
||||
put: () => {},
|
||||
delete: () => {},
|
||||
patch: () => {},
|
||||
head: () => {},
|
||||
options: () => {},
|
||||
},
|
||||
rest: {
|
||||
get: () => {},
|
||||
post: () => {},
|
||||
put: () => {},
|
||||
delete: () => {},
|
||||
patch: () => {},
|
||||
head: () => {},
|
||||
options: () => {},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// MSW v2 http compatibility shim for @vitest/mocker
|
||||
// This provides MSW v2 http exports using MSW v1 APIs
|
||||
|
||||
try {
|
||||
// Try to import from MSW v1
|
||||
const { rest } = require('msw');
|
||||
|
||||
// Export MSW v1 'rest' as MSW v2 'http' for @vitest/mocker compatibility
|
||||
module.exports = {
|
||||
http: rest,
|
||||
// Provide individual methods that @vitest/mocker might expect
|
||||
get: rest.get,
|
||||
post: rest.post,
|
||||
put: rest.put,
|
||||
delete: rest.delete,
|
||||
patch: rest.patch,
|
||||
head: rest.head,
|
||||
options: rest.options,
|
||||
all: rest.all,
|
||||
};
|
||||
} catch (error) {
|
||||
// Fallback if MSW is not available
|
||||
console.warn(
|
||||
'MSW not available, providing minimal http mock for @vitest/mocker compatibility',
|
||||
);
|
||||
const noop = () => {};
|
||||
module.exports = {
|
||||
http: {
|
||||
get: noop,
|
||||
post: noop,
|
||||
put: noop,
|
||||
delete: noop,
|
||||
patch: noop,
|
||||
head: noop,
|
||||
options: noop,
|
||||
all: noop,
|
||||
},
|
||||
get: noop,
|
||||
post: noop,
|
||||
put: noop,
|
||||
delete: noop,
|
||||
patch: noop,
|
||||
head: noop,
|
||||
options: noop,
|
||||
all: noop,
|
||||
};
|
||||
}
|
||||
+10
-2
@@ -2,8 +2,8 @@ import React, { useEffect } from 'react';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { Content, AlertDisplay } from '@backstage/core-components';
|
||||
import { apis } from './support/apis';
|
||||
import type { Decorator, Preview } from '@storybook/react';
|
||||
import { useGlobals } from '@storybook/preview-api';
|
||||
import type { Decorator, Preview } from '@storybook/react-vite';
|
||||
import { useGlobals } from 'storybook/preview-api';
|
||||
import { UnifiedThemeProvider, themes } from '@backstage/theme';
|
||||
|
||||
// Default Backstage theme CSS (from packages/ui)
|
||||
@@ -52,20 +52,24 @@ const preview: Preview = {
|
||||
},
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
|
||||
backgrounds: {
|
||||
disable: true,
|
||||
},
|
||||
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
|
||||
options: {
|
||||
storySort: {
|
||||
order: ['Backstage UI', 'Plugins', 'Layout', 'Navigation'],
|
||||
},
|
||||
},
|
||||
|
||||
viewport: {
|
||||
viewports: {
|
||||
initial: {
|
||||
@@ -82,6 +86,10 @@ const preview: Preview = {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
docs: {
|
||||
codePanel: true,
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
Story => {
|
||||
|
||||
Reference in New Issue
Block a user