Skip to content

Commit

Permalink
optimize devtools
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmood committed Oct 23, 2024
1 parent 63505d2 commit 2a32b4f
Show file tree
Hide file tree
Showing 47 changed files with 1,293 additions and 1,198 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ All the non-core functions are just examples of how you can compose functions to
- **Scalable**: Naturally scale large state into multiple modules and files without performance degradation.
- **Middlewares**: Simple and type-safe middleware composition interface.
- **Tiny**: About [0.3KB](https://bundlephobia.com/package/stalo) Minified + Gzipped.
- **Devtools**: Native devtools support.
- **Devtools**: Native [devtools](https://github.com/ysmood/stalo/issues/3) support.

## Documentation

Expand Down
2 changes: 2 additions & 0 deletions chrome-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ To build the chrome extension, under the root of the repo:
```bash
npm run build-extension
```

The extension will output to [here](./dist).
14 changes: 8 additions & 6 deletions chrome-extension/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ function genManifest() {
);
console.info("Generated chrome extension html entrypoint");

execSync(`npx rollup -c rollup.config.js`, {
stdio: "inherit",
env: {
...process.env,
ENTRIES: [communicator, background, contentScript].join(","),
},
[communicator, background, contentScript].forEach((entry) => {
execSync(`npx vite -c vite.ext.config.ts build`, {
stdio: "inherit",
env: {
...process.env,
ENTRY: entry,
},
});
});

writeFileSync("dist/icon.png", readFileSync("src/icon.png"));
Expand Down
28 changes: 0 additions & 28 deletions chrome-extension/rollup.config.js

This file was deleted.

86 changes: 58 additions & 28 deletions chrome-extension/src/communicator.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,66 @@
import { getDevtools, devtoolsKey } from "stalo/lib/devtools";
import { eventInit, eventRecord, eventUpdate, StaloEvent } from "./types";

(async function connect() {
await new Promise<void>((resolve) => {
if (getDevtools()) resolve();
window.addEventListener(devtoolsKey, () => {
resolve();
import { getDevtools, devtoolsKey, Devtools } from "stalo/lib/devtools";
import { initName } from "@stalo/devtools-ui";
import { sendMessage, setNamespace, onMessage } from "webext-bridge/window";
import {
eventGet,
eventInit,
eventRecord,
eventSet,
Get,
Init,
namespace,
Record as Rec,
Set,
} from "./constants";
import { uid } from "stalo/lib/utils";

connectAll();

async function connectAll() {
setNamespace(namespace);

const list: Record<string, Devtools<object>> = {};

function updateList() {
getDevtools<object>().forEach((d) => {
if (list[d.id]) return;

list[d.id] = d;
connect(d);
});
}

window.addEventListener(devtoolsKey, () => {
updateList();
});

const list = getDevtools();
setInterval(updateList, 1000);

if (!list) {
return;
}
onMessage<Get>(eventGet, ({ data }) => {
return list[data].state;
});

list.forEach((devtools, i) => {
window.dispatchEvent(
new CustomEvent(eventInit, {
detail: [i, devtools.name, devtools.initRecord],
})
);

devtools.subscribe((record) => {
window.dispatchEvent(
new CustomEvent(eventRecord, { detail: [i, record] })
);
});
onMessage<Set>(eventSet, ({ data }) => {
list[data.id].state = data.state;
});
}

function connect(d: Devtools<object>) {
const init: Init = {
sessionID: d.id,
name: d.name,
record: {
id: uid(),
name: initName,
description: "Initial state when devtools is opened",
state: d.state,
createdAt: Date.now(),
},
};
sendMessage(eventInit, init, "devtools");

window.addEventListener(eventUpdate, (e) => {
const [i, state] = (e as StaloEvent).detail;
list[i].state = JSON.parse(state);
d.subscribe((record) => {
const req: Rec = { id: d.id, record };
sendMessage(eventRecord, req, "devtools");
});
})();
}
31 changes: 31 additions & 0 deletions chrome-extension/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const namespace = "@@stalo";
export const eventInit = "@@stalo-init";
export const eventRecord = "@@stalo-record";
export const eventSet = "@@stalo-set";
export const eventGet = "@@stalo-get";

type Rec<S> = {
id: string;
name: string;
state: S;
description?: string;
createdAt: number;
};

export type Init = {
sessionID: string;
name: string;
record: Rec<object>;
};

export type Get = string;

export type Set = {
id: string;
state: object;
};

export type Record = {
id: string;
record: Rec<object>;
};
29 changes: 8 additions & 21 deletions chrome-extension/src/content-script.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
import { sendMessage, onMessage } from "webext-bridge/content-script";
import { StaloEvent, eventInit, eventRecord, eventUpdate } from "./types";
import { allowWindowMessaging } from "webext-bridge/content-script";
import { namespace } from "./constants";

(() => {
window.addEventListener(eventInit, (e) => {
sendMessage(eventInit, (e as StaloEvent).detail, "devtools");
});
allowWindowMessaging(namespace);

window.addEventListener(eventRecord, (e) => {
sendMessage(eventRecord, (e as StaloEvent).detail, "devtools");
});

onMessage(eventUpdate, ({ data }) => {
const event = new CustomEvent(eventUpdate, { detail: data });
window.dispatchEvent(event);
});

window.addEventListener("load", () => {
const script = document.createElement("script");
script.src = chrome.runtime.getURL("communicator.js");
document.head.appendChild(script);
});
})();
window.addEventListener("load", () => {
const script = document.createElement("script");
script.src = chrome.runtime.getURL("communicator.js");
document.head.appendChild(script);
});
61 changes: 34 additions & 27 deletions chrome-extension/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,59 @@
import ReactDOM from "react-dom/client";
import { onMessage, sendMessage } from "webext-bridge/devtools";
import { eventInit, eventRecord, eventUpdate } from "./types";
import { Record } from "stalo/lib/devtools";
import { unplug, plug, Connection, Panel } from "@stalo/devtools-ui";
import {
eventGet,
eventInit,
eventRecord,
eventSet,
Get,
Init,
Record as Rec,
Set,
} from "./constants";
import { unplug, Connection, Panel, plug } from "@stalo/devtools-ui";

connect();
render();

const root = document.createElement("div");
function render() {
const root = document.createElement("div");

document.body.appendChild(root);
document.body.appendChild(root);

ReactDOM.createRoot(root).render(<Panel />);
ReactDOM.createRoot(root).render(<Panel chromeExtension />);
}

function connect() {
const list: Connection[] = [];
const list: Record<string, Connection> = {};

chrome.runtime.onConnect.addListener((port) => {
port.onDisconnect.addListener(() => {
list.forEach((_, id) => {
unplug(id);
});
Object.keys(list).forEach((id) => unplug(id));
});
});

onMessage(eventInit, async ({ data }) => {
const [id, name, rec] = data as unknown as [
number,
string,
Record<unknown>
];

onMessage<Init>(eventInit, ({ data }) => {
const conn: Connection = {
id,
name,
setState(json) {
sendMessage(eventUpdate, [id, json], "content-script");
id: data.sessionID,
name: data.name,
getState: async () => {
const req: Get = data.sessionID;
return await sendMessage(eventGet, req, "window");
},
setState: (state) => {
const req: Set = { id: data.sessionID, state };
sendMessage(eventSet, req, "window");
},
};

list[id] = conn;

plug(conn);

conn.onInit?.(rec);
conn.onInit?.(data.record);

list[conn.id] = conn;
});

onMessage(eventRecord, async ({ data }) => {
const [id, rec] = data as unknown as [number, Record<unknown>];
list[id].onRecord?.(rec);
onMessage<Rec>(eventRecord, ({ data }) => {
list[data.id]?.onRecord?.(data.record);
});
}
7 changes: 0 additions & 7 deletions chrome-extension/src/types.ts

This file was deleted.

11 changes: 10 additions & 1 deletion chrome-extension/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ import manifest from "./manifest";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), manifest],
optimizeDeps: { exclude: ["fsevents"] },
optimizeDeps: {
exclude: ["fsevents"],
include: [
`monaco-editor/esm/vs/language/json/json.worker`,
`monaco-editor/esm/vs/editor/editor.worker`,
],
},
build: {
chunkSizeWarningLimit: 10 * 1024 * 1024,
},
});
18 changes: 18 additions & 0 deletions chrome-extension/vite.ext.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineConfig } from "vite";

const name = process.env.ENTRY!;

export default defineConfig({
optimizeDeps: { exclude: ["fsevents"] },
build: {
emptyOutDir: false,
chunkSizeWarningLimit: 10 * 1024 * 1024,
rollupOptions: {
input: `./src/${name}.ts`,
output: {
entryFileNames: "[name].js",
format: "iife",
},
},
},
});
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"words": [
"codemirror",
"immer",
"immerable",
"okaidia",
"Stackframe",
"stalo",
"todomvc",
"todos",
Expand Down
15 changes: 15 additions & 0 deletions devtools-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Overview

## Usage

Check the [example](../examples/Devtools.tsx).

## Development

To develop the devtools-ui:

```bash
npm start
```

The entry file is the `index.html`.
Loading

0 comments on commit 2a32b4f

Please sign in to comment.