Upgrade to Webpack 5 breaking Storybook 5
Asked Answered
B

4

14

In process of upgrading a webpack 4/storybook 5 project to webpack 5 to hopefully take advantage of federated modules. I have regular webpack --config webpack.config.js building working atfer some struggle, but I can't seem to overcome this storybook config issue to get that working. there's not a lot in the storybook webpack.config.js - just some module rules for testing for less files and using the appropriate loaders. It seems the error I'm encountering is typical when upgrading webpack majors, as I've found a number of folks that encountered the same thing going from 3-4, but anything I've tried has failed so far. The specific stacktrace is:

Cannot read property 'tapAsync' of undefined
    at ExternalModuleFactoryPlugin.apply (/Users/tbullard/Workspace/unify/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js:29:39)
    at compiler.hooks.compile.tap (/Users/tbullard/Workspace/unify/node_modules/webpack/lib/ExternalsPlugin.js:24:63)
    at SyncHook.eval [as call] (eval at create (/Users/tbullard/Workspace/unify/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
    at SyncHook.lazyCompileHook (/Users/tbullard/Workspace/unify/node_modules/tapable/lib/Hook.js:154:20)
    at hooks.beforeCompile.callAsync.err (/Users/tbullard/Workspace/unify/node_modules/@storybook/core/node_modules/webpack/lib/Compiler.js:665:23)
    at _err0 (eval at create (/Users/tbullard/Workspace/unify/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at compiler.inputFileSystem.readFile (/Users/tbullard/Workspace/unify/node_modules/@storybook/core/node_modules/webpack/lib/DllReferencePlugin.js:72:15)
    at process.nextTick (/Users/tbullard/Workspace/unify/node_modules/@storybook/core/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:85:15)
    at process._tickCallback (internal/process/next_tick.js:61:11)

Leads me to believe there's a plugin incompatibility πŸ€·πŸ»β€β™‚οΈ TIA!

Burushaski answered 22/4, 2020 at 21:48 Comment(1)
Storybook is a fully self-contained solution, don't update its dependencies manually, just update it. (and right now, looking at its config because it's open source and I encourage you to do the same, it's set up work with webpack 4, not 5. Remember: in semver a major version change means it's backward incompatible and will break things) – Realism
M
9

As of 6.2.0, Storybook's preview builder is officially Webpack 5 compatible and the manager builder is unofficially Webpack 5 compatible. See this explanation of the builders and Webpack 5 compatibility. Also check out this gist/comments section with more detailed installation instructions.

If I understand correctly, setting the builder to Webpack 5 (as per these instructions) will force the preview builder to use Webpack 5, allowing you to expose your UI components for cool, new Webpack 5 features such as module federation.

However, if you also want to force the manager builder to use Webpack 5 (so that you can just finish breaking up with Webpack 4), you'll need to make use of Yarn selective dependency resolutions. Here is what I did specifically (in a package.json):

"resolutions": {
    "webpack": "^5.27.2",
    "css-loader": "^5.0.1",
    "dotenv-webpack": "^7.0.2",
    "html-webpack-plugin": "^5.0.0",
    "style-loader": "^2.0.0",
    "terser-webpack-plugin": "^5.1.1",
    "webpack-dev-middleware": "^4.1.0",
    "webpack-virtual-modules": "^0.4.2"
  }

With these resolutions, Yarn detects that Webpack 4 is no longer used and removes it. The SB build gives this warning:

info @storybook/react v6.2.0-rc.10
info 
info => Loading presets
WARN Unexpected webpack version in manager-builder
WARN - Received: 5.27.2
WARN - Expected: 4.x

One of the tasks of migrating from Webpack 4 to 5 involves manually providing browser polyfills for node packages which were automatically provided by Webpack 4. I want to note that if you find yourself manually providing a ton of polyfills while upgrading Storybook to Webpack 5, you have probably gotten off in the wrong direction. The Storybook dev-server builds get cached in a local (to the package where Storybook is installed) node_modules directory (whatever-package/node_modules/.cache/storybook/dev-server). Deleting the dev-server sub-directory regularly can help you debug your build and potentially spare you from building out long lists of unnecessary node polyfills. (I learned this the hard way).

With that said, for a cleanish install of Storybook you might not actually need any polyfills. On the other hand, some cases do require the node polyfills (e.g. @storybook/addon-docs requires "assert" (see below)). Here is one way to add polyfills (and addons, if you want) to Storybook's Webpack config in main.js:

module.exports = {
  core: {
    builder: 'webpack5',
  },
  stories: ['../whatever/src/**/*.stories.@(ts|tsx)'],
  addons: [
    '@storybook/addon-actions',
    '@storybook/addon-controls',
    '@storybook/addon-docs',
  ],
  webpackFinal: (config) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        fallback: {
          ...config.fallback,
          assert: require.resolve('assert-browserify/'),
        },
      },
    };
  },
};

