Storybook: v4.1.0 stop allowing webpack.config.js to influence manager

Created on 14 Dec 2018  路  38Comments  路  Source: storybookjs/storybook

Describe the bug
@storybook/[email protected] broke (<= 4.0.12 worked) the ability for .storybook/webpack.config.js to contribute to the manager webpack bundle. This is important to us, as we have addons that rely on webpack features that we need to configure, this worked in versions before 4.1.0, however, it appears that this behavior was removed at that time.

To Reproduce
Attempt to use a feature in your .storybook/addon.js that your webpack.config.js enables.

Expected behavior
I should be able to use features and settings in the manager bundle from the custom webpack.config.js

addons babel / webpack bug has workaround high priority

Most helpful comment

@nowells I didn't expect people would need to modify the webpack config for manager.

I was wrong.

There's a solution for you, which you can do right now:

  • create a file inside your storybook folder: presets.js
  • set it's contents to:
    ```js
    module.exports = [
    path.resolve('./my-preset'),
    ];
  • create a file inside your storybook folder: my-preset.js
  • set it's contents to:
    js export async function managerWebpack(baseConfig, options) { return baseConfig; }

This should modify the webpack config of the manager to your desire.

You can use this file to modify both configs at once:

export async function managerWebpack(baseConfig, options) {
  return baseConfig;
}
export async function managerBabel(baseConfig, options) {
  return baseConfig;
}
export async function webpack(baseConfig, options) {
  return baseConfig;
}
export async function babel(baseConfig, options) {
  return baseConfig;
}

We haven't really introduced this api to the world yet, but this should allow you to do what you want.

All 38 comments

@nowells I didn't expect people would need to modify the webpack config for manager.

I was wrong.

There's a solution for you, which you can do right now:

  • create a file inside your storybook folder: presets.js
  • set it's contents to:
    ```js
    module.exports = [
    path.resolve('./my-preset'),
    ];
  • create a file inside your storybook folder: my-preset.js
  • set it's contents to:
    js export async function managerWebpack(baseConfig, options) { return baseConfig; }

This should modify the webpack config of the manager to your desire.

You can use this file to modify both configs at once:

export async function managerWebpack(baseConfig, options) {
  return baseConfig;
}
export async function managerBabel(baseConfig, options) {
  return baseConfig;
}
export async function webpack(baseConfig, options) {
  return baseConfig;
}
export async function babel(baseConfig, options) {
  return baseConfig;
}

We haven't really introduced this api to the world yet, but this should allow you to do what you want.

Thank @ndelangen thanks for getting back to me. I looked through the code and found the presets feature, however, it's definition in the code does not make me feel like it is something I would want to use: "Custom presets" is an experimental and undocumented feature that will be changed or deprecated soon. Use it on your own risk.

Also, this appears to be a breaking change from the published docs for v4, so it is unfortunate to have this land as a minor bump. We have tons of projects at our company that would need to be updated, which we can certainly do, but unfortunate to have to coordinate either pinning to 4.0.12 or doing a change like the presets one (which from the code it appears that we would need to change again since it is not stable).

It seems to me that restoring the webpack.config.js behavior would be the most ideal situation, as it is valuable, and important in a consistent ecosystem of adding code to both the iframe and manager, and not just the iframe.

Thanks for your time and consideration of this issue.

@ndelangen I tried your solution and got:

