Skip to content

Commit

Permalink
Merge pull request #17829 from storybookjs/feat/add-vite-builder-auto…
Browse files Browse the repository at this point in the history
…migration

CLI: Add automigration to `@storybook/builder-vite`
  • Loading branch information
shilman committed Mar 31, 2022
2 parents a0a2a8b + 6d847d6 commit 55ae2c3
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 1 deletion.
11 changes: 11 additions & 0 deletions MIGRATION.md
@@ -1,6 +1,7 @@
<h1>Migration</h1>

- [From version 6.4.x to 6.5.0](#from-version-64x-to-650)
- [Vite builder renamed](#vite-builder-renamed)
- [Docs framework refactor for React](#docs-framework-refactor-for-react)
- [Opt-in MDX2 support](#opt-in-mdx2-support)
- [CSF3 auto-title improvements](#csf3-auto-title-improvements)
Expand Down Expand Up @@ -196,6 +197,16 @@

## From version 6.4.x to 6.5.0

### Vite builder renamed

SB6.5 renames Storybook's [Vite builder](https://github.com/storybookjs/builder-vite) from `storybook-builder-vite` to `@storybook/builder-vite`. This move is part of a larger effort to improve Vite support in Storybook.

Storybook's `automigrate` command can migrate for you. To manually migrate:

1. Remove `storybook-builder-vite` from your `package.json` dependencies
2. Install `@storybook/builder-vite`
3. Update your `core.builder` setting in `.storybook/main.js` to `@storybook/builder-vite`.

### Docs framework refactor for React

SB6.5 moves framework specializations (e.g. ArgType inference, dynamic snippet rendering) out of `@storybook/addon-docs` and into the specific framework packages to which they apply (e.g. `@storybook/react`).
Expand Down
52 changes: 52 additions & 0 deletions lib/cli/src/automigrate/fixes/builder-vite.test.ts
@@ -0,0 +1,52 @@
/* eslint-disable no-underscore-dangle */
import path from 'path';
import { JsPackageManager } from '../../js-package-manager';
import { builderVite } from './builder-vite';

// eslint-disable-next-line global-require, jest/no-mocks-import
jest.mock('fs-extra', () => require('../../../../../__mocks__/fs-extra'));

const checkBuilderVite = async ({ packageJson = {}, main }) => {
// eslint-disable-next-line global-require
require('fs-extra').__setMockFiles({
[path.join('.storybook', 'main.js')]: `module.exports = ${JSON.stringify(main)};`,
});
const packageManager = {
retrievePackageJson: () => ({ dependencies: {}, devDependencies: {}, ...packageJson }),
} as JsPackageManager;
return builderVite.check({ packageManager });
};

describe('builder-vite fix', () => {
describe('storybook-builder-vite', () => {
it('using storybook-builder-vite', async () => {
const main = { core: { builder: 'storybook-builder-vite' } };
await expect(checkBuilderVite({ main })).resolves.toMatchObject({
builder: 'storybook-builder-vite',
});
});
it('using storybook-builder-vite with options', async () => {
const main = { core: { builder: { name: 'storybook-builder-vite', options: {} } } };
await expect(checkBuilderVite({ main })).resolves.toMatchObject({
builder: {
name: 'storybook-builder-vite',
options: {},
},
});
});
});
describe('other builders', () => {
it('using @storybook/builder-vite', async () => {
const main = { core: { builder: { name: '@storybook/builder-vite', options: {} } } };
await expect(checkBuilderVite({ main })).resolves.toBeFalsy();
});
it('using webpack5', async () => {
const main = { core: { builder: 'webpack5' } };
await expect(checkBuilderVite({ main })).resolves.toBeFalsy();
});
it('no builder specified', async () => {
const main = {};
await expect(checkBuilderVite({ main })).resolves.toBeFalsy();
});
});
});
94 changes: 94 additions & 0 deletions lib/cli/src/automigrate/fixes/builder-vite.ts
@@ -0,0 +1,94 @@
import chalk from 'chalk';
import dedent from 'ts-dedent';

import { ConfigFile, readConfig, writeConfig } from '@storybook/csf-tools';

import { Fix } from '../types';
import { getStorybookInfo } from '../helpers/getStorybookInfo';
import { PackageJson, writePackageJson } from '../../js-package-manager';

const logger = console;

interface BuilderViteOptions {
builder: any;
main: ConfigFile;
packageJson: PackageJson;
}

/**
* Is the user using 'storybook-builder-vite' in their project?
*
* If so, prompt them to upgrade to '@storybook/builder-vite'.
*
* - Add '@storybook/builder-vite' as dev dependency
* - Remove 'storybook-builder-vite' dependency
* - Add core.builder = '@storybook/builder-vite' to main.js
*/
export const builderVite: Fix<BuilderViteOptions> = {
id: 'builder-vite',

async check({ packageManager }) {
const packageJson = packageManager.retrievePackageJson();
const { mainConfig } = getStorybookInfo(packageJson);
if (!mainConfig) {
logger.warn('Unable to find storybook main.js config');
return null;
}
const main = await readConfig(mainConfig);
const builder = main.getFieldValue(['core', 'builder']);
const builderName = typeof builder === 'string' ? builder : builder?.name;

if (builderName !== 'storybook-builder-vite') {
logger.info(`Not using community vite builder, skipping`);
return null;
}

return { builder, main, packageJson };
},

prompt({ builder }) {
const builderFormatted = chalk.cyan(JSON.stringify(builder, null, 2));

return dedent`
We've detected you're using the community vite builder: ${builderFormatted}
'storybook-builder-vite' is deprecated and now located at ${chalk.cyan(
'@storybook/builder-vite'
)}.
We can upgrade your project to use the new builder automatically.
More info: ${chalk.yellow(
'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#vite-builder-renamed'
)}
`;
},

async run({ result: { builder, main, packageJson }, packageManager, dryRun }) {
const { dependencies = {}, devDependencies = {} } = packageJson;

logger.info(`Removing existing 'storybook-builder-vite' dependency`);
if (!dryRun) {
delete dependencies['storybook-builder-vite'];
delete devDependencies['storybook-builder-vite'];
writePackageJson(packageJson);
}

logger.info(`Adding '@storybook/builder-vite' as dev dependency`);
if (!dryRun) {
packageManager.addDependencies({ installAsDevDependencies: true }, [
'@storybook/builder-vite',
]);
}

logger.info(`Updating main.js to use vite builder`);
if (!dryRun) {
const updatedBuilder =
typeof builder === 'string'
? '@storybook/builder-vite'
: { name: '@storybook/builder-vite', options: builder.options };
main.setFieldValue(['core', 'builder'], updatedBuilder);
await writeConfig(main);
}
},
};
3 changes: 2 additions & 1 deletion lib/cli/src/automigrate/fixes/index.ts
Expand Up @@ -3,7 +3,8 @@ import { webpack5 } from './webpack5';
import { angular12 } from './angular12';
import { mainjsFramework } from './mainjsFramework';
import { eslintPlugin } from './eslint-plugin';
import { builderVite } from './builder-vite';
import { Fix } from '../types';

export * from '../types';
export const fixes: Fix[] = [cra5, webpack5, angular12, mainjsFramework, eslintPlugin];
export const fixes: Fix[] = [cra5, webpack5, angular12, mainjsFramework, eslintPlugin, builderVite];

0 comments on commit 55ae2c3

Please sign in to comment.