Storybook: Cannot get /iframe.html

Created on 11 Mar 2019  路  17Comments  路  Source: storybookjs/storybook

Describe the bug

I'm currently running into this issue when I run storybook locally. Storybook loads but I see the message Cannot GET /iframe.html in the window where the component should render.

Request URL: http://localhost:9009/iframe.html?id=*
Request Method: GET
Status Code: 404 Not Found
Remote Address: [::1]:9009
Referrer Policy: no-referrer-when-downgrade

Packages I'm using

 "@storybook/addon-actions": "5.0.1",
  "@storybook/addon-links": "5.0.1",
  "@storybook/addons": "5.0.1",
  "@storybook/react": "5.1.0-alpha.2"
core question / support

Most helpful comment

I ran into this issue as well after migrating from extend mode to full control mode. Fixed it by changing the config.plugins option from

config.plugins = [
  ...
]

to

config.plugins.push(
  ...
)

It may be worth updating the docs at https://storybook.js.org/docs/configurations/custom-webpack-config/#full-control-mode to preserve the plugins config array as well

All 17 comments

For me this turned out to be a path issue - the git repo created a folder called Design%20System - removing the encoded space to just DesignSystem fixed this for me.

I'm also having this problem. Not seeing any strange folder names :(

In my case webpack.config.js had a line config.output.publicPath = '/storybook/'; but /storybook didn't exist. Removing that line fixed the problem.

Hello

I encountered the same issue.

Here is my webpack.config.js

const { resolve } = require("path");
const { root, srcClient, pages } = require("../webpack/paths");
const { sassLoaderData, alias } = require("../webpack/data");
const webpack = require("webpack");

const brand = process.env.BRAND || "AF";

module.exports = async ({ config }) => {
    config.node = {
        fs: "empty",
    };

    config.module.rules.push({
        test: /\.(png|jpg)$/,
        loader: "url-loader",
        options: {
            limit: 25000,
        },
    });

    config.module.rules.push({
        test: /\.woff|eot|svg|otf|ttf|woff2$/,
        loader: "url-loader", // fonts needs to be in a font folder
        options: {
            limit: 1000,
            name: "font/[name].[ext]",
        },
    });

    config.module.rules.push({
        test: /\.scss/,
        use: [
            "style-loader",
            "css-loader",
            {
                loader: "sass-loader",
                options: {
                    data: sassLoaderData,
                },
            },
        ],
        include: [pages, resolve(root, "node_modules/gridle")],
    });

    config.module.rules.push({
        test: /\.css/,
        use: ["style-loader", "css-loader", "postcss-loader"],
        include: [
            resolve(root, "node_modules/rc-slider/assets"),
            resolve(root, "node_modules/react-select/dist"),
            resolve(root, "node_modules/storybook-host/assets/css"),
        ],
    });

    config.module.rules.push({
        test: /(\.js|\.jsx)$/,
        exclude: /node_modules/,
        use: {
            loader: "babel-loader",
            options: {
                caller: { target: "web" },
            },
        },
    });

    config.resolve = {
        modules: [srcClient, "node_modules"],
        alias,
        extensions: [".js", ".jsx", ".scss"],
    };

    config.plugins = [
        new webpack.NormalModuleReplacementPlugin(/(.*)@brand(\.*)/, function(resource) {
            resource.request = resource.request.replace(/@brand/, `brands/${brand}`);
        }),
    ];

    // Return the altered config
    return config;
};

