diff --git a/MIGRATION.md b/MIGRATION.md
index 5b30c2c35719..4495d71096a8 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1,7 +1,8 @@
Migration
- [From version 7.5.0 to 7.6.0](#from-version-750-to-760)
- - [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
+ - [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)
@@ -312,6 +313,12 @@
## From version 7.5.0 to 7.6.0
+#### CommonJS with Vite is deprecated
+
+Using CommonJS in the `main` configuration with `main.cjs` or `main.cts` is deprecated, and will be removed in Storybook 8.0. This is a necessary change because [Vite will remove support for CommonJS in an upcoming release](https://github.com/vitejs/vite/discussions/13928).
+
+You can address this by converting your `main` configuration file to ESM syntax and renaming it to `main.mjs` or `main.mts` if your project does not have `"type": "module"` in its `package.json`. To convert the config file to ESM you will need to replace any CommonJS syntax like `require()`, `module.exports`, or `__dirname`. If you haven't already, you may also consider adding `"type": "module"` to your package.json and converting your project to ESM.
+
#### Using implicit actions during rendering is deprecated
In Storybook 7, we inferred if the component accepts any action props,
diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts
index 2811d93905f9..39b9c1ba5df8 100644
--- a/code/lib/core-server/src/build-dev.ts
+++ b/code/lib/core-server/src/build-dev.ts
@@ -11,6 +11,7 @@ import {
loadMainConfig,
resolveAddonName,
resolvePathInStorybookCache,
+ serverResolve,
validateFrameworkName,
} from '@storybook/core-common';
import prompts from 'prompts';
@@ -19,6 +20,9 @@ import { global } from '@storybook/global';
import { telemetry } from '@storybook/telemetry';
import { join, resolve } from 'path';
+import { deprecate } from '@storybook/node-logger';
+import dedent from 'ts-dedent';
+import { readFile } from 'fs-extra';
import { MissingBuilderError } from '@storybook/core-events/server-errors';
import { storybookDevServer } from './dev-server';
import { outputStats } from './utils/output-stats';
@@ -107,6 +111,24 @@ export async function buildDevStandalone(
getManagerBuilder(),
]);
+ if (builderName.includes('builder-vite')) {
+ const deprecationMessage =
+ dedent(`Using CommonJS in your main configuration file is deprecated with Vite.
+ - Refer to the migration guide at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#commonjs-with-vite-is-deprecated`);
+
+ const mainJsPath = serverResolve(resolve(options.configDir || '.storybook', 'main')) as string;
+ if (/\.c[jt]s$/.test(mainJsPath)) {
+ deprecate(deprecationMessage);
+ }
+ const mainJsContent = await readFile(mainJsPath, 'utf-8');
+ // Regex that matches any CommonJS-specific syntax, stolen from Vite: https://github.com/vitejs/vite/blob/91a18c2f7da796ff8217417a4bf189ddda719895/packages/vite/src/node/ssr/ssrExternal.ts#L87
+ const CJS_CONTENT_REGEX =
+ /\bmodule\.exports\b|\bexports[.[]|\brequire\s*\(|\bObject\.(?:defineProperty|defineProperties|assign)\s*\(\s*exports\b/;
+ if (CJS_CONTENT_REGEX.test(mainJsContent)) {
+ deprecate(deprecationMessage);
+ }
+ }
+
const resolvedRenderer = renderer && resolveAddonName(options.configDir, renderer, options);
// Load second pass: all presets are applied in order