Storybook Migration to webpackFinal

Configure webpack for Storybook

If you are looking for how you can configure webpack for Storybook, please check out our guide: How to configure Webpack and Vite for Storybook.

Nx 12.7 as in combination with Storybook v6.3 doesn't need a custom webpack.config.js which was previously required and auto-generated by Nx.

Here are the main differences to the previous setups:

  • there's no webpack.config.js
  • custom webpack configurations can be added in the webpackFinal property of the main.js file

Here's an example of a newly generated main.js file:

.storybook/main.js
1// project-level .storybook/main.js file 2const rootMain = require('../../../.storybook/main'); 3 4module.exports = { 5 ...rootMain, 6 7 core: { ...rootMain.core, builder: 'webpack5' }, 8 9 stories: [ 10 ...rootMain.stories, 11 '../src/lib/**/*.stories.mdx', 12 '../src/lib/**/*.stories.@(js|jsx|ts|tsx)', 13 ], 14 addons: [...rootMain.addons], 15 webpackFinal: async (config, { configType }) => { 16 // apply any global webpack configs that might have been specified in .storybook/main.js 17 if (rootMain.webpackFinal) { 18 config = await rootMain.webpackFinal(config, { configType }); 19 } 20 21 // add your own webpack tweaks if needed 22 23 return config; 24 }, 25}; 26

At the Nx workspace root level, the configuration file looks as follows:

.storybook/main.js
1// root level .storybook/main.js file 2module.exports = { 3 stories: [], 4 addons: ['@storybook/addon-essentials'], 5 // uncomment the property below if you want to apply some webpack config globally 6 // webpackFinal: async (config, { configType }) => { 7 // // Make whatever fine-grained changes you need that should apply to all storybook configs 8 9 // // Return the altered config 10 // return config; 11 // }, 12}; 13

Migrating

If you're upgrading from a lower version of Nx, your old Storybook configuration will still work. New configurations generated will use the new syntax as shown above. The newly generated code will also make sure to extend from a global webpack.config.js which might exist in the root-level .storybook/ directory of your Nx workspace.

This gives you the flexibility to incrementally migrate your configurations.

Here's the step-by-step migration process:

1. adjust the main.js file

Restructure your main.js file so that it looks like in the example illustrated above.

If you need to keep your root-level .storybook/webpack.config.js for now, then make sure you adjust the main.js in a way that it properly calls the root-level webpack.config.js to inherit all of the global configurations.

.storybook/webpack.config.js
1const rootMain = require('../../../.storybook/main'); 2const rootWebpackConfig = require('../../../.storybook/webpack.config'); 3 4module.exports = { 5 ...rootMain, 6 ... 7 webpackFinal: async (config) => { 8 // for backwards compatibility call the `rootWebpackConfig` 9 // this can be removed once that one is migrated fully to 10 // use the `webpackFinal` property in the `main.js` file 11 config = rootWebpackConfig({ config }); 12 13 // add your own webpack tweaks if needed 14 15 return config; 16 }, 17}; 18
Tip!

The easiest way is probably to generate a new library and Storybook configuration and then copy & paste the main.js.

2. Move any custom webpack configuration to webpackFinal

In previous versions of Nx a custom webpack.config.js was generated with the following content:

webpack.config.js
1const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 2const rootWebpackConfig = require('../../../.storybook/webpack.config'); 3/** 4 * Export a function. Accept the base config as the only param. 5 * 6 * @param {Parameters<typeof rootWebpackConfig>[0]} options 7 */ 8module.exports = async ({ config, mode }) => { 9 config = await rootWebpackConfig({ config, mode }); 10 11 const tsPaths = new TsconfigPathsPlugin({ 12 configFile: './tsconfig.base.json', 13 }); 14 15 config.resolve.plugins 16 ? config.resolve.plugins.push(tsPaths) 17 : (config.resolve.plugins = [tsPaths]); 18 19 return config; 20}; 21

Such webpack file is no more needed as Storybook v6.3+ has proper TypeScript support already built-in now.

In case you made custom modifications to the webpack.config.js file, you need to move them over to the main.js webpackFinal property and then delete the webpack.config.js.

3. Remove the root-level .storybook/webpack.config.js file

Once you've migrated all your libraries, you can think about removing the root-level .storybook/webpack.config.js file and migrate any custom configuration there to .storybook/main.js webpackFinal property in the very same folder.

4. Opting in to Webpack 5

If you choose to opt-in to Webpack 5, by specifying builder: 'webpack5' in your project's .storybook/main.(js|ts) (as shown above, in the example of a newly generated main.js file), don't forget to add the Storybook dependencies for Webpack 5 to work:

โฏ

npm add -D @storybook/builder-webpack5 @storybook/manager-webpack5