diff --git a/app/web-components/README.md b/app/web-components/README.md index 7baf1c3c0af5..24d844c716aa 100644 --- a/app/web-components/README.md +++ b/app/web-components/README.md @@ -24,31 +24,9 @@ For more information visit: [storybook.js.org](https://storybook.js.org) Storybook also comes with a lot of [addons](https://storybook.js.org/docs/web-components/configure/storybook-addons) and a great API to customize as you wish. You can also build a [static version](https://storybook.js.org/docs/web-components/workflows/publish-storybook) of your storybook and deploy it anywhere you want. -# Setup page reload via HMR +# Hot Module Reloading (HMR) -As web components register on a global registry which only accepts a certain name/class once it can lead to errors when using classical HMR. -There are ideas on how to archive HMR with a static registry but there is no proven solution yet. - -Therefore the best approach for now is to do full page reloads. -If you keep your stories to specific states of components (which we would recommend anyways) this usually means it is fast. -To activate full page reload - -```js -// ==> REPLACE -configure(require.context('../stories', true, /\.stories\.(js|mdx)$/), module); - -// ==> WITH -// force full reload to not reregister web components -const req = require.context('../stories', 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(); - }); -} -``` +As web components register on a global registry which only accepts a certain name/class once it can lead to errors when using classical HMR. There are ideas on how to archive HMR with a static registry but there is no proven solution yet. Therefore the best approach for now is to do full page reloads. If you keep your stories to specific states of components (which we would recommend anyways) this usually means it is fast. # Setup es6/7 dependencies @@ -59,11 +37,11 @@ For example if you have a library called `my-library` which is in ES2017 then yo ```js // .storybook/main.js -module.exports = { - webpackFinal: async config => { +module.exports = { + webpackFinal: async (config) => { // find web-components rule for extra transpilation const webComponentsRule = config.module.rules.find( - rule => rule.use && rule.use.options && rule.use.options.babelrc === false + (rule) => rule.use && rule.use.options && rule.use.options.babelrc === false ); // add your own `my-library` webComponentsRule.test.push(new RegExp(`node_modules(\\/|\\\\)my-library(.*)\\.js$`)); diff --git a/app/web-components/src/client/index.ts b/app/web-components/src/client/index.ts index b2379641137f..746997618218 100644 --- a/app/web-components/src/client/index.ts +++ b/app/web-components/src/client/index.ts @@ -1,3 +1,5 @@ +import { window, EventSource } from 'global'; + export { storiesOf, setAddon, @@ -21,4 +23,18 @@ export * from './preview/types-6-0'; // TODO: disable HMR and do full page loads because of customElements.define if (module && module.hot && module.hot.decline) { module.hot.decline(); + + // forcing full reloads for customElements as elements can only be defined once per page + const hmr = new EventSource('__webpack_hmr'); + hmr.addEventListener('message', function fullPageReload(event: { data: string }) { + try { + // Only care for built events. Heartbeats are not parsable so we ignore those + const { action } = JSON.parse(event.data); + if (action === 'built') { + window.location.reload(); + } + } catch (error) { + // Most part we only get here from the data in the server-sent event not being parsable which is ok + } + }); } diff --git a/examples/web-components-kitchen-sink/.storybook/main.js b/examples/web-components-kitchen-sink/.storybook/main.js index d028ac2f59fe..55e614957df8 100644 --- a/examples/web-components-kitchen-sink/.storybook/main.js +++ b/examples/web-components-kitchen-sink/.storybook/main.js @@ -1,5 +1,6 @@ module.exports = { logLevel: 'debug', + stories: ['../stories/**/*.stories.js', '../stories/**/*.stories.mdx'], addons: [ '@storybook/addon-docs', '@storybook/addon-controls', diff --git a/examples/web-components-kitchen-sink/.storybook/preview.js b/examples/web-components-kitchen-sink/.storybook/preview.js index 5670ebb2e8e9..85bf6e78544f 100644 --- a/examples/web-components-kitchen-sink/.storybook/preview.js +++ b/examples/web-components-kitchen-sink/.storybook/preview.js @@ -1,6 +1,6 @@ /* global window */ -import { configure, addParameters, setCustomElements } from '@storybook/web-components'; +import { addParameters, setCustomElements } from '@storybook/web-components'; import customElements from '../custom-elements.json'; @@ -18,18 +18,3 @@ addParameters({ iframeHeight: '200px', }, }); - -// configure(require.context('../stories', true, /\.stories\.(js|mdx)$/), module); - -// force full reload to not re-register web components -const req = require.context('../stories', 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(); - }); -} diff --git a/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev b/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev index 6678d7fb441a..9d6da7a8d99c 100644 --- a/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev +++ b/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-dev @@ -17,6 +17,7 @@ Object { "ROOT/addons/knobs/dist/esm/preset/addDecorator.js-generated-other-entry.js", "ROOT/addons/links/dist/esm/preset/addDecorator.js-generated-other-entry.js", "ROOT/examples/web-components-kitchen-sink/.storybook/preview.js-generated-config-entry.js", + "ROOT/examples/web-components-kitchen-sink/.storybook/generated-stories-entry.js", "NODE_MODULES/webpack-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined", ], "keys": Array [ diff --git a/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod b/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod index e89fc5cfd4fa..fc513e03e4c6 100644 --- a/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod +++ b/lib/core-server/src/__snapshots__/web-components-kitchen-sink_preview-prod @@ -17,6 +17,7 @@ Object { "ROOT/addons/knobs/dist/esm/preset/addDecorator.js-generated-other-entry.js", "ROOT/addons/links/dist/esm/preset/addDecorator.js-generated-other-entry.js", "ROOT/examples/web-components-kitchen-sink/.storybook/preview.js-generated-config-entry.js", + "ROOT/examples/web-components-kitchen-sink/.storybook/generated-stories-entry.js", ], "keys": Array [ "name",