diff --git a/.changeset/large-apes-perform.md b/.changeset/large-apes-perform.md new file mode 100644 index 000000000..8eacbe717 --- /dev/null +++ b/.changeset/large-apes-perform.md @@ -0,0 +1,5 @@ +--- +'wmr': patch +--- + +Fix case where the module-graph would become stale if two co-dependent modules would import the same file, when this file would get updated we'd only cache-bust the import in one of those two files making the graph stale. One file updates the old version and the other updates the new one. diff --git a/packages/wmr/demo/public/index.tsx b/packages/wmr/demo/public/index.tsx index 813fe2710..b6f2d1cf0 100644 --- a/packages/wmr/demo/public/index.tsx +++ b/packages/wmr/demo/public/index.tsx @@ -53,4 +53,4 @@ export async function prerender(data) { } // @ts-ignore -if (module.hot) module.hot.accept(u => render(, document.body)); +if (module.hot) module.hot.accept(u => hydrate(, document.body)); diff --git a/packages/wmr/demo/public/lib/loc.js b/packages/wmr/demo/public/lib/loc.js index 2766ae276..31813dd2d 100644 --- a/packages/wmr/demo/public/lib/loc.js +++ b/packages/wmr/demo/public/lib/loc.js @@ -39,7 +39,6 @@ export const exec = (url, route, matches) => { return matches; }; - export function LocationProvider(props) { const [url, route] = useReducer(UPDATE, location.pathname + location.search); diff --git a/packages/wmr/src/lib/websocket-server.js b/packages/wmr/src/lib/websocket-server.js index a6aa70e79..fd01a5c79 100644 --- a/packages/wmr/src/lib/websocket-server.js +++ b/packages/wmr/src/lib/websocket-server.js @@ -19,12 +19,14 @@ export default class WebSocketServer extends ws.Server { client.on('message', function (data) { const message = JSON.parse(data.toString()); if (message.type === 'hotAccepted') { - if (!moduleGraph.has(message.id)) { - moduleGraph.set(message.id, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false }); + const [id] = message.id.split('?'); + if (!moduleGraph.has(id)) { + moduleGraph.set(id, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false }); } - const entry = moduleGraph.get(message.id); + const entry = moduleGraph.get(id); entry.acceptingUpdates = true; + entry.stale = false; } }); } diff --git a/packages/wmr/src/wmr-middleware.js b/packages/wmr/src/wmr-middleware.js index 4714dc83e..81b1f56f4 100644 --- a/packages/wmr/src/wmr-middleware.js +++ b/packages/wmr/src/wmr-middleware.js @@ -399,7 +399,6 @@ export const TRANSFORMS = { const specModule = moduleGraph.get(modSpec); specModule.dependents.add(importer); if (specModule.stale) { - specModule.stale = false; return spec + `?t=${Date.now()}`; } diff --git a/packages/wmr/test/fixtures.test.js b/packages/wmr/test/fixtures.test.js index e59294929..0af312d19 100644 --- a/packages/wmr/test/fixtures.test.js +++ b/packages/wmr/test/fixtures.test.js @@ -248,6 +248,30 @@ describe('fixtures', () => { expect(text).toEqual('3'); }); + it('should bubble up updates in non-accepted files with multiple parents', async () => { + await loadFixture('hmr', env); + instance = await runWmrFast(env.tmp.path); + await getOutput(env, instance); + + let homeFoo = await env.page.$('#home-foo'); + let rootFoo = await env.page.$('#root-foo'); + let homeText = homeFoo ? await homeFoo.evaluate(el => el.textContent) : null; + let rootText = rootFoo ? await rootFoo.evaluate(el => el.textContent) : null; + expect(homeText).toEqual('42'); + expect(rootText).toEqual('42'); + + await updateFile(env.tmp.path, 'store.js', content => content.replace('42', '43')); + + await timeout(2000); + + homeFoo = await env.page.$('#home-foo'); + rootFoo = await env.page.$('#root-foo'); + homeText = homeFoo ? await homeFoo.evaluate(el => el.textContent) : null; + rootText = rootFoo ? await rootFoo.evaluate(el => el.textContent) : null; + expect(homeText).toEqual('43'); + expect(rootText).toEqual('43'); + }); + it('should hot reload for a newly created file', async () => { await loadFixture('hmr', env); instance = await runWmrFast(env.tmp.path); diff --git a/packages/wmr/test/fixtures/hmr/home.js b/packages/wmr/test/fixtures/hmr/home.js index 839a1facb..211676280 100644 --- a/packages/wmr/test/fixtures/hmr/home.js +++ b/packages/wmr/test/fixtures/hmr/home.js @@ -1,9 +1,11 @@ +import { FOO } from './store.js'; import useCounter from './useCounter.js'; function Home() { const [count, increment] = useCounter(); return (
+

{FOO}

Home

{count}

diff --git a/packages/wmr/test/fixtures/hmr/index.js b/packages/wmr/test/fixtures/hmr/index.js index ff99220b9..9fbbe19e9 100644 --- a/packages/wmr/test/fixtures/hmr/index.js +++ b/packages/wmr/test/fixtures/hmr/index.js @@ -1,11 +1,13 @@ import { render } from 'preact'; import styles from './style.module.css'; import Home from './home.js'; +import { FOO } from './store.js'; export function App() { return (

+

{FOO}

diff --git a/packages/wmr/test/fixtures/hmr/store.js b/packages/wmr/test/fixtures/hmr/store.js new file mode 100644 index 000000000..e027273ee --- /dev/null +++ b/packages/wmr/test/fixtures/hmr/store.js @@ -0,0 +1 @@ +export const FOO = 42;