Skip to content

Commit 3226bf0

Browse files
committed
perf: compiler code move to woker thread
1 parent eca3296 commit 3226bf0

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

src/layout/root-preview/compiler.ts renamed to src/layout/root-preview/compiler.worker.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,28 @@ type TransformOptions = Parameters<typeof transform>["1"];
77
type PluginItem = TransformOptions["plugins"];
88
type PluginObj = NonNullable<PluginItem>[number];
99

10+
export interface CompilerMessageEventData {
11+
type: "CODE_COMPILED" | "CODE_COMPILE_ERROR";
12+
data: string | Error;
13+
}
14+
15+
// woker compiler
16+
self.addEventListener("message", ({ data }) => {
17+
try {
18+
self.postMessage({
19+
type: "CODE_COMPILED",
20+
data: compile(data),
21+
} satisfies CompilerMessageEventData);
22+
} catch (e) {
23+
self.postMessage({
24+
type: "CODE_COMPILE_ERROR",
25+
data: e as Error,
26+
} satisfies CompilerMessageEventData);
27+
}
28+
});
29+
1030
// 编译 main.tsx 的内容
11-
export const compile = (files: MultipleFiles) => {
31+
const compile = (files: MultipleFiles) => {
1232
const main = files[ENTRY_FILE_NAME];
1333
return babelTransform(ENTRY_FILE_NAME, main.value, files);
1434
};

src/layout/root-preview/index.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { useContext, useEffect, useState } from "react";
22
import { PlaygroundContext } from "@/core/context";
3-
import { compile } from "./compiler";
3+
import type { CompilerMessageEventData } from "./compiler.worker";
44
import iframeSource from "./iframe.html?raw";
55
import { IMPORT_MAP_FILE_NAME } from "@/core/files";
66
import ErrorAlert from "@/components/error-alert";
77
import { cn } from "@/lib/utils";
88

9+
const compilerWorker = new Worker(new URL("./compiler.worker.ts", import.meta.url), {
10+
type: "module",
11+
});
12+
913
function genIframeUrl(importMap: string, compilerCode: string) {
1014
const htmlStr = iframeSource
1115
.replace(
@@ -36,11 +40,21 @@ export default function RootPreview() {
3640

3741
// ============== Compiler ==============
3842
const [compiledCode, setCompiledCode] = useState("");
43+
3944
useEffect(() => {
40-
const res = compile(files);
41-
setCompiledCode(res);
45+
compilerWorker.postMessage(files);
4246
}, [files]);
4347

48+
useEffect(() => {
49+
compilerWorker.addEventListener("message", (ev: MessageEvent<CompilerMessageEventData>) => {
50+
if (ev.data.type === "CODE_COMPILED") {
51+
setCompiledCode(ev.data.data as string);
52+
} else if (ev.data.type === "CODE_COMPILE_ERROR") {
53+
console.error(ev.data.data);
54+
}
55+
});
56+
}, []);
57+
4458
// ============== Iframe Url ==============
4559
const [iframeUrl, setIframeUrl] = useState(() => genIframeUrl(importMapContent, compiledCode));
4660

@@ -52,9 +66,9 @@ export default function RootPreview() {
5266
// ============== Error Handler ==============
5367
const [errMsg, setErrMsg] = useState<string>();
5468

55-
const handleMessage = (event: MessageEvent<MessageData>) => {
56-
if (event.data.type === "ERROR") {
57-
setErrMsg(event.data.message);
69+
const handleMessage = (ev: MessageEvent<MessageData>) => {
70+
if (ev.data.type === "ERROR") {
71+
setErrMsg(ev.data.message);
5872
}
5973
};
6074

0 commit comments

Comments
 (0)