/
framework-preset-react.ts
98 lines (87 loc) · 2.9 KB
/
framework-preset-react.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import path from 'path';
import { TransformOptions } from '@babel/core';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import type { Configuration } from 'webpack';
import { logger } from '@storybook/node-logger';
import type { Options } from '@storybook/core-common';
export async function babel(config: TransformOptions, options: Options) {
const isDevelopment = options.configType === 'DEVELOPMENT';
const reactOptions = await options.presets.apply(
'reactOptions',
{} as {
fastRefresh?: boolean;
},
options
);
const fastRefreshEnabled =
isDevelopment && (reactOptions.fastRefresh || process.env.FAST_REFRESH === 'true');
if (!fastRefreshEnabled) {
return config;
}
return {
...config,
plugins: [
[require.resolve('react-refresh/babel'), {}, 'storybook-react-refresh'],
...(config.plugins || []),
],
};
}
const storybookReactDirName = path.dirname(require.resolve('@storybook/react/package.json'));
// TODO: improve node_modules detection
const context = storybookReactDirName.includes('node_modules')
? path.join(storybookReactDirName, '../../') // Real life case, already in node_modules
: path.join(storybookReactDirName, '../../node_modules'); // SB Monorepo
const hasJsxRuntime = () => {
try {
require.resolve('react/jsx-runtime', { paths: [context] });
return true;
} catch (e) {
return false;
}
};
export async function babelDefault(config: TransformOptions): Promise<TransformOptions> {
const presetReactOptions = hasJsxRuntime() ? { runtime: 'automatic' } : {};
return {
...config,
presets: [
...(config?.presets || []),
[require.resolve('@babel/preset-react'), presetReactOptions],
require.resolve('@babel/preset-flow'),
],
plugins: [...(config?.plugins || []), require.resolve('babel-plugin-add-react-displayname')],
};
}
export async function webpackFinal(config: Configuration, options: Options) {
const isDevelopment = options.configType === 'DEVELOPMENT';
const reactOptions = await options.presets.apply(
'reactOptions',
{} as {
fastRefresh?: boolean;
},
options
);
const fastRefreshEnabled =
isDevelopment && (reactOptions.fastRefresh || process.env.FAST_REFRESH === 'true');
if (!fastRefreshEnabled) {
return config;
}
// matches the name of the plugin in CRA.
const hasReactRefresh = config.plugins.find((p) => p.constructor.name === 'ReactRefreshPlugin');
if (hasReactRefresh) {
logger.warn("=> React refresh is already set. You don't need to set the option");
return config;
}
logger.info('=> Using React fast refresh');
return {
...config,
plugins: [
...config.plugins,
// Storybook uses webpack-hot-middleware https://github.com/storybookjs/storybook/issues/14114
new ReactRefreshWebpackPlugin({
overlay: {
sockIntegration: 'whm',
},
}),
],
};
}