Skip to content

Commit

Permalink
pref: run client scripts only when opening the DevTools Panel (#101)
Browse files Browse the repository at this point in the history
* pref: run client scripts only when opening the DevTools Panel

* refactor: remove unnecessary logic

* refactor: create a port in the panel created callback

* refactor: variable names

* refactor: suppress debug log
  • Loading branch information
koba04 committed Dec 18, 2022
1 parent d0e5a6c commit b04c3da
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 77 deletions.
8 changes: 1 addition & 7 deletions packages/swr-devtools-extensions/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 33,7 @@ const port = runtime.connect({
const root = createRoot(rootEl);
const render = (el: ReactElement) => root.render(el);

/*
port.onDisconnect.addListener(() => {
cache.clear();
mounted = false;
render(<SWRDevToolPanel cache={null} events={null} />);
});
*/
render(<SWRDevToolPanel cache={null} events={null} key="swr-not-found" />);

let mounted = false;
port.onMessage.addListener(
Expand Down
57 changes: 23 additions & 34 deletions packages/swr-devtools-extensions/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 4,24 @@ import type { ContentMessage } from "./content";
const contentPortMap = new Map();
const panelPortMap = new Map();

// queued messages until a panel is connected
const queuedContentMessages: any[] = [];
let panelIsOpen = false;

runtime.onConnect.addListener((port) => {
const debug = (...args: any[]) => {
// console.log(...args);
};

runtime.onConnect.addListener((port: Runtime.Port) => {
const tabId = port.sender?.tab?.id || port.name.replace("panel:", "");
console.log("on connect", { name: port.name, tabId });

// A port between a content page
if (port.name === "content") {
contentPortMap.set(tabId, port);
if (panelPortMap.has(tabId)) {
// notify that a panel is connected
port.postMessage({
type: "displayed_panel",
});
}
port.postMessage({
type: panelIsOpen ? "panelshow" : "panelhide",
});
port.onDisconnect.addListener(() => {
console.log("disconnected content port => ", tabId);
contentPortMap.delete(tabId);
});
port.onMessage.addListener(
Expand All @@ -32,46 33,34 @@ runtime.onConnect.addListener((port) => {
};

const panelPort = panelPortMap.get(tabId);
/*
console.log("sent message from content to panel", data, {
panelPort?.postMessage(data);

debug("sent message from content to panel", data, {
sender,
tabId,
panelPortMap,
panelPort,
});
*/
if (panelPort) {
panelPort.postMessage(data);
} else {
// not ready for sending messages
queuedContentMessages.push(data);
}
}
);
// A port between the SWR panel in devtools
} else if (port.name.startsWith("panel")) {
panelPortMap.set(tabId, port);
// console.log("panelport", { tabId, panelPortMap, contentPortMap });
const contentPort = contentPortMap.get(tabId);
if (contentPort) {
// notify that a panel is connected
contentPort.postMessage({
type: "displayed_panel",
});
}
// flush queued messages
if (queuedContentMessages.length > 0) {
queuedContentMessages.forEach((m) => port?.postMessage(m));
queuedContentMessages.length = 0;
}
port.onDisconnect.addListener(() => {
console.log("disconnected panel port => ", tabId);
panelPortMap.delete(tabId);
});
port.onMessage.addListener((message) => {
console.log("sent message from panel to content", message);
if (contentPort !== null) {
contentPort.postMessage(message);
if (message.type === "panelshow") {
panelIsOpen = true;
} else if (message.type === "panelhide") {
panelIsOpen = false;
}

const contentPort = contentPortMap.get(tabId);
contentPort?.postMessage(message);

debug("sent message from panel to content", message, contentPort);
});
}
});
37 changes: 18 additions & 19 deletions packages/swr-devtools-extensions/src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 49,40 @@ export type ContentMessage =
tabId: number;
};

// queued messages until a panel is displayed
const queuedMessages: any[] = [];
const enqueueMessage = (message: any) => {
queuedMessages.push(message);
};

let isDisplayedPanel = false;
let panelIsOpen = false;

let port_: Runtime.Port | null = null;

const debug = (...args: any[]) => {
// console.log(...args);
};

const getPort = () => {
if (port_ !== null) return port_;
debug("reconnect content port");
port_ = runtime.connect({ name: "content" });
const onMessage = (message: any) => {
// a panel has been displayed, so we sent queued messages
if (message.type === "displayed_panel") {
queuedMessages.forEach((m) => {
port_?.postMessage(m);
});
isDisplayedPanel = true;
debug("receive event", { message });
if (message.type === "panelshow") {
panelIsOpen = true;
window.postMessage({ type: "panelshow" });
} else if (message.type === "panelhide") {
panelIsOpen = false;
window.postMessage({ type: "panelhide" });
}
};
// cannot get tabId here
port_.onMessage.addListener(onMessage);
port_.onDisconnect.addListener(() => {
debug("disconnect content panel port");
panelIsOpen = false;
port_?.onMessage.removeListener(onMessage);
port_ = null;
});

return port_;
};

// proxy messages from applications to a background script

// A new page has been loaded.
// this event is sent with any pages that don't have SWRDevTools
getPort().postMessage({
Expand All @@ -94,18 94,17 @@ window.addEventListener("message", (e: MessageEvent<DevToolsMessage>) => {
switch (e.data?.type) {
case "initialized": {
port.postMessage(e.data);
// sync the status of displayed panel
window.postMessage({ type: "load", payload: { panelIsOpen } });
break;
}
case "updated_swr_cache":
case "request_start":
case "request_success":
case "request_error":
case "request_discarded": {
if (isDisplayedPanel) {
if (panelIsOpen) {
port.postMessage(e.data);
} else {
// enqueue a message if a panel hasn't been displayed
enqueueMessage(e.data);
}
break;
}
Expand Down
15 changes: 13 additions & 2 deletions packages/swr-devtools-extensions/src/devtools.ts
Original file line number Diff line number Diff line change
@@ -1,5 1,16 @@
import { devtools } from "webextension-polyfill";
import { devtools, runtime } from "webextension-polyfill";

devtools.panels.create("SWR", "", "panel.html").then(() => {
devtools.panels.create("SWR", "", "panel.html").then((panel) => {
const port = runtime.connect({
name: "panel:" devtools.inspectedWindow.tabId,
});
panel.onHidden.addListener(() => {
// console.log("hide panel");
port.postMessage({ type: "panelhide" });
});
panel.onShown.addListener(() => {
// console.log("show panel");
port.postMessage({ type: "panelshow" });
});
console.log("The DevTools panel has been created");
});
4 changes: 3 additions & 1 deletion packages/swr-devtools-extensions/src/panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 6,9 @@
html {
height: 100%;
background-color: white;
@media (prefers-color-scheme: dark) {
}
@media (prefers-color-scheme: dark) {
html {
background-color: rgb(39, 40, 34);
}
}
Expand Down
18 changes: 14 additions & 4 deletions packages/swr-devtools-panel/src/components/SWRDevToolPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 129,11 @@ export const SWRDevToolPanel = ({ cache, events }: Props) => {
/>
)
) : (
<NoteText>
Haven&apos;t received any cache data from SWRDevTools
</NoteText>
<NotFound>
<NotFoundText>
Open SWRDevTools on the page using SWR.
</NotFoundText>
</NotFound>
)}
</PanelWrapper>
</DevToolWindow>
Expand Down Expand Up @@ -187,6 189,14 @@ const PanelWrapper = styled.div`
height: calc(100% - 36px);
`;

const NoteText = styled.p`
const NotFound = styled.div`
display: flex;
height: 100%;
justify-content: center;
align-items: center;
font-size: 1.2rem;
`;

const NotFoundText = styled.p`
color: var(--swr-devtools-text-color);
`;
49 changes: 39 additions & 10 deletions packages/swr-devtools/src/createSWRDevTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 20,10 @@ export class EventEmitter {
}
}

const debug = (...args: any[]) => {
// console.log(...args);
};

const injected = new WeakSet();

export type DevToolsMessage =
Expand Down Expand Up @@ -64,18 68,22 @@ export type DevToolsMessage =
};
};

let devToolsPanelIsOpen = false;

const inject = (cache: Cache) =>
injectSWRCache(cache, (key: string, value: any) => {
window.postMessage(
{
type: "updated_swr_cache",
payload: serializePayload({
key,
value,
}),
},
"*"
);
if (devToolsPanelIsOpen) {
window.postMessage(
{
type: "updated_swr_cache",
payload: serializePayload({
key,
value,
}),
},
"*"
);
}
});

const noop = () => {
Expand All @@ -92,6 100,18 @@ const dummyHooks = {
export const createSWRDevtools = () => {
const events = new EventEmitter();

if (typeof window !== "undefined") {
window.addEventListener("message", (e) => {
if (e.data?.type === "panelshow") {
devToolsPanelIsOpen = true;
} else if (e.data?.type === "panelhide") {
devToolsPanelIsOpen = false;
} else if (e.data?.type === "load") {
devToolsPanelIsOpen = e.data?.payload?.panelIsOpen;
}
});
}

const swrdevtools: Middleware = (useSWRNext) => (key, fn, config) => {
// use the same React instance with the application
const { useLayoutEffect, useEffect, useRef } =
Expand All @@ -105,6 125,7 @@ export const createSWRDevtools = () => {
useLayoutEffect(() => {
window.postMessage({ type: "initialized" }, "*");
}, []);

// FIXME: I'll use mutate to support mutating from a devtool panel.
// const { cache /* , mutate */ } = useSWRConfig();
const cache = config.cache;
Expand All @@ -119,6 140,7 @@ export const createSWRDevtools = () => {

useEffect(() => {
return () => {
if (!devToolsPanelIsOpen) return;
// When the key changes or unmounts, ongoing requests should be discarded.
// This only affects React 17.
// https://github.com/vercel/swr/blob/bcc39321dd12133a0c42207ef4bdef7e214d9b1e/core/use-swr.ts#L245-L254
Expand All @@ -135,6 157,13 @@ export const createSWRDevtools = () => {
};
}, [serializedKey]);

debug({ devToolsPanelIsOpen });

// If DevToolsPanel is not opened, we don't do anything.
if (!devToolsPanelIsOpen) {
return useSWRNext(key, fn, config);
}

const wrappedFn = fn
? (...args: any) => {
const id = ~~(Math.random() * 1e8);
Expand Down

1 comment on commit b04c3da

@vercel
Copy link

@vercel vercel bot commented on b04c3da Dec 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

swr-devtools – ./

swr-devtools-git-main-koba04.vercel.app
swr-devtools-koba04.vercel.app
swr-devtools.vercel.app

Please sign in to comment.