Skip to content

Commit

Permalink
Merge pull request #19259 from storybookjs/vite/framework-plugins
Browse files Browse the repository at this point in the history
Issue: storybookjs/builder-vite#498

Closes #19245

## What I did

When we made the change in 7.0 to start using the user's `vite.config.js`, I made the (faulty) assumption that users would already have vite framework plugins (e.g. `@vitejs/plugin-react`) installed.  But this isn't always true, for example, a project might just be a collection of components being exported, and there may not be an actual app.  

So, this PR checks to see if the required framework plugin is already in the config, and if not, adds it.  I created a utility function to check for the plugin, but ideally this would live in a `vite-core` instead of duplicated across each framework.  This, combined with the duplication in #19216, makes me lean towards creating such a package.  But, it can be done any time and these duplications cleaned up at that point, so I don't think it's a blocker.

## How to test

Create a sandbox, delete `vite.config.js`, and start storybook.  Without this change there would be a crash, but it should work just fine now.
  • Loading branch information
IanVS authored Oct 4, 2022
2 parents 9f56f8e + 0bf4ad8 commit 2674cc1
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 32 deletions.
2 changes: 1 addition & 1 deletion code/frameworks/react-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"@storybook/client-api": "7.0.0-alpha.34",
"@storybook/preview-web": "7.0.0-alpha.34",
"@storybook/react": "7.0.0-alpha.34",
"@vitejs/plugin-react": "^2.0.1",
"@vitejs/plugin-react": "^2.0.0",
"ast-types": "^0.14.2",
"magic-string": "^0.26.1",
"react-docgen": "^6.0.0-alpha.3",
Expand Down
22 changes: 8 additions & 14 deletions code/frameworks/react-vite/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,35 @@
/* eslint-disable global-require */
import path from 'path';
import fs from 'fs';
import type { StorybookConfig, TypescriptOptions } from '@storybook/builder-vite';
import { hasPlugin, readPackageJson } from './utils';

export const addons: StorybookConfig['addons'] = ['@storybook/react'];

export const core: StorybookConfig['core'] = {
builder: '@storybook/builder-vite',
};

function readPackageJson(): Record<string, any> | false {
const packageJsonPath = path.resolve('package.json');
if (!fs.existsSync(packageJsonPath)) {
return false;
}

const jsonContent = fs.readFileSync(packageJsonPath, 'utf8');
return JSON.parse(jsonContent);
}

