Skip to content

Commit

Permalink
Merge pull request #24395 from storybookjs/vite-5
Browse files Browse the repository at this point in the history
Vite: Support Vite 5
  • Loading branch information
JReinhold committed Oct 13, 2023
2 parents 6b2150c + 8b0ffb0 commit a427c33
Show file tree
Hide file tree
Showing 18 changed files with 83 additions and 72 deletions.
2 changes: 1 addition & 1 deletion code/builders/builder-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"peerDependencies": {
"@preact/preset-vite": "*",
"typescript": ">= 4.3.x",
"vite": "^3.0.0 || ^4.0.0",
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0",
"vite-plugin-glimmerx": "*"
},
"peerDependenciesMeta": {
Expand Down
3 changes: 1 addition & 2 deletions code/builders/builder-vite/src/build.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { build as viteBuild, mergeConfig } from 'vite';
import type { Options } from '@storybook/types';
import { commonConfig } from './vite-config';

import { sanitizeEnvVars } from './envs';

export async function build(options: Options) {
const { build: viteBuild, mergeConfig } = await import('vite');
const { presets } = options;

const config = await commonConfig(options, 'build');
Expand All @@ -21,6 +21,5 @@ export async function build(options: Options) {
}).build;

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

await viteBuild(await sanitizeEnvVars(options, finalConfig));
}
10 changes: 7 additions & 3 deletions code/builders/builder-vite/src/codegen-entries.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { loadPreviewOrConfigFile } from '@storybook/core-common';
import type { Options } from '@storybook/types';
import slash from 'slash';
import { normalizePath } from 'vite';
import { listStories } from './list-stories';