I also face the same issue :(


module.exports = async ({ config, mode }) => ({
    ...config,

    module: {
       // ...config.module,
        rules: [
           // ...config.module.rules,
            {
                test    : /\.(js|jsx)$/,
                exclude : /node_modules/,
                use     : 'babel-loader',
            },
            {
                test: /\.css$/,
                use: [
                    "style-loader",
                    "css-loader"
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    // MiniCssExtractPlugin.loader,
                    "style-loader",

                    "css-loader",
                    // {
                    //     loader: "postcss-loader",
                    //     options: {
                    //         ident: 'postcss',
                    //         sourceMap: true,
                    //         plugins: [
                    //             require('autoprefixer')({ browsers: ['> 1%', 'last 2 versions'] })
                    //         ],
                    //     }
                    // },
                    "sass-loader",
                ],
            },
            {
                test: /\.(eot|otf|ttf|woff|woff2)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            context: '/', // check if '/' => './'
                            name: 'fonts/[name].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.(png|svg|jpg|gif|ico)$/,
                oneOf: [
                    {test: /flags\/\dx\d\//, use: 'file-loader?name=ext/flags/[name].[ext]'},
                    {test: /\/amcharts\//,   use: 'file-loader?name=ext/amcharts/[name].[ext]'},
                    {test: /.*/,             use: 'file-loader?name=images/[name].[ext]'}
                ]
            },
            {
                test: /\.(mobileconfig)$/,
                use: 'file-loader?name=files/[name].[ext]'
            },
            {
                test: /datatables\.net.*/,
                use: 'imports-loader?define=>false'
            }
        ]
    },

    plugins: [
         extractedCSS
    ]
})

@yairEO @lauterry
Yeah well, you're both REMOVING all webpack plugins, including the HtmlWebpackplugin, so it would make sense for there to be no html outputted.

@dmoojunk you may have stumbled upon an actual bug

I ran into this issue as well after migrating from extend mode to full control mode. Fixed it by changing the config.plugins option from

config.plugins = [
  ...
]

to

config.plugins.push(
  ...
)

It may be worth updating the docs at https://storybook.js.org/docs/configurations/custom-webpack-config/#full-control-mode to preserve the plugins config array as well

@ndelangen - Thanks! you saved me.

I wasn't aware there were any default plugins in the first place! who knew...

For me the problem was also in the webpack config.

Before

const customConfig = require('../../../../../webpack.config');

module.exports = async ({ config, mode }) => {
    return {
        ...config,
        module: {
            rules: customConfig.module.rules,
        },
        plugins: customConfig.plugins,
    };
  };

After

const customConfig = require('../../../../../webpack.config');

module.exports = async ({ config, mode }) => {
    return {
        ...config,
        module: {
            rules: customConfig.module.rules,
        },
        plugins: [
            ...config.plugins,
            ...customConfig.plugins,
        ],
    };
  };

For me the problem was that the output path was the same as the configuration path.
Storybook clears the output path before build.

// webpack.config.js
module.exports = async ({ config }) => {
  config.plugins.push(new TestWebpackPlugin());
  return config;
};
// test.webpack.plugins.js
const pluginName = 'DefWebpackPlugin';
class TestPlugin {
  constructor() {

  }

  apply(compiler) {
    compiler.hooks.compilation.tap(pluginName,(compilation) => {
      // Q => ?????????????????????????
      // why 'compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing' awlays is undefined
      if (!compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing) return;
      compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap(pluginName, (data, callback) => {
        // do something
        callback && callback(null, data);
      });
    });
  }
}

module.exports = TestPlugin;

Same issue for me like @jxh150535011 , i have undefined hooks for htmlWebpackPlugin. Can鈥檛 use my custom plugin for inject data on html with storybook.

What would you like to inject?

What would you like to inject?

I want inject some html svg sprite on the base template, with a custom plugin like we done on the project(SSR twig + vueJS). I have found how to do this, I recreate the htmlWepbackPlugin with the conf of storybook iFrame. It's work fine. But it's really strange that storybook erase hooks from HtmlWebpackPlugin on compilation, because the plugin appear on the conf output.

@djodjonx AFAIK we don't do anything special to remove those hooks. In fact I wouldn't even know how, or if removing hooks from webpack compilation is possible.

Could there be a problem with the HtmlWebpackPlugin? @jantimon ?

I ran into this issue as well after migrating from extend mode to full control mode. Fixed it by changing the config.plugins option from

config.plugins = [
  ...
]

to

config.plugins.push(
  ...
)

It may be worth updating the docs at https://storybook.js.org/docs/configurations/custom-webpack-config/#full-control-mode to preserve the plugins config array as well

Thanks, was my case as well! 馃檹

Was this page helpful?
0 / 5 - 0 ratings