export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => {
const { plugins = [] } = config;

// Add react plugin if not present
if (!hasPlugin(plugins, 'vite:react-babel')) {
const { default: react } = await import('@vitejs/plugin-react');
plugins.push(react());
}

// Add docgen plugin
const { reactDocgen, reactDocgenTypescriptOptions } = await presets.apply<any>(
'typescript',
{} as TypescriptOptions
);
let typescriptPresent;

try {
const pkgJson = readPackageJson();
typescriptPresent =
pkgJson && (pkgJson.devDependencies?.typescript || pkgJson.dependencies?.typescript);
} catch (e) {
typescriptPresent = false;
}

if (reactDocgen === 'react-docgen-typescript' && typescriptPresent) {
plugins.push(
require('@joshwooding/vite-plugin-react-docgen-typescript')(reactDocgenTypescriptOptions)
Expand Down
28 changes: 28 additions & 0 deletions code/frameworks/react-vite/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import path from 'path';
import fs from 'fs';
import { PluginOption } from 'vite';

export function readPackageJson(): Record<string, any> | false {
const packageJsonPath = path.resolve('package.json');
if (!fs.existsSync(packageJsonPath)) {
return false;
}

const jsonContent = fs.readFileSync(packageJsonPath, 'utf8');
return JSON.parse(jsonContent);
}

function checkName(plugin: PluginOption, name: string) {
return typeof plugin === 'object' && 'name' in plugin && plugin.name === name;
}

export function hasPlugin(plugins: PluginOption[], name: string) {
return Boolean(
plugins.find((p): boolean => {
if (Array.isArray(p)) {
return Boolean(hasPlugin(p, name));
}
return checkName(p, name);
})
);
}
8 changes: 8 additions & 0 deletions code/frameworks/svelte-vite/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { StorybookConfig } from '@storybook/builder-vite';
import { hasPlugin } from './utils';
import { svelteDocgen } from './plugins/svelte-docgen';

export const addons: StorybookConfig['addons'] = ['@storybook/svelte'];
Expand All @@ -10,6 +11,13 @@ export const core: StorybookConfig['core'] = {
export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => {
const { plugins = [] } = config;

// Add svelte plugin if not present
if (!hasPlugin(plugins, 'vite-plugin-svelte')) {
const { svelte } = await import('@sveltejs/vite-plugin-svelte');
plugins.push(svelte());
}

// Add docgen plugin
plugins.push(svelteDocgen(config));

return {
Expand Down
16 changes: 16 additions & 0 deletions code/frameworks/svelte-vite/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { PluginOption } from 'vite';

function checkName(plugin: PluginOption, name: string) {
return typeof plugin === 'object' && 'name' in plugin && plugin.name === name;
}

export function hasPlugin(plugins: PluginOption[], name: string) {
return Boolean(
plugins.find((p): boolean => {
if (Array.isArray(p)) {
return Boolean(hasPlugin(p, name));
}
return checkName(p, name);
})
);
}
2 changes: 1 addition & 1 deletion code/frameworks/vue3-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"@storybook/core-server": "7.0.0-alpha.34",
"@storybook/preview-web": "7.0.0-alpha.34",
"@storybook/vue3": "7.0.0-alpha.34",
"@vitejs/plugin-vue": "^3.0.3",
"@vitejs/plugin-vue": "^3.0.0",
"magic-string": "^0.26.1",
"vite": "^3.1.3",
"vue-docgen-api": "^4.40.0"
Expand Down
20 changes: 8 additions & 12 deletions code/frameworks/vue3-vite/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import path from 'path';
import fs from 'fs';
import type { StorybookConfig } from '@storybook/builder-vite';
import { vueDocgen } from './plugins/vue-docgen';
import { hasPlugin } from './utils';

export const addons: StorybookConfig['addons'] = ['@storybook/vue3'];

export const core: StorybookConfig['core'] = {
builder: '@storybook/builder-vite',
};

export function readPackageJson(): Record<string, any> | false {
const packageJsonPath = path.resolve('package.json');
if (!fs.existsSync(packageJsonPath)) {
return false;
}

const jsonContent = fs.readFileSync(packageJsonPath, 'utf8');
return JSON.parse(jsonContent);
}

export const viteFinal: StorybookConfig['viteFinal'] = async (config, { presets }) => {
const { plugins = [] } = config;

// Add vue plugin if not present
if (!hasPlugin(plugins, 'vite:vue')) {
const { default: vue } = await import('@vitejs/plugin-vue');
plugins.push(vue());
}

// Add docgen plugin
plugins.push(vueDocgen());

const updated = {
Expand Down
16 changes: 16 additions & 0 deletions code/frameworks/vue3-vite/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { PluginOption } from 'vite';

function checkName(plugin: PluginOption, name: string) {
return typeof plugin === 'object' && 'name' in plugin && plugin.name === name;
}

export function hasPlugin(plugins: PluginOption[], name: string) {
return Boolean(
plugins.find((p): boolean => {
if (Array.isArray(p)) {
return Boolean(hasPlugin(p, name));
}
return checkName(p, name);
})
);
}
18 changes: 14 additions & 4 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8486,7 +8486,7 @@ __metadata:
"@storybook/preview-web": 7.0.0-alpha.34
"@storybook/react": 7.0.0-alpha.34
"@types/node": ^14.14.20 || ^16.0.0
"@vitejs/plugin-react": ^2.0.1
"@vitejs/plugin-react": ^2.0.0
ast-types: ^0.14.2
magic-string: ^0.26.1
react-docgen: ^6.0.0-alpha.3
Expand Down Expand Up @@ -9182,7 +9182,7 @@ __metadata:
"@storybook/preview-web": 7.0.0-alpha.34
"@storybook/vue3": 7.0.0-alpha.34
"@types/node": ^14.14.20 || ^16.0.0
"@vitejs/plugin-vue": ^3.0.3
"@vitejs/plugin-vue": ^3.0.0
magic-string: ^0.26.1
typescript: ~4.6.3
vite: ^3.1.3
Expand Down Expand Up @@ -11013,7 +11013,7 @@ __metadata:
languageName: node
linkType: hard

"@vitejs/plugin-react@npm:^2.0.0, @vitejs/plugin-react@npm:^2.0.1":
"@vitejs/plugin-react@npm:^2.0.0":
version: 2.1.0
resolution: "@vitejs/plugin-react@npm:2.1.0"
dependencies:
Expand All @@ -11030,7 +11030,7 @@ __metadata:
languageName: node
linkType: hard

"@vitejs/plugin-vue@npm:^3.0.3":
"@vitejs/plugin-vue@npm:^3.0.0":
version: 3.1.0
resolution: "@vitejs/plugin-vue@npm:3.1.0"
peerDependencies:
Expand All @@ -11040,6 +11040,16 @@ __metadata:
languageName: node
linkType: hard

"@vitejs/plugin-vue@npm:^3.0.3":
version: 3.1.2
resolution: "@vitejs/plugin-vue@npm:3.1.2"
peerDependencies:
vite: ^3.0.0
vue: ^3.2.25
checksum: 53867c9367f1133305e858541a9094a44c5e60d82d0c68d5eb41194dcac01ecd273252786046b3e523d40112374ac7f47558f7b292394a4529355d64b82c04cf
languageName: node
linkType: hard

"@vue/babel-helper-vue-jsx-merge-props@npm:^1.4.0":
version: 1.4.0
resolution: "@vue/babel-helper-vue-jsx-merge-props@npm:1.4.0"
Expand Down

0 comments on commit 2674cc1

Please sign in to comment.