diff options
| author | Amadeus Demarzi <[email protected]> | 2025-12-17 05:33:46 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-17 07:33:46 -0600 |
| commit | 5c490c51edd5a8e3953fcc439d46c0e138294073 (patch) | |
| tree | 29f538fa1ad1666507960e30830b0f07db9de44a /packages/ui/src | |
| parent | 5da1c0087b7a0216bf633d12ff038422727ff235 (diff) | |
| download | opencode-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.tsx | 23 | ||||
| -rw-r--r-- | packages/ui/src/components/diff.css | 2 | ||||
| -rw-r--r-- | packages/ui/src/components/session-review.css | 1 | ||||
| -rw-r--r-- | packages/ui/src/context/worker-pool.tsx | 10 | ||||
| -rw-r--r-- | packages/ui/src/custom-elements.d.ts | 5 | ||||
| -rw-r--r-- | packages/ui/src/pierre/worker.ts | 36 |
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"], + }, + }) +})() |
