-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Open
Description
Describe the bug
Summary
Given the following SPA (https://github.com/thediveo/lxkns/tree/chore/web/web/lxkns ... notice the chore/web branch) using...
- React 19
- MUI 7
- mdx-js 3
- Vite 7
- Storybook 10
...crashes with...
■ Vite Internal server error: Unexpected `FunctionDeclaration` in code: only
│ import/exports are supported
│ Plugin: @mdx-js/rollup
│ File: ./src/components/helpviewer/chapters/01-intro.mdx:3:1
│ 1 | import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from
│ "react/jsx-runtime";
│ 2 | import {useMDXComponents as _provideComponents} from
│ "file://./node_modules/@storybook/addo...
│ 3 | function _createMdxContent(props) {
│ | ^
│ 4 | const _components = {
│ 5 | h1: "h1",
...as soon as a component uses MDX for itself.
Configuration
main.ts
Notice, stories does not include a pattern for .mdx content.
// .storybook/main.ts
import type { StorybookConfig as StorybookViteConfig } from '@storybook/react-vite'
const config: StorybookViteConfig = {
framework: {
name: '@storybook/react-vite',
options: {},
},
stories: [
'../src/**/*.stories.@(ts|tsx)',
],
addons: [
'@storybook/addon-docs',
'@storybook/addon-links',
'@storybook/addon-themes',
],
docs: {
defaultName: 'Description',
},
core: {
disableTelemetry: true,
disableWhatsNewNotifications: true,
},
typescript: {
check: true,
},
}
export default configproview.tsx
// .storybook/preview.tsx
import { BrowserRouter } from 'react-router-dom'
import type { Parameters, Preview } from '@storybook/react-vite'
import { withThemeFromJSXProvider, DecoratorHelpers } from '@storybook/addon-themes'
const { pluckThemeFromContext } = DecoratorHelpers
import '@fontsource/roboto/300.css'
import '@fontsource/roboto/400.css'
import '@fontsource/roboto/500.css'
import '@fontsource/roboto/700.css'
import '@fontsource/roboto-mono/400.css'
import { lxknsDarkTheme, lxknsLightTheme } from '../src/app/appstyles'
import { createTheme, StyledEngineProvider, ThemeProvider } from '@mui/material/styles'
import CssBaseline from '@mui/material/CssBaseline'
import { themes } from 'storybook/theming'
const lightTheme = createTheme(
{
components: {
MuiSelect: {
defaultProps: {
variant: 'standard', // MUI v4 default.
},
},
},
palette: {
mode: 'light',
primary: {
main: '#3f51b5',
},
secondary: {
main: '#f50057',
},
},
},
lxknsLightTheme,
)
const darkTheme = createTheme(
{
components: {
MuiSelect: {
defaultProps: {
variant: 'standard', // MUI v4 default.
},
},
},
palette: {
mode: 'dark',
},
},
lxknsDarkTheme,
)
export const parameters: Parameters = {
docs: {
theme: themes.normal, // use same theme as the surrounding parts
},
}
const preview: Preview = {
decorators: [
(Story) => (
<BrowserRouter basename=''>
<StyledEngineProvider injectFirst>
<Story />
</StyledEngineProvider>
</BrowserRouter>
),
withThemeFromJSXProvider({
themes: {
light: lightTheme,
dark: darkTheme,
},
defaultTheme: themes.normal.base,
Provider: ThemeProvider,
GlobalStyles: CssBaseline,
}),
(Story, context) => {
const isDark = pluckThemeFromContext(context) === 'dark'
// addon-docs is broken ... nein! doch! ohhh! ... and thus we need
// to deal with duplicates. ohhh!
const docsStories = document.querySelectorAll(`#anchor--${context.id} .docs-story`) as
NodeListOf<HTMLElement>
docsStories.forEach((story) => {
if (story.style) {
story.style.background = isDark
? darkTheme.palette.background.default
: lightTheme.palette.background.default;
}
})
return <Story />
},
],
}
export default previewvite.config.ts
This configuration works correctly with mdx-js 3.
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'
import svgr from 'vite-plugin-svgr'
import mdx from '@mdx-js/rollup'
import path from 'path'
import remarkGfm from 'remark-gfm'
import remarkImages from 'remark-images'
import remarkTextr from 'remark-textr'
import remarkGEmoji from 'remark-gemoji'
import textrTypoApos from 'typographic-apostrophes'
import textrTypoQuotes from 'typographic-quotes'
import textrTypoPossPluralsApos from 'typographic-apostrophes-for-possessive-plurals'
import textrTypoEllipses from 'typographic-ellipses'
import textrTypoNumberEnDashes from 'typographic-en-dashes'
import rehypeSlug from 'rehype-slug'
// There's only typographic-em-dashes that covers US typographic style, but no
// need for a full-blown npm module just to get European en dash typography.
const textrTypoEnDashes = (input: string) => {
return input
.replace(/ -- /gim, ' – ')
}
const srcs = [
'app',
'components',
'hooks',
'icons',
'models',
'utils',
'views',
]
// https://vite.dev/config/
export default defineConfig({
base: './',
build: {
outDir: 'build'
},
server: {
host: "0.0.0.0",
port: 3300,
proxy: {
'/api': 'http://localhost:5010',
},
},
resolve: {
alias: Object.fromEntries(
srcs.map(d => [d, path.resolve(__dirname, `src/${d}`)])
)
},
plugins: [
{
enforce: 'pre',
...mdx({
remarkPlugins: [
remarkGfm,
remarkImages,
remarkGEmoji,
[remarkTextr, {
plugins: [
textrTypoApos,
textrTypoQuotes,
textrTypoPossPluralsApos,
textrTypoEllipses,
textrTypoNumberEnDashes,
textrTypoEnDashes,
],
options: {
locale: 'en-us'
}
}],
],
rehypePlugins: [
rehypeSlug,
],
})
},
tsconfigPaths(),
react(),
svgr({
svgrOptions: {
icon: true,
}
}),
]
})tsconfig.json
tsconfig.app.json
// tsconfig.app.json
{
"compilerOptions": {
"baseUrl": "./src",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
"lib": [
"ES2022",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"types": [
"react",
"vite/client"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": false,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": [
"src",
"vite.config.ts"
]
}tsconfig.node.json
// tsconfig.node.json
{
"compilerOptions": {
"baseUrl": "./src",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": [
"ES2023",
"dom"
],
"module": "ESNext",
"types": [
"node",
"vite/client"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": false,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": [
"src",
"vite.config.ts"
]
}...how to make storybook work with SPAs that use mdx themselves?
Reproduction link
https://github.com/thediveo/lxkns/tree/chore/web/web/lxkns
Reproduction steps
git clone -b chore/web https://github.com/thediveo/lxkns.- open the workspace in a dev container.
cd web/lxknsyarn && yarn run storybook- navigate to: http://localhost:6006/?path=/docs/universal-helpviewer--description
- crashes and burns (see details above)
System
│
│
│ Storybook Environment Info:
│
│ System:
│ OS: Linux 6.14 Ubuntu 24.04.3 LTS 24.04.3 LTS (Noble Numbat)
│ CPU: (4) x64 Intel(R) Xeon(R) Gold 6354 CPU @ 3.00GHz
│ Shell: 5.2.21 - /bin/bash
│ Binaries:
│ Node: 24.12.0 - /usr/local/share/nvm/versions/node/v24.12.0/bin/node
│ Yarn: 1.22.22 - /usr/bin/yarn <----- active
│ npm: 11.6.2 - /usr/local/share/nvm/versions/node/v24.12.0/bin/npm
│ pnpm: 10.25.0 - /usr/local/share/nvm/versions/node/v24.12.0/bin/pnpm
│ npmPackages:
│ @storybook/addon-docs: ^10.1.4 => 10.1.9
│ @storybook/addon-links: ^10.1.4 => 10.1.9
│ @storybook/addon-themes: ^10.1.8 => 10.1.9
│ @storybook/react-vite: ^10.1.4 => 10.1.9
│ storybook: ^10.1.9 => 10.1.9Additional context
No response
dosubot