Storybook: Questions: Web components HMR for v5.3.4

Created on 16 Jan 2020  路  18Comments  路  Source: storybookjs/storybook

Dear Maintainers,

With v5.3.x came new setup, particularly, import stories into main.js.
Thus HMR approach for Web Components no longer works for '@storybook/html'
Are there any workarounds?

html web-components core feature request has workaround todo

Most helpful comment

I'll put up a PR

All 18 comments

cc @daKmoR @ndelangen

what "does no longer work" mean in that context? and are we talking about @storybook/web-components or @storybook/html?

HMR for web components when @storybook/html is used.
Previously, there was a way to configure it but now configuration is different and we don't have that much control.

indeed you can not use that configuration in main.js 馃檲

@ndelangen any way to influence the HMR behaviour now?

@daKmoR can you put this in .storybook/preview.js?

if (module.hot) {
  module.hot.accept(req.id, () => {
    const currentLocationHref = window.location.href;
    window.history.pushState(null, null, currentLocationHref);
    window.location.reload();
  });
}

It still works, but then you're also moving some declarative config from main.js into preview.js, which is a bit odd. It would be nice to have a callback that's provided module/req so you can do post-config tweaks, or something.

@daKmoR @alazurenko The code to deal with stories HMR when configured with main.js is right here:
https://github.com/storybookjs/storybook/blob/a6c2a85183e3701c8f73003b0df4d62c540ce771/lib/core/src/client/preview/start.js#L493-L502

As you see, we know exactly which framework we're in, so we can do a bit of framework dependent HMR handling code.

Would you be able to open a PR @alazurenko ?

Alright, I think this setup would be beneficial for HTML and Web Components.

when i click the link in ndelangen's response, i don't see lines 493-502 at all, so i'm not quite sure what i'm supposed to be looking at.

i'm currently using @storybook/web-components v5.3.12 and tried following the example set out here by adding this to preview.js:

const req = require.context('../src/components', true, /\.stories\.(js|mdx)$/);
configure(req, module);
if (module.hot) {
  module.hot.accept(req.id, () => {
    const currentLocationHref = window.location.href;
    window.history.pushState(null, null, currentLocationHref);
    window.location.reload();
  });
}

the behavior i'm seeing is that updates to the stories trigger a hot reload, updates to the components don't trigger a reload at all (components and stories in my repo are co-located under the path /src/components/${component-name} if that's useful context). it also seems like using configure(req, module); causes the console error Unexpected loaded state. Did you call load twice? as though configure is being called multiple times, even though i'm only using it once.

what's the correct way to set storybook up so that the iframe reloads when updates are made to the web components?

@oldwestaction I have managed to split config for development and production environment, since we only need HRM for development.

utils.js

const { NODE_ENV } = process.env;
const PRODUCTION = 'production';
const isProduction = NODE_ENV === PRODUCTION;
module.exports = { isProduction }

main.js

const { isProduction } = require('./utils.js');
module.exports = {
    stories: [ isProduction ? '../src/components/**/*.stories.(js|mdx)': null ],
    addons: [],
  // .... rest of config
}

preview.js

const { isProduction } = require('./utils.js');
// ... preview configuration
if (!isProduction) {
    const stories = require.context('./../src/components', true, /\.stories\.(js|mdx)$/);
    configure(stories, module);
    if (module.hot) {
        module.hot.accept(stories.id, () => {
            const currentLocationHref = window.location.href;
            window.history.pushState(null, null, currentLocationHref);
            window.location.reload();
        });
    }
}

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

We wrote a HMR handler for custom elements and it's been working fairly well for our situation: https://github.com/polleverywhere/hmr-custom-element

Hope this works for you guys as well.

Nice one @steel! 馃挴

@steel @daKmoR any chance we can integrate this into @storybook/web-components out of the box so it's zero config?

Impressive @steel, would love to have that by default in app/web-components for 6.0.0!

If you need any help, we could pair program on it?

I'll put up a PR

I'm gonna delay this. We don't use LitElement, only lit-html within the custom element. This helper does not work with LitElement which is what the kitchen sink app uses. I don't want folks to get some sense of false hope. I can still put up a PR though if you like that updates the doc with instructions on how to try it if they are not using LitElement.

The internals of LitElement are quite a complicated beast. This is partially the reason we chose not to use it. We chose to develop pure and simple custom elements with a dash of lit-html internals.

Let me know.
Thanks.

For vanilla storybook (e.g. html) here's a workaround for live reload in the meantime.

  1. npm install --save-dev webpack-livereload-plugin

  2. In .storybook/main.js:

    2a. const LiveReloadPlugin = require('webpack-livereload-plugin');

    2b. Edit the webpack config. config, here is the thing passed to webpackFinal in module.exports

    //remove HMR
    config.plugins = config.plugins.filter(plugin => plugin.constructor.name != "HotModuleReplacementPlugin");
    config.entry = config.entry.filter(entry => entry.indexOf("webpack-hot-middleware") === -1);
    
    //Add LiveReload
    config.plugins.push(new LiveReloadPlugin());
    
  3. In .storybook/preview-head.html add:
    <script src="http://localhost:35729/livereload.js"></script>

Was this page helpful?
0 / 5 - 0 ratings