From 6d9c90c0d4eed8f2dd73759bfd64547e4fdbfac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ovidiu=20Chereche=C8=99?= Date: Wed, 5 Apr 2023 12:20:44 +0300 Subject: [PATCH] Automatically enable webpack top level await (#1433) --- docs/MIGRATION_V6.md | 1 - .../webpackConfig/__tests__/customDevConfig.ts | 5 +++++ .../webpackConfig/__tests__/customExportConfig.ts | 5 +++++ .../webpackConfig/__tests__/defaultDevConfig.ts | 5 +++++ .../webpackConfig/__tests__/defaultExportConfig.ts | 5 +++++ .../src/server/webpackConfig/getDevWebpackConfig.ts | 6 ++++++ .../server/webpackConfig/getExportWebpackConfig.ts | 6 ++++++ .../webpackConfig/webpackConfigTopLevelAwait.ts | 12 ++++++++++++ packages/react-cosmos-ui/webpack.config.cosmos.js | 3 --- website/webpack.config.js | 3 --- 10 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 packages/react-cosmos-plugin-webpack/src/server/webpackConfig/webpackConfigTopLevelAwait.ts diff --git a/docs/MIGRATION_V6.md b/docs/MIGRATION_V6.md index 0379e3fa6b..9e469a6e3d 100644 --- a/docs/MIGRATION_V6.md +++ b/docs/MIGRATION_V6.md @@ -62,7 +62,6 @@ React Cosmos 6 also comes with a brand new Vite plugin. To set up a Vite codebas - `NativeFixtureLoader` component moved from `react-cosmos/native` to new `react-cosmos-native` package. Install `react-cosmos-native@next` as well for a React Native setup. - `getFixtures2()` renamed to `getFixtures()`. - `getCosmosConfigAtPath()` is now async. To replicate the old sync behavior, require() the config module manually and pass it to `createCosmosConfig()`. -- `experiments.topLevelAwait` webpack setting is required when using a custom webpack config (see example [here](https://github.com/react-cosmos/react-cosmos/blob/88f992bbcbf954fd8b4b672362efd0d50fcb9885/packages/react-cosmos-ui/webpack.config.cosmos.js#L44-L46)). - For visual regression testing you may need to make Jest transpile Cosmos modules by adding `"/node_modules/react-cosmos"` to `transformIgnorePatterns` in your Jest config. There might be some other subtle breaking changes, especially if you're implementing a custom Cosmos renderer or if you're integrated with a bundler other than webpack. Create an issue or send us a message on [Discord](https://discord.gg/3X95VgfnW5) if this is the case and we'll do our best to help you with the migration. diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customDevConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customDevConfig.ts index e0bd340a84..8de9ace23c 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customDevConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customDevConfig.ts @@ -135,3 +135,8 @@ it('includes HotModuleReplacementPlugin', async () => { ); expect(hotModuleReplacementPlugin).toBeDefined(); }); + +it('sets experiments.topLevelAwait to true', async () => { + const { experiments } = await getCustomDevWebpackConfig(); + expect(experiments?.topLevelAwait).toBe(true); +}); diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customExportConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customExportConfig.ts index 93a61c213a..d1aedd6d28 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customExportConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/customExportConfig.ts @@ -106,3 +106,8 @@ it('does not include HotModuleReplacementPlugin', async () => { ); expect(hotModuleReplacementPlugin).not.toBeDefined(); }); + +it('sets experiments.topLevelAwait to true', async () => { + const { experiments } = await getCustomExportWebpackConfig(); + expect(experiments?.topLevelAwait).toBe(true); +}); diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultDevConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultDevConfig.ts index 9650e68dee..438c8742e1 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultDevConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultDevConfig.ts @@ -77,3 +77,8 @@ it('includes HotModuleReplacementPlugin', async () => { ); expect(hotModuleReplacementPlugin).toBeDefined(); }); + +it('sets experiments.topLevelAwait to true', async () => { + const { experiments } = await getDefaultDevWebpackConfig(); + expect(experiments?.topLevelAwait).toBe(true); +}); diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultExportConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultExportConfig.ts index 89cc2d8069..747b470590 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultExportConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/__tests__/defaultExportConfig.ts @@ -82,3 +82,8 @@ it('does not include HotModuleReplacementPlugin', async () => { ); expect(hotModuleReplacementPlugin).not.toBeDefined(); }); + +it('sets experiments.topLevelAwait to true', async () => { + const { experiments } = await getDefaultExportWebpackConfig(); + expect(experiments?.topLevelAwait).toBe(true); +}); diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getDevWebpackConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getDevWebpackConfig.ts index 8478550b7d..dc95a8ab4f 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getDevWebpackConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getDevWebpackConfig.ts @@ -9,6 +9,7 @@ import { getWebpackConfigResolve } from './getWebpackConfigResolve.js'; import { ensureHtmlWebackPlugin } from './htmlPlugin.js'; import { getGlobalsPlugin, hasPlugin } from './plugins.js'; import { resolveWebpackClientPath } from './resolveWebpackClientPath.js'; +import { ensureWebpackConfigTopLevelAwait } from './webpackConfigTopLevelAwait.js'; export async function getDevWebpackConfig( cosmosConfig: CosmosConfig, @@ -26,6 +27,7 @@ export async function getDevWebpackConfig( module: getWebpackConfigModule(baseWebpackConfig), resolve: getWebpackConfigResolve(cosmosConfig, baseWebpackConfig), plugins: getPlugins(cosmosConfig, baseWebpackConfig, userWebpack), + experiments: getExperiments(baseWebpackConfig), }; // optimization.splitChunks.name = false breaks auto fixture file discovery. @@ -92,3 +94,7 @@ function getHotMiddlewareEntry(reloadOnFail: boolean) { const clientPath = resolve('webpack-hot-middleware/client'); return `${clientPath}?reload=${reloadOnFail}&overlay=false`; } + +function getExperiments(baseWebpackConfig: webpack.Configuration) { + return ensureWebpackConfigTopLevelAwait(baseWebpackConfig); +} diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getExportWebpackConfig.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getExportWebpackConfig.ts index 0cce343a2d..9a72bc5e1b 100644 --- a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getExportWebpackConfig.ts +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/getExportWebpackConfig.ts @@ -9,6 +9,7 @@ import { getWebpackConfigResolve } from './getWebpackConfigResolve.js'; import { ensureHtmlWebackPlugin } from './htmlPlugin.js'; import { getGlobalsPlugin } from './plugins.js'; import { resolveWebpackClientPath } from './resolveWebpackClientPath.js'; +import { ensureWebpackConfigTopLevelAwait } from './webpackConfigTopLevelAwait.js'; export async function getExportWebpackConfig( cosmosConfig: CosmosConfig, @@ -25,6 +26,7 @@ export async function getExportWebpackConfig( module: getWebpackConfigModule(baseWebpackConfig), resolve: getWebpackConfigResolve(cosmosConfig, baseWebpackConfig), plugins: getPlugins(cosmosConfig, baseWebpackConfig, userWebpack), + experiments: getExperiments(baseWebpackConfig), }; } @@ -65,3 +67,7 @@ function getPlugins( noEmitErrorsPlugin, ]); } + +function getExperiments(baseWebpackConfig: webpack.Configuration) { + return ensureWebpackConfigTopLevelAwait(baseWebpackConfig); +} diff --git a/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/webpackConfigTopLevelAwait.ts b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/webpackConfigTopLevelAwait.ts new file mode 100644 index 0000000000..72a257551d --- /dev/null +++ b/packages/react-cosmos-plugin-webpack/src/server/webpackConfig/webpackConfigTopLevelAwait.ts @@ -0,0 +1,12 @@ +import webpack from 'webpack'; + +export function ensureWebpackConfigTopLevelAwait( + baseWebpackConfig: webpack.Configuration +): webpack.Configuration['experiments'] { + const experiments = baseWebpackConfig.experiments || {}; + if (!experiments.topLevelAwait) { + experiments.topLevelAwait = true; + } + + return experiments; +} diff --git a/packages/react-cosmos-ui/webpack.config.cosmos.js b/packages/react-cosmos-ui/webpack.config.cosmos.js index fe3890694c..4624bcef69 100644 --- a/packages/react-cosmos-ui/webpack.config.cosmos.js +++ b/packages/react-cosmos-ui/webpack.config.cosmos.js @@ -44,7 +44,4 @@ export default { title: 'React Cosmos', }), ], - experiments: { - topLevelAwait: true, - }, }; diff --git a/website/webpack.config.js b/website/webpack.config.js index 748fb27da9..482ac3bb40 100644 --- a/website/webpack.config.js +++ b/website/webpack.config.js @@ -65,9 +65,6 @@ export default async () => { optimization: { minimize: false, }, - experiments: { - topLevelAwait: true, - }, }; if (env === 'development') {