summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src
diff options
context:
space:
mode:
authorAmadeus Demarzi <[email protected]>2025-12-17 05:33:46 -0800
committerGitHub <[email protected]>2025-12-17 07:33:46 -0600
commit5c490c51edd5a8e3953fcc439d46c0e138294073 (patch)
tree29f538fa1ad1666507960e30830b0f07db9de44a /packages/ui/src
parent5da1c0087b7a0216bf633d12ff038422727ff235 (diff)
downloadopencode-5c490c51edd5a8e3953fcc439d46c0e138294073.tar.gz
opencode-5c490c51edd5a8e3953fcc439d46c0e138294073.zip
Diffs Performance Improvements (#5653)
Co-authored-by: Adam <[email protected]>
Diffstat (limited to 'packages/ui/src')
-rw-r--r--packages/ui/src/components/diff-ssr.tsx23
-rw-r--r--packages/ui/src/components/diff.css2
-rw-r--r--packages/ui/src/components/session-review.css1
-rw-r--r--packages/ui/src/context/worker-pool.tsx10
-rw-r--r--packages/ui/src/custom-elements.d.ts5
-rw-r--r--packages/ui/src/pierre/worker.ts36
6 files changed, 53 insertions, 24 deletions
diff --git a/packages/ui/src/components/diff-ssr.tsx b/packages/ui/src/components/diff-ssr.tsx
index b38b4a34f..e367a4fbe 100644
--- a/packages/ui/src/components/diff-ssr.tsx
+++ b/packages/ui/src/components/diff-ssr.tsx
@@ -1,8 +1,9 @@
-import { FileDiff } from "@pierre/diffs"
+import { DIFFS_TAG_NAME, FileDiff } from "@pierre/diffs"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
import { onCleanup, onMount, Show, splitProps } from "solid-js"
-import { isServer } from "solid-js/web"
+import { Dynamic, isServer } from "solid-js/web"
import { createDefaultOptions, styleVariables, type DiffProps } from "../pierre"
+import { useWorkerPool } from "../context/worker-pool"
export type SSRDiffProps<T = {}> = DiffProps<T> & {
preloadedDiff: PreloadMultiFileDiffResult<T>
@@ -12,17 +13,21 @@ export function Diff<T>(props: SSRDiffProps<T>) {
let container!: HTMLDivElement
let fileDiffRef!: HTMLElement
const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"])
+ const workerPool = useWorkerPool()
let fileDiffInstance: FileDiff<T> | undefined
const cleanupFunctions: Array<() => void> = []
onMount(() => {
if (isServer || !props.preloadedDiff) return
- fileDiffInstance = new FileDiff<T>({
- ...createDefaultOptions(props.diffStyle),
- ...others,
- ...props.preloadedDiff,
- })
+ fileDiffInstance = new FileDiff<T>(
+ {
+ ...createDefaultOptions(props.diffStyle),
+ ...others,
+ ...props.preloadedDiff,
+ },
+ workerPool,
+ )
// @ts-expect-error - fileContainer is private but needed for SSR hydration
fileDiffInstance.fileContainer = fileDiffRef
fileDiffInstance.hydrate({
@@ -65,11 +70,11 @@ export function Diff<T>(props: SSRDiffProps<T>) {
return (
<div data-component="diff" style={styleVariables} ref={container}>
- <diffs-container ref={fileDiffRef} id="ssr-diff">
+ <Dynamic component={DIFFS_TAG_NAME} ref={fileDiffRef} id="ssr-diff">
<Show when={isServer}>
<template shadowrootmode="open" innerHTML={props.preloadedDiff.prerenderedHTML} />
</Show>
- </diffs-container>
+ </Dynamic>
</div>
)
}
diff --git a/packages/ui/src/components/diff.css b/packages/ui/src/components/diff.css
index 345271a12..3251eb4c6 100644
--- a/packages/ui/src/components/diff.css
+++ b/packages/ui/src/components/diff.css
@@ -1,4 +1,6 @@
[data-component="diff"] {
+ contain: content;
+
[data-slot="diff-hunk-separator-line-number"] {
position: sticky;
left: 0;
diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css
index 0cd228592..35df4a80f 100644
--- a/packages/ui/src/components/session-review.css
+++ b/packages/ui/src/components/session-review.css
@@ -5,6 +5,7 @@
height: 100%;
overflow-y: auto;
scrollbar-width: none;
+ contain: strict;
&::-webkit-scrollbar {
display: none;
}
diff --git a/packages/ui/src/context/worker-pool.tsx b/packages/ui/src/context/worker-pool.tsx
new file mode 100644
index 000000000..fc2eecc03
--- /dev/null
+++ b/packages/ui/src/context/worker-pool.tsx
@@ -0,0 +1,10 @@
+import type { WorkerPoolManager } from "@pierre/diffs/worker"
+import { createSimpleContext } from "./helper"
+
+const ctx = createSimpleContext<WorkerPoolManager | undefined, { pool: WorkerPoolManager | undefined }>({
+ name: "WorkerPool",
+ init: (props) => props.pool,
+})
+
+export const WorkerPoolProvider = ctx.provider
+export const useWorkerPool = ctx.use
diff --git a/packages/ui/src/custom-elements.d.ts b/packages/ui/src/custom-elements.d.ts
index b756e51da..49ec4449f 100644
--- a/packages/ui/src/custom-elements.d.ts
+++ b/packages/ui/src/custom-elements.d.ts
@@ -1,12 +1,15 @@
+import { DIFFS_TAG_NAME } from "@pierre/diffs"
+
/**
* TypeScript declaration for the <diffs-container> custom element.
* This tells TypeScript that <diffs-container> is a valid JSX element in SolidJS.
* Required for using the @pierre/diffs web component in .tsx files.
*/
+
declare module "solid-js" {
namespace JSX {
interface IntrinsicElements {
- "diffs-container": HTMLAttributes<HTMLElement>
+ [DIFFS_TAG_NAME]: HTMLAttributes<HTMLElement>
}
}
}
diff --git a/packages/ui/src/pierre/worker.ts b/packages/ui/src/pierre/worker.ts
index e47268d4e..2d2640674 100644
--- a/packages/ui/src/pierre/worker.ts
+++ b/packages/ui/src/pierre/worker.ts
@@ -1,20 +1,28 @@
-import { getOrCreateWorkerPoolSingleton } from "@pierre/diffs/worker"
+import { getOrCreateWorkerPoolSingleton, WorkerPoolManager } from "@pierre/diffs/worker"
import ShikiWorkerUrl from "@pierre/diffs/worker/worker.js?worker&url"
export function workerFactory(): Worker {
return new Worker(ShikiWorkerUrl, { type: "module" })
}
-export const workerPool = getOrCreateWorkerPoolSingleton({
- poolOptions: {
- workerFactory,
- // poolSize defaults to 8. More workers = more parallelism but
- // also more memory. Too many can actually slow things down.
- // poolSize: 8,
- },
- highlighterOptions: {
- theme: "OpenCode",
- // Optionally preload languages to avoid lazy-loading delays
- // langs: ["typescript", "javascript", "css", "html"],
- },
-})
+export const workerPool: WorkerPoolManager | undefined = (() => {
+ if (typeof window === "undefined") {
+ return undefined
+ }
+ return getOrCreateWorkerPoolSingleton({
+ poolOptions: {
+ workerFactory,
+ // poolSize defaults to 8. More workers = more parallelism but
+ // also more memory. Too many can actually slow things down.
+ // NOTE: 2 is probably better for OpenCode, as I think 8 might be
+ // a bit overkill, especially because Safari has a significantly slower
+ // boot up time for workers
+ poolSize: 2,
+ },
+ highlighterOptions: {
+ theme: "OpenCode",
+ // Optionally preload languages to avoid lazy-loading delays
+ // langs: ["typescript", "javascript", "css", "html"],
+ },
+ })
+})()