Skip to content

Commit

Permalink
Add webpack5-compiler automigration
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinpalkovic committed Feb 8, 2024
1 parent c125ec6 commit f18d9d3
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 2 deletions.
105 changes: 105 additions & 0 deletions code/lib/cli/src/automigrate/fixes/webpack5-compiler-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import execa from 'execa';
import prompts from 'prompts';
import type { SupportedFrameworks } from '@storybook/types';
import { frameworkPackages } from '@storybook/core-common';
import type { Fix } from '../types';
import { getFrameworkPackageName } from '../helpers/mainConfigFile';
import { frameworkToDefaultBuilder } from '../../helpers';
import { CoreBuilder } from '../../project_types';

type Options = {
shouldAddSWC: boolean;
shouldRemoveSWCFlag: boolean;
isNextJs: boolean;
};

export const webpack5Migration: Fix<Options> = {
id: 'webpack5-compiler-setup',

async check({ mainConfig, packageManager }) {
const frameworkPackageName = getFrameworkPackageName(mainConfig);
const frameworkName = Object.entries(frameworkPackages).find(
([name]) => name === frameworkPackageName
)?.[1];

const builder = frameworkName
? // TODO: Consider using also custom builders
frameworkToDefaultBuilder[frameworkName]
: await (async () => {
const webpackVersion = await packageManager.getPackageVersion('webpack');
return !!webpackVersion ? CoreBuilder.Webpack5 : CoreBuilder.Vite;
})();

if (builder !== CoreBuilder.Webpack5) {
return null;
}

const excludedFrameworks: SupportedFrameworks[] = ['angular', 'ember', 'nextjs'];

const isExcludedFramework = frameworkName ? excludedFrameworks.includes(frameworkName) : false;

if (isExcludedFramework) {
return null;
}

const usesSWC = mainConfig.framework?.options?.builder?.useSWC;

if (!isExcludedFramework) {
return {
shouldAddSWC: usesSWC === true,
shouldRemoveSWCFlag: 'useSWC' in mainConfig.framework?.options?.builder,
isNextJs: packageManager.type === 'next.js',
};
}

return {};
},

async prompt({ shouldAddSWC, shouldRemoveSWCFlag, isNextJs }) {
let message = 'We need to update your Storybook configuration for Webpack 5.\n';
if (shouldRemoveSWCFlag) {
message += 'The "frameworks.options.builder.useSWC" flag will be removed.\n';
}

if (shouldAddSWC !== undefined) {
const addonName = shouldAddSWC
? '@storybook/addon-webpack5-compiler-swc'
: '@storybook/addon-webpack5-compiler-babel';
message += `The "${addonName}" will be added to your project.\n`;

message +=
'After the migration, you can switch compilers if needed by manually adding the alternative addon.';
}

if (isNextJs) {
message += 'Next.js-specific migrations will be applied.';
}

return message;
},

async run({ result, mainConfigPath, dryRun }) {
const { shouldAddSWC, shouldRemoveSWCFlag, isNextJs } = result;

if (shouldRemoveSWCFlag && !dryRun) {
// Logic for remove `frameworks.options.builder.useSWC` from mainConfig
}

if (shouldAddSWC !== undefined && !dryRun) {
const compiler = shouldAddSWC ? 'swc' : 'babel';
const addonName = `@storybook/addon-webpack5-compiler-${compiler}`;
const command = `npx storybook@next add ${addonName}`;

try {
await execa.command(command, { stdio: 'inherit' });
} catch (error) {
console.error(`Failed to install ${addonName}`, error);
throw new Error(`Failed to install ${addonName}`);
}
}

if (isNextJs && !dryRun) {
// Next.js-specific migration logic
}
},
};
4 changes: 2 additions & 2 deletions code/lib/cli/src/automigrate/helpers/mainConfigFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const logger = console;

/**
* Given a Storybook configuration object, retrieves the package name or file path of the framework.
* @param mainConfig - The main Storybook configuration object to lookup.
* @returns - The package name of the framework. If not found, returns null.
* @param mainConfig The main Storybook configuration object to lookup.
* @returns The package name of the framework. If not found, returns null.
*/
export const getFrameworkPackageName = (mainConfig?: StorybookConfigRaw) => {
const packageNameOrPath =
Expand Down
25 changes: 25 additions & 0 deletions code/lib/cli/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
} from '@storybook/core-common';
import type { SupportedFrameworks } from '@storybook/types';
import type { SupportedRenderers } from './project_types';
import { CoreBuilder } from './project_types';
import { SupportedLanguage } from './project_types';
import { versions as storybookMonorepoPackages } from '@storybook/core-common';

Expand Down Expand Up @@ -168,6 +169,30 @@ const frameworkToRenderer: Record<
'web-components': 'web-components',
};

export const frameworkToDefaultBuilder: Record<SupportedFrameworks, CoreBuilder> = {
angular: CoreBuilder.Webpack5,
ember: CoreBuilder.Webpack5,
'html-vite': CoreBuilder.Vite,
'html-webpack5': CoreBuilder.Webpack5,
nextjs: CoreBuilder.Webpack5,
'preact-vite': CoreBuilder.Vite,
'preact-webpack5': CoreBuilder.Webpack5,
qwik: CoreBuilder.Vite,
'react-vite': CoreBuilder.Vite,
'react-webpack5': CoreBuilder.Webpack5,
'server-webpack5': CoreBuilder.Webpack5,
solid: CoreBuilder.Vite,
'svelte-vite': CoreBuilder.Vite,
'svelte-webpack5': CoreBuilder.Webpack5,
sveltekit: CoreBuilder.Vite,
'vue-vite': CoreBuilder.Vite,
'vue-webpack5': CoreBuilder.Webpack5,
'vue3-vite': CoreBuilder.Vite,
'vue3-webpack5': CoreBuilder.Webpack5,
'web-components-vite': CoreBuilder.Vite,
'web-components-webpack5': CoreBuilder.Webpack5,
};

export async function copyTemplateFiles({
packageManager,
renderer,
Expand Down

0 comments on commit f18d9d3

Please sign in to comment.