Skip to content

Commit

Permalink
feat(storybook): add adapter for babel and webpack
Browse files Browse the repository at this point in the history
  • Loading branch information
JSerFeng committed Nov 14, 2023
1 parent 43df7e3 commit 3b7c09f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 73 deletions.
6 changes: 6 additions & 0 deletions .changeset/hungry-balloons-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@modern-js/storybook-builder': patch
---

feat(storybook): add adapter for storybook addons
feat(storybook): 为 storybook addons 添加一些适配逻辑
71 changes: 0 additions & 71 deletions packages/storybook/builder/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { createBuilder } from '@modern-js/builder';
import { loadConfig } from '@modern-js/core';
import type { Options } from '@storybook/types';
import type { Compiler } from '@modern-js/builder-shared/webpack-dev-middleware';
import type { PluginItem } from '@babel/core';
import { applyOptionsChain, logger } from '@modern-js/utils';
import type { BuilderConfig, BuilderOptions } from './types';
import { getConfigFileName, getProvider, runWithErrorMsg } from './utils';
import { pluginStorybook } from './plugin-storybook';
Expand All @@ -29,8 +27,6 @@ export async function getCompiler(
(await presets.apply<BuilderConfig | void>('modern', loadedConfig)) ||
loadedConfig;

await addonAdapter(finalConfig, options);

const provider = await getProvider(bundler, finalConfig);

if (!provider) {
Expand All @@ -53,70 +49,3 @@ export async function getCompiler(

return builder.createCompiler() as Promise<Compiler>;
}

/**
* Some addons expose babel plugins and presets, or modify webpack
*/
async function addonAdapter(finalConfig: BuilderConfig, options: Options) {
const { presets } = options;
const babelOptions = await presets.apply('babel', {}, { ...options });

finalConfig.tools ??= {};
finalConfig.tools.babel = config => {
const getPluginName = (plugin: PluginItem) =>
Array.isArray(plugin) ? plugin[0] : plugin;
const getOptions = (plugin: PluginItem) =>
Array.isArray(plugin) ? plugin[1] : null;

const replaceOrInsert = (plugin: PluginItem, plugins: PluginItem[]) => {
const pluginName = getPluginName(plugin);

const append = [];
for (let i = 0; i < plugins.length; i++) {
if (getPluginName(plugins[i]) === pluginName) {
if (getOptions(plugin)) {
logger.info(
'Detected duplicated babel plugin, overrides with the new one',
);
plugins[i] = plugin;
}
} else {
append.push(plugin);
}
}

plugins.push(...append);
};

const currentPlugins = config.plugins || [];

// O(n * n) but the number of plugins should be small
for (const plugin of babelOptions.plugins || []) {
replaceOrInsert(plugin, currentPlugins);
}

return {
...config,
...babelOptions,
plugins: currentPlugins,
presets: config.presets,
};
};

finalConfig.tools ??= {};

// @ts-expect-error tools.webpack not present in rspack config, but it's OK, we only
// adapt webpack addon now
finalConfig.tools.webpack = applyOptionsChain(
// @ts-expect-error tools.webpack not present in rspack config, but it's OK, we only
finalConfig.tools.webpack,
async (defaultConfig: any) => {
const finalDefaultConfig = await presets.apply(
'webpackFinal',
defaultConfig,
options,
);
return finalDefaultConfig;
},
);
}
78 changes: 76 additions & 2 deletions packages/storybook/builder/src/plugin-storybook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/* eslint-disable max-lines */
import { isAbsolute, join, resolve } from 'path';
import { slash, watch, globby, applyOptionsChain } from '@modern-js/utils';
import {
slash,
watch,
globby,
applyOptionsChain,
logger,
} from '@modern-js/utils';
import {
BuilderPlugin,
SharedBuilderConfig,
Expand All @@ -22,7 +28,7 @@ import {
loadPreviewOrConfigFile,
} from '@storybook/core-common';
import { globals } from '@storybook/preview/globals';

import type { PluginItem } from '@babel/core';
import type {
BuilderPluginAPI as WebpackAPI,
WebpackConfig,
Expand Down Expand Up @@ -119,6 +125,8 @@ export const pluginStorybook: (
};

if ('modifyWebpackConfig' in api) {
addonAdapter(api, options);

api.modifyWebpackConfig(modifyConfig);
api.modifyWebpackChain(async chain => {
await applyDocgenWebpack(chain, options);
Expand Down Expand Up @@ -472,3 +480,69 @@ async function watchStories(
);
return watcher;
}

/**
* Some addons expose babel plugins and presets, or modify webpack
*/
async function addonAdapter(api: WebpackAPI | RspackAPI, options: Options) {
const { presets } = options;

api.modifyBuilderConfig(async finalConfig => {
const babelOptions = await presets.apply('babel', {}, { ...options });
finalConfig.tools ??= {};
finalConfig.tools.babel ??= {};
finalConfig.tools.babel = config => {
const getPluginName = (plugin: PluginItem) =>
Array.isArray(plugin) ? plugin[0] : plugin;
const getOptions = (plugin: PluginItem) =>
Array.isArray(plugin) ? plugin[1] : null;

const replaceOrInsert = (plugin: PluginItem, plugins: PluginItem[]) => {
const pluginName = getPluginName(plugin);

const append = [];
for (let i = 0; i < plugins.length; i++) {
if (getPluginName(plugins[i]) === pluginName) {
if (getOptions(plugin)) {
logger.info(
'Detected duplicated babel plugin, overrides with the new one',
);
plugins[i] = plugin;
}
} else {
append.push(plugin);
}
}

plugins.push(...append);
};

const currentPlugins = config.plugins || [];

// O(n * n) but the number of plugins should be small
for (const plugin of babelOptions.plugins || []) {
replaceOrInsert(plugin, currentPlugins);
}

return {
...config,
...babelOptions,
plugins: currentPlugins,
presets: config.presets,
overrides: [
...(config.overrides || []),
...(babelOptions.overrides || []),
],
};
};
});

(api as WebpackAPI).modifyWebpackConfig(async config => {
const finalDefaultConfig = await presets.apply(
'webpackFinal',
config,
options,
);
return finalDefaultConfig;
});
}

0 comments on commit 3b7c09f

Please sign in to comment.