Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(wmr) - fix stale hmr module graph #427

Merged
merged 6 commits into from
Mar 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/large-apes-perform.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion packages/wmr/demo/public/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ export async function prerender(data) {
}

// @ts-ignore
if (module.hot) module.hot.accept(u => render(<u.module.App />, document.body));
if (module.hot) module.hot.accept(u => hydrate(<u.module.App />, document.body));
1 change: 0 additions & 1 deletion packages/wmr/demo/public/lib/loc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 5 additions & 3 deletions packages/wmr/src/lib/websocket-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
});
}
Expand Down
1 change: 0 additions & 1 deletion packages/wmr/src/wmr-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()}`;
}

Expand Down
24 changes: 24 additions & 0 deletions packages/wmr/test/fixtures.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions packages/wmr/test/fixtures/hmr/home.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { FOO } from './store.js';
import useCounter from './useCounter.js';

function Home() {
const [count, increment] = useCounter();
return (
<div>
<p id="home-foo">{FOO}</p>
<p class="home">Home</p>
<p class="count">{count}</p>
<p class="increment" onClick={increment}>
Expand Down
2 changes: 2 additions & 0 deletions packages/wmr/test/fixtures/hmr/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<main class={styles.app}>
<header>
<p id="root-foo">{FOO}</p>
<nav>
<a href="/">Home</a>
</nav>
Expand Down
1 change: 1 addition & 0 deletions packages/wmr/test/fixtures/hmr/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const FOO = 42;