Skip to content

Commit

Permalink
(wmr) - prevent newly created files from refreshing the page (#433)
Browse files Browse the repository at this point in the history
* prevent newly created files from refreshing the page

* normalize specifiers

* fix casing

* remove leading /

* Update wmr-middleware.js

* Update wmr-middleware.js

* Update wmr-middleware.js

* Update stupid-kings-cross.md

* only mark the module as stale when dependents accept

* fix stale closures

* repeated updates and consistent timestamps

* fix conflict

* update fixture

* Update index.tsx
  • Loading branch information
JoviDeCroock authored Mar 15, 2021
1 parent 28ee2d3 commit bcf3bdf
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-kings-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'wmr': patch
---

Newly created files shouldn't cause a page-reload
3 changes: 2 additions & 1 deletion packages/wmr/src/lib/websocket-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export default class WebSocketServer extends ws.Server {
client.on('message', function (data) {
const message = JSON.parse(data.toString());
if (message.type === 'hotAccepted') {
const [id] = message.id.split('?');
let [id] = message.id.split('?');
id = id.startsWith('/') ? id.slice(1) : id;
if (!moduleGraph.has(id)) {
moduleGraph.set(id, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false });
}
Expand Down
22 changes: 14 additions & 8 deletions packages/wmr/src/plugins/wmr/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@ const URL_SUFFIX = /\/(index\.html)?$/;

function handleMessage(e) {
const data = JSON.parse(e.data);

switch (data.type) {
case 'reload':
window.location.reload();
break;
case 'update':
data.changes.forEach(url => {
url = resolve(url);

if (!mods.get(url)) {
if (/\.(css|s[ac]ss)$/.test(url)) {
if (mods.has(url + '.js')) {
Expand All @@ -64,14 +62,15 @@ function handleMessage(e) {
updateQueue.push(url);
}
const errorId = errorCount;
if (!updating)
dequeue().then(() => {
if (!updating) {
dequeue(new Date().toISOString()).then(() => {
if (errorId === errorCount) {
// try {
// console.clear();
// } catch (e) {}
}
});
}
});
break;
case 'error':
Expand All @@ -94,15 +93,22 @@ function handleError(e) {
// HMR updates are queued uniquely and run in sequence
const updateQueue = [];
let updating = false;
function dequeue() {
function dequeue(date) {
updating = updateQueue.length !== 0;
return updating && update(updateQueue.shift()).then(dequeue, dequeue);
return (
updating &&
update(updateQueue.shift(), date).then(
() => dequeue(date),
() => dequeue(date)
)
);
}
function update(url) {

function update(url, date) {
const mod = getMod(url);
const dispose = Array.from(mod.dispose);
const accept = Array.from(mod.accept);
const newUrl = url + '?t=' + Date.now();
const newUrl = url + '?t=' + date;
const p = mod.import ? mod.import(newUrl) : import(newUrl);

return p
Expand Down
34 changes: 21 additions & 13 deletions packages/wmr/src/wmr-middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,24 @@ export default function wmrMiddleware({
// Delete file from the in-memory cache:
WRITE_CACHE.delete(filename);

filename = '/' + filename;
const mod = moduleGraph.get(filename);

if (!mod) return false;

if (mod.acceptingUpdates) {
mod.stale = true;
pendingChanges.add(filename);
return true;
} else if (mod.dependents.size) {
return [...mod.dependents].every(function (value) {
mod.stale = true;
return bubbleUpdates(value, visited);
let accepts = true;
[...mod.dependents].forEach(value => {
if (!bubbleUpdates(value, visited)) accepts = false;
});

if (accepts) mod.stale = true;

return accepts;
}

// We need a full-reload signal
return false;
}
Expand All @@ -164,15 +168,18 @@ export default function wmrMiddleware({
WRITE_CACHE.delete(filename);
pendingChanges.add('/' + filename);
} else if (/\.(mjs|[tj]sx?)$/.test(filename)) {
if (!moduleGraph.has(filename)) {
clearTimeout(timeout);
return;
}

if (!bubbleUpdates(filename)) {
moduleGraph.clear();
pendingChanges.clear();
clearTimeout(timeout);
onChange({ reload: true });
}
} else {
WRITE_CACHE.delete(filename);
moduleGraph.clear();
pendingChanges.clear();
clearTimeout(timeout);
onChange({ reload: true });
Expand Down Expand Up @@ -317,7 +324,7 @@ export const TRANSFORMS = {
},

// Handle individual JavaScript modules
async js({ id, file, prefix, res, cwd, out, NonRollup }) {
async js({ id, file, prefix, res, cwd, out, NonRollup, req }) {
let code;
try {
res.setHeader('Content-Type', 'application/javascript;charset=utf-8');
Expand Down Expand Up @@ -345,10 +352,11 @@ export const TRANSFORMS = {
if (spec === 'wmr') return '/_wmr.js';
if (/^(data:|https?:|\/\/)/.test(spec)) return spec;

if (!moduleGraph.has(importer)) {
moduleGraph.set(importer, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false });
let graphId = importer.startsWith('/') ? importer.slice(1) : importer;
if (!moduleGraph.has(graphId)) {
moduleGraph.set(graphId, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false });
}
const mod = moduleGraph.get(importer);
const mod = moduleGraph.get(graphId);

// const resolved = await NonRollup.resolveId(spec, importer);
const resolved = await NonRollup.resolveId(spec, file);
Expand Down Expand Up @@ -398,14 +406,14 @@ export const TRANSFORMS = {
spec = `/@npm/${meta.module}${meta.path ? '/' + meta.path : ''}`;
}

const modSpec = spec.replace('../', '/').replace('./', '/');
const modSpec = spec.startsWith('../') ? spec.replace(/..\/g/, '') : spec.replace('./', '');
mod.dependencies.add(modSpec);
if (!moduleGraph.has(modSpec)) {
moduleGraph.set(modSpec, { dependencies: new Set(), dependents: new Set(), acceptingUpdates: false });
}

const specModule = moduleGraph.get(modSpec);
specModule.dependents.add(importer);
specModule.dependents.add(graphId);
if (specModule.stale) {
return spec + `?t=${Date.now()}`;
}
Expand Down
13 changes: 12 additions & 1 deletion packages/wmr/test/fixtures.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ describe('fixtures', () => {
expect(homeText).toEqual('42');
expect(rootText).toEqual('42');

await updateFile(env.tmp.path, 'store.js', content => content.replace('42', '43'));
await updateFile(env.tmp.path, 'store/index.js', content => content.replace('42', '43'));

await timeout(2000);

Expand All @@ -270,6 +270,17 @@ describe('fixtures', () => {
rootText = rootFoo ? await rootFoo.evaluate(el => el.textContent) : null;
expect(homeText).toEqual('43');
expect(rootText).toEqual('43');

await updateFile(env.tmp.path, 'store/index.js', content => content.replace('43', '44'));

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('44');
expect(rootText).toEqual('44');
});

it('should hot reload for a newly created file', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/wmr/test/fixtures/hmr/home.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FOO } from './store.js';
import { FOO } from './store/index.js';
import useCounter from './useCounter.js';

function Home() {
Expand Down
2 changes: 1 addition & 1 deletion packages/wmr/test/fixtures/hmr/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render } from 'preact';
import styles from './style.module.css';
import Home from './home.js';
import { FOO } from './store.js';
import { FOO } from './store/index.js';

export function App() {
return (
Expand Down
File renamed without changes.

0 comments on commit bcf3bdf

Please sign in to comment.