const absoluteFilesToImport = (files: string[], name: string) =>
const absoluteFilesToImport = async (
files: string[],
name: string,
normalizePath: (id: string) => string
) =>
files
.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`)
.join('\n');

export async function generateVirtualStoryEntryCode(options: Options) {
const { normalizePath } = await import('vite');
const storyEntries = await listStories(options);
const resolveMap = storyEntries.reduce<Record<string, string>>(
(prev, entry) => ({ ...prev, [entry]: entry.replace(slash(process.cwd()), '.') }),
Expand All @@ -18,7 +22,7 @@ export async function generateVirtualStoryEntryCode(options: Options) {
const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');

return `
${absoluteFilesToImport(storyEntries, 'story')}
${await absoluteFilesToImport(storyEntries, 'story', normalizePath)}
function loadable(key) {
return {${modules}}[key];
Expand Down
3 changes: 2 additions & 1 deletion code/builders/builder-vite/src/codegen-importfn-script.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from 'path';
import { normalizePath } from 'vite';

import type { Options } from '@storybook/types';
import { logger } from '@storybook/node-logger';

Expand All @@ -26,6 +26,7 @@ function toImportPath(relativePath: string) {
* @param stories An array of absolute story paths.
*/
async function toImportFn(stories: string[]) {
const { normalizePath } = await import('vite');
const objectEntries = stories.map((file) => {
const ext = path.extname(file);
const relativePath = normalizePath(path.relative(process.cwd(), file));
Expand Down
3 changes: 2 additions & 1 deletion code/builders/builder-vite/src/list-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { glob } from 'glob';
import { normalizeStories, commonGlobOptions } from '@storybook/core-common';

import type { Options } from '@storybook/types';
import { normalizePath } from 'vite';

export async function listStories(options: Options) {
const { normalizePath } = await import('vite');

return (
await Promise.all(
normalizeStories(await options.presets.apply('stories', [], options), {
Expand Down
2 changes: 1 addition & 1 deletion code/builders/builder-vite/src/optimizeDeps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as path from 'path';
import { normalizePath, resolveConfig } from 'vite';
import type { InlineConfig as ViteInlineConfig, UserConfig } from 'vite';
import type { Options } from '@storybook/types';
import { listStories } from './list-stories';
Expand Down Expand Up @@ -128,6 +127,7 @@ const asyncFilter = async (arr: string[], predicate: (val: string) => Promise<bo

export async function getOptimizeDeps(config: ViteInlineConfig, options: Options) {
const { root = process.cwd() } = config;
const { normalizePath, resolveConfig } = await import('vite');
const absoluteStories = await listStories(options);
const stories = absoluteStories.map((storyPath) => normalizePath(path.relative(root, storyPath)));
// TODO: check if resolveConfig takes a lot of time, possible optimizations here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import findCacheDirectory from 'find-cache-dir';
import { init, parse } from 'es-module-lexer';
import MagicString from 'magic-string';
import { ensureFile, writeFile } from 'fs-extra';
import { mergeAlias } from 'vite';
import type { Alias, Plugin } from 'vite';

const escapeKeys = (key: string) => key.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
Expand Down Expand Up @@ -38,6 +37,8 @@ const replacementMap = new Map([
*/
export async function externalGlobalsPlugin(externals: Record<string, string>) {
await init;
const { mergeAlias } = await import('vite');

return {
name: 'storybook:external-globals-plugin',
enforce: 'post',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
import { parse } from 'es-module-lexer';
import MagicString from 'magic-string';
import { createFilter } from 'vite';

const include = [/\.stories\.([tj])sx?$/, /(stories|story).mdx$/];
const filter = createFilter(include);
export async function injectExportOrderPlugin() {
const { createFilter } = await import('vite');

export const injectExportOrderPlugin = {
name: 'storybook:inject-export-order-plugin',
// This should only run after the typescript has been transpiled
enforce: 'post',
async transform(code: string, id: string) {
if (!filter(id)) return undefined;
const include = [/\.stories\.([tj])sx?$/, /(stories|story).mdx$/];
const filter = createFilter(include);

// TODO: Maybe convert `injectExportOrderPlugin` to function that returns object,
// and run `await init;` once and then call `parse()` without `await`,
// instead of calling `await parse()` every time.
const [, exports] = await parse(code);
return {
name: 'storybook:inject-export-order-plugin',
// This should only run after the typescript has been transpiled
enforce: 'post',
async transform(code: string, id: string) {
if (!filter(id)) return undefined;

if (exports.includes('__namedExportsOrder')) {
// user has defined named exports already
return undefined;
}
const s = new MagicString(code);
const orderedExports = exports.filter((e) => e !== 'default');
s.append(`;export const __namedExportsOrder = ${JSON.stringify(orderedExports)};`);
return {
code: s.toString(),
map: s.generateMap({ hires: true, source: id }),
};
},
};
// TODO: Maybe convert `injectExportOrderPlugin` to function that returns object,
// and run `await init;` once and then call `parse()` without `await`,
// instead of calling `await parse()` every time.
const [, exports] = await parse(code);

if (exports.includes('__namedExportsOrder')) {
// user has defined named exports already
return undefined;
}
const s = new MagicString(code);
const orderedExports = exports.filter((e) => e !== 'default');
s.append(`;export const __namedExportsOrder = ${JSON.stringify(orderedExports)};`);
return {
code: s.toString(),
map: s.generateMap({ hires: true, source: id }),
};
},
};
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type { Plugin } from 'vite';
import { createFilter } from 'vite';
import MagicString from 'magic-string';

/**
* This plugin removes HMR `accept` calls in story files. Stories should not be treated
* as hmr boundaries, but vite has a bug which causes them to be treated as boundaries
* (https://github.com/vitejs/vite/issues/9869).
*/
export function stripStoryHMRBoundary(): Plugin {
export async function stripStoryHMRBoundary(): Promise<Plugin> {
const { createFilter } = await import('vite');

const filter = createFilter(/\.stories\.([tj])sx?$/);
return {
name: 'storybook:strip-hmr-boundary-plugin',
Expand Down
7 changes: 4 additions & 3 deletions code/builders/builder-vite/src/vite-config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as path from 'path';
import { loadConfigFromFile, mergeConfig } from 'vite';
import findCacheDirectory from 'find-cache-dir';
import type {
ConfigEnv,
Expand Down Expand Up @@ -41,6 +40,8 @@ export async function commonConfig(
_type: PluginConfigType
): Promise<ViteInlineConfig> {
const configEnv = _type === 'development' ? configEnvServe : configEnvBuild;
const { loadConfigFromFile, mergeConfig } = await import('vite');

const { viteConfigPath } = await getBuilderOptions<BuilderOptions>(options);

const projectRoot = path.resolve(options.configDir, '..');
Expand Down Expand Up @@ -80,8 +81,8 @@ export async function pluginConfig(options: Options) {
const plugins = [
codeGeneratorPlugin(options),
await csfPlugin(options),
injectExportOrderPlugin,
stripStoryHMRBoundary(),
await injectExportOrderPlugin(),
await stripStoryHMRBoundary(),
{
name: 'storybook:allow-storybook-dir',
enforce: 'post',
Expand Down
2 changes: 1 addition & 1 deletion code/builders/builder-vite/src/vite-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Server } from 'http';
import { createServer } from 'vite';
import type { Options } from '@storybook/types';
import { commonConfig } from './vite-config';
import { getOptimizeDeps } from './optimizeDeps';
Expand Down Expand Up @@ -29,5 +28,6 @@ export async function createViteServer(options: Options, devServer: Server) {

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

const { createServer } = await import('vite');
return createServer(await sanitizeEnvVars(options, finalConfig));
}
2 changes: 1 addition & 1 deletion code/frameworks/preact-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
"peerDependencies": {
"preact": ">=10",
"vite": "^3.0.0 || ^4.0.0"
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"engines": {
"node": ">=16"
Expand Down
4 changes: 2 additions & 2 deletions code/frameworks/react-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"prep": "../../../scripts/prepare/bundle.ts"
},
"dependencies": {
"@joshwooding/vite-plugin-react-docgen-typescript": "0.2.1",
"@joshwooding/vite-plugin-react-docgen-typescript": "0.3.0",
"@rollup/pluginutils": "^5.0.2",
"@storybook/builder-vite": "workspace:*",
"@storybook/react": "workspace:*",
Expand All @@ -63,7 +63,7 @@
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"vite": "^3.0.0 || ^4.0.0"
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"engines": {
"node": ">=16"
Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/svelte-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
},
"peerDependencies": {
"svelte": "^3.0.0 || ^4.0.0",
"vite": "^3.0.0 || ^4.0.0"
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"engines": {
"node": "^14.18 || >=16"
Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/vue-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"vite": "^3.0.0 || ^4.0.0",
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0",
"vue": "^2.7.0"
},
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/vue3-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"vite": "^3.0.0 || ^4.0.0"
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"engines": {
"node": "^14.18 || >=16"
Expand Down
24 changes: 12 additions & 12 deletions code/lib/cli/src/sandbox-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ const baseTemplates = {
},
'react-vite/default-js': {
name: 'React Latest (Vite | JavaScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template react',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template react',
expected: {
framework: '@storybook/react-vite',
renderer: '@storybook/react',
Expand All @@ -160,7 +160,7 @@ const baseTemplates = {
},
'react-vite/default-ts': {
name: 'React Latest (Vite | TypeScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template react-ts',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template react-ts',
expected: {
framework: '@storybook/react-vite',
renderer: '@storybook/react',
Expand Down Expand Up @@ -215,7 +215,7 @@ const baseTemplates = {
},
'vue3-vite/default-js': {
name: 'Vue v3 (Vite | JavaScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template vue',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template vue',
expected: {
framework: '@storybook/vue3-vite',
renderer: '@storybook/vue3',
Expand All @@ -225,7 +225,7 @@ const baseTemplates = {
},
'vue3-vite/default-ts': {
name: 'Vue v3 (Vite | TypeScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template vue-ts',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template vue-ts',
expected: {
framework: '@storybook/vue3-vite',
renderer: '@storybook/vue3',
Expand Down Expand Up @@ -257,7 +257,7 @@ const baseTemplates = {
'html-vite/default-js': {
name: 'HTML Latest (Vite | JavaScript)',
script:
'npm create vite@latest --yes {{beforeDir}} -- --template vanilla && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
'npm create vite@beta --yes {{beforeDir}} -- --template vanilla && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
expected: {
framework: '@storybook/html-vite',
renderer: '@storybook/html',
Expand All @@ -268,7 +268,7 @@ const baseTemplates = {
'html-vite/default-ts': {
name: 'HTML Latest (Vite | TypeScript)',
script:
'npm create vite@latest --yes {{beforeDir}} -- --template vanilla-ts && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
'npm create vite@beta --yes {{beforeDir}} -- --template vanilla-ts && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
expected: {
framework: '@storybook/html-vite',
renderer: '@storybook/html',
Expand All @@ -278,7 +278,7 @@ const baseTemplates = {
},
'svelte-vite/default-js': {
name: 'Svelte Latest (Vite | JavaScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template svelte',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template svelte',
expected: {
framework: '@storybook/svelte-vite',
renderer: '@storybook/svelte',
Expand All @@ -288,7 +288,7 @@ const baseTemplates = {
},
'svelte-vite/default-ts': {
name: 'Svelte Latest (Vite | TypeScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template svelte-ts',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template svelte-ts',
expected: {
framework: '@storybook/svelte-vite',
renderer: '@storybook/svelte',
Expand Down Expand Up @@ -355,7 +355,7 @@ const baseTemplates = {
'lit-vite/default-js': {
name: 'Lit Latest (Vite | JavaScript)',
script:
'npm create vite@latest --yes {{beforeDir}} -- --template lit && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
'npm create vite@beta --yes {{beforeDir}} -- --template lit && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
expected: {
framework: '@storybook/web-components-vite',
renderer: '@storybook/web-components',
Expand All @@ -367,7 +367,7 @@ const baseTemplates = {
'lit-vite/default-ts': {
name: 'Lit Latest (Vite | TypeScript)',
script:
'npm create vite@latest --yes {{beforeDir}} -- --template lit-ts && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
'npm create vite@beta --yes {{beforeDir}} -- --template lit-ts && cd {{beforeDir}} && echo "export default {}" > vite.config.js',
expected: {
framework: '@storybook/web-components-vite',
renderer: '@storybook/web-components',
Expand Down Expand Up @@ -424,7 +424,7 @@ const baseTemplates = {
},
'preact-vite/default-js': {
name: 'Preact Latest (Vite | JavaScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template preact',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template preact',
expected: {
framework: '@storybook/preact-vite',
renderer: '@storybook/preact',
Expand All @@ -434,7 +434,7 @@ const baseTemplates = {
},
'preact-vite/default-ts': {
name: 'Preact Latest (Vite | TypeScript)',
script: 'npm create vite@latest --yes {{beforeDir}} -- --template preact-ts',
script: 'npm create vite@beta --yes {{beforeDir}} -- --template preact-ts',
expected: {
framework: '@storybook/preact-vite',
renderer: '@storybook/preact',
Expand Down

0 comments on commit a427c33

Please sign in to comment.