Re: addons, I had serious issues with node polyfills when attempting to use addon-essentials. I've been... adding... addons piecemeal instead (standalone packages via npm), and that seems to be working without any polyfills (@storybook/actions and @storybook/controls are good oob; @storybook/docs requires the assert polyfill (above), @storybook/addons is also working fine with theming in manager.ts---that is:

import { addons } from '@storybook/addons';
import { themes } from '@storybook/theming';

addons.setConfig({
  theme: themes.dark,
}); 

I also want to note that adding sass-loader to Webpack config.module.rules works as expected. Some people were running into problems with some scss preset with Storybook and Webpack 5. Here's the relevant portion of a proper Storybook Webpack config for Sass:

 module: {
        ...config.module,
        rules: [
          ...config.module.rules,
          {
            test: /\.(scss)$/,
            use: [
              {
                loader: 'style-loader',
              },
              {
                loader: 'css-loader',
              },
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: function () {
                      return [require('precss'), require('autoprefixer')];
                    },
                  },
                },
              },
              {
                loader: require.resolve('sass-loader'),
                options: {
                  // using sass (Dart) instead of node-sass because node-sass (Javascript) cannot resolve Yarn 2's Plug'N'Play synthetic node_modules directory
                  // Evidently, sass is a bit slower to compile than node-sass, but I think I prefer sass anyway for latest features (such as @use)
                  implementation: require('sass'),
                },
              },
            ],
          },
        ],
      },

Hope that will get you off the ground πŸ›«

Massy answered 26/3, 2021 at 22:22 Comment(1)
Thank you for writing all of this out, it's clear, informative, and comprehensive. – Hauptmann
T
7

Storybook is not yet ready to work with Webpack 5 but it is on their roadmap for version 7.0.

More context in this GitHub issue.

Topography answered 2/6, 2020 at 9:29 Comment(0)
S
1

Upgrading webpack v4 to v5 in storybook v6. check the below link for detailed explanation.

https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#webpack-5

   "@storybook/builder-webpack5": "^6.5.15",
   "@storybook/manager-webpack5": "^6.5.15",
Safar answered 23/1, 2023 at 15:29 Comment(1)
Thanks for the link, managed to fix my build by adding a resolution: "@storybook/react/webpack": "^5" – Ignominious
S
0

It happened to me as well, in the end I solved it setting the dependency for storybook webpack5 but using webpack4:

    "@storybook/addon-actions": "^6.2.9",
    "@storybook/addon-controls": "^6.2.9",
    "@storybook/addon-storysource": "^6.2.9",
    "@storybook/builder-webpack5": "^6.2.9",
    "@storybook/vue": "^6.2.9",

As I read here: https://mcmap.net/q/802020/-webpack-5-and-storybook-6-integration-throws-an-error-in-defineplugin-js I think it's better to wait a bit before using webpack5

Scilla answered 23/4, 2021 at 12:10 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.