(function (exports, require, module, __filename, __dirname) { export async function managerWebpack(baseConfig, options) {
ERR!                                                               ^^^^^^
ERR!
ERR! SyntaxError: Unexpected token export

@ndelangen any guidance on my question above (sorry, not trying to push), we have pinned to 4.0.12 internally for now, but would like to understand a stable path forward.

@nowells Sorry for the inconvenience here. We'll try to get it sorted ASAP. First, a question: do you need a custom webpack config or if we added back in a bunch of standard loaders would that solve your problem in the short term? (The current manager config is pretty stripped down, but doesn't need to be.)

@igor-dv At what point can we call the presets API stable? I think this is a pretty good use case for it--I don't see us going back to a unified config, and it looks like people are relying on being able to configure the manager too. See also #5004

@lflpowell: I was able to get it working with this:

module.exports = {
  async managerWebpack(baseConfig, options) {
    return baseConfig;
  }
};

@shilman we need a custom webpack config in our workflow, we need to run our own plugins to make storybooks work in our ecosystem. At the very least adding back in the standard loaders might help (such as JSX) however, I think having the ability to customize just like the preview is pretty powerful and useful for more advanced cases.

@shilman since this also broke our storybook usage that is based on CRA (so not having any additional webpack config) we would be very happy if standard loaders would work out of the box when compiling the manager. We have e.g. an addon that now breaks the compile process since it is loading png files (or rather failing to import them now).

@shilman, it's internally stable, but we didn't want to introduce a new presets.js file, and decided to make it officially stable once we support a single configuration file.

+1 for this issue. Seems like it's a root cause of the one that I reported: https://github.com/storybooks/storybook/issues/5122

When I install storybook 4.0.9 seems to be working fine.
Any plans for this to come into 4.2.0?

Here's what @igor-dv and I discussed as a proposed solution. Feedback appreciated @ndelangen @tmeasday @nowells @travikk @Laskoran @lflpowell @DBosley. If this sounds reasonable, PRs are welcome. If nobody takes it in the next few days, I'll take a swing at it myself.

Long term

We're planning a unified preview/manager config file, in which case you would simply configure your manager as you see fit. Unfortunately, we don't have a timeline on this yet.

Short term

This is an unintentional breaking change in 4.1, and to address the issue we propose a new package, titled something like @storybook/patch-manager-config, that's a convenience function for @ndelangen's workaround posted above. We'll guarantee that the package is compatible with Storybook until the long-term solution is available, at which point we'll deprecate the package.

Please let me know what you think!

@shilman what does the package do exactly?

My thinking (pardon me for the drive-by) was that if the only reason we didn't want to support .storybook/presets.js was that the unified config was coming and that was a nicer API; but now unified config is delayed; then I would suggest it isn't such a bad thing to support .storybook/presets.js after all.

It doesn't seem like such a back-compat burden to support it as a stand in for the presets field of a unified config.

@tmeasday When you install the package, it sets up the presets to make sure that your manager config matches your preview config.

Sounds good to me.

So I propose we fix this meantime like so:

// .storybook/webpack.config.js
module.exports = {
  preview: async ({ config }) => ({
    ...config,
  }),
  manager: async ({ config }) => ({
    ...config,
  }),
};

Look like the cleanest solution, to me.

I can work on this today and have a fix out by a few days.

What do you think @shilman

@ndelangen let's just use presets rather than complicating the API. I think this is a corner case. I'm working on the documentation now in #5301

FYI to anybody who's monitoring this issue:

  • We plan to make the workaround described above officially supported post 5.0
  • We haven't had time to update the documentation. There's a WIP PR, but that requires a lot more work to merge and we don't have time to get to it until after the 5.0 release https://github.com/storybooks/storybook/pull/5333

Hi, what is the proper solution here? I was waiting for 5.0 release, but seems like it's still the same.

@mohsinulhaq the presets solution described above. we'll support it moving forward.

thanks, the solution worked.

However, I get this warning:
"Custom presets" is an experimental and undocumented feature that will be changed or deprecated soon. Use it on your own risk.

@mohsinulhaq Thanks, I'll remove that warning!

Son of a gun!! I just released https://github.com/storybooks/storybook/releases/tag/v5.0.1 containing PR #5911 that references this issue. Upgrade today to try it out!

Closing this issue. Please re-open if you think there's still more to do.

thanks @shilman 馃ぉ

Ooh-la-la!! I just released https://github.com/storybooks/storybook/releases/tag/v5.1.0-alpha.3 containing PR #5911 that references this issue. Upgrade today to try it out!

Because it's a pre-release you can find it on the @next NPM tag.

wow, is this an automated script?

In https://github.com/storybooks/storybook/issues/4995#issuecomment-447270973

export async function managerWebpack(baseConfig, options) {
return baseConfig;
}

May I know why all these functions are marked async? I remove async and it still works.

I just wanted to say thank you for your work in making the presets.js available. It worked great, and was easy to migrate to (and actually made the settings easier with the more granular configuration).

@mohsinulhaq There's a practice of annotating promise-returning functions as async even if they don't use await syntax, just to ensure and document that they're async.

@mohsinulhaq There's a practice of annotating promise-returning functions as async even if they don't use await syntax, just to ensure and document that they're async.

wouldn't that result in wrapping promise inside another promise?

You can't wrap JS promises, as they automatically flatten.

Wow, I didn't know that. Thanks a lot @slikts !

It would be great to note in the docs that the customization of webpack does not include the manager, and other core webpack bundles. Total PITA to figure that out.

We also need to override the manager webpack config so we can enforce a maximum chunk size.

Seems like there has been some changes with preset config since this thread started. The solution that worked for SB 5.x.x. was to use a .storybook/main.js config as documented here:
https://storybook.js.org/docs/presets/writing-presets/#advanced-configuration

_Background: since upgrading to SB 5.3.1 we have had issues with JS bundles greater than 1MB (constraint due to hosting on AWS S3 via lambda for auth)._

@johnhunter you should be able to do this by filling in managerWebpack in main.js. Have you tried that?

All good thanks!

main.js

const merge = require('webpack-merge');

// https://storybook.js.org/docs/presets/writing-presets/#advanced-configuration
module.exports = {
  managerWebpack: async (config, options) => {
    return merge(config, { /* config override here...*/ });
  },
};

@shilman I have an issue after migrating from 5.2.* to 5.3.*. I've tried to move to new configs, so my main.js file looks like below:

module.exports = {
    managerWebpack: async (config, options) => {
        config.module.rules.push({
            test: /\.tsx?$/,
            use: [
                {
                    loader: require.resolve("ts-loader"),
                    options: {
                        transpileOnly: true,
                        configFile: path.resolve(__dirname, "./tsconfig.json")
                    }
                }
            ]
        });
        config.module.rules.push({ test: /\.md$/, use: [{ loader: "raw-loader" }] });
        config.resolve.extensions.push(".ts", ".tsx");
        return config;
    },
    stories: [
        "../stories/components/**/*.stories.ts"
    ],
    addons: [
        "@storybook/addon-knobs/register",
        "@storybook/addon-actions/register",
        path.resolve(__dirname, "./changelog/register.tsx"),
    ],
};

There is an /changelog/register.tsx addon, and I need to have custom manager webpack config to load .tsx, .md files. It worked fine in old setup, when manager webpack config was defined in separate presets.js file. But now it seems that this config are loaded after loading addons/presets that's why I get an error like:

WARN   Failed to load preset: "C:\\Work\\planck\\web-components\\src\\storybook\\config\\changelog\\register.tsx" on level 1
ERR! C:\Work\planck\web-components\src\storybook\config\changelog\register.tsx:1
ERR! (function (exports, require, module, __filename, __dirname) { import React from "react";
ERR!                                                                      ^^^^^
ERR! 
ERR! SyntaxError: Unexpected identifier
ERR!     at new Script (vm.js:79:7)
ERR!     at createScript (vm.js:251:10)
...

Could you please advise me what could be the possible fix for that? Any help would be appreciated.

@andrei-ilyukovich I believe this is fixed in https://github.com/storybookjs/storybook/pull/9648

Was this page helpful?
0 / 5 - 0 ratings