Skip to content

Commit

Permalink
Merge pull request #14445 from brion-fuller/fuller/web-components-hmr
Browse files Browse the repository at this point in the history
Web-components: Add full reload listening to server-side-events
  • Loading branch information
shilman authored Apr 9, 2021
2 parents 486f611 + 3697239 commit 0aa48ce
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 43 deletions.
32 changes: 5 additions & 27 deletions app/web-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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$`));
Expand Down
16 changes: 16 additions & 0 deletions app/web-components/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { window, EventSource } from 'global';

export {
storiesOf,
setAddon,
Expand All @@ -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
}
});
}
1 change: 1 addition & 0 deletions examples/web-components-kitchen-sink/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
logLevel: 'debug',
stories: ['../stories/**/*.stories.js', '../stories/**/*.stories.mdx'],
addons: [
'@storybook/addon-docs',
'@storybook/addon-controls',
Expand Down
17 changes: 1 addition & 16 deletions examples/web-components-kitchen-sink/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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();
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit 0aa48ce

Please sign in to comment.