High-performance React code/text diff viewer for large text/code files with virtualized rendering.
- 📦 npm:
react-virtualized-diff - 🌐 Live Demo: https://www.zhangjiahang.com/react-virtualized-diff
- 📊 Benchmark report: benchmark-results/results.md
- 🇨🇳 中文文档: README.zh-CN.md
Most diff components are smooth for small files, but degrade heavily with 10k+ lines.
react-virtualized-diff is built for:
- Virtualized rendering for big-file performance
- Side-by-side layout for easy review
- Collapsed unchanged blocks with configurable context
- TypeScript support for predictable integration
pnpm add react-virtualized-diff
# or npm i react-virtualized-diff
# or yarn add react-virtualized-diffimport { DiffViewer } from 'react-virtualized-diff';
const original = `line 1\nline 2\nline 3`;
const modified = `line 1\nline 2 changed\nline 3\nline 4`;
export function App() {
return (
<DiffViewer
original={original}
modified={modified}
contextLines={2}
height={480}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
original |
string |
- | Original text content (new API) |
modified |
string |
- | Modified text content (new API) |
oldValue |
string |
- | Compatibility API: same as original |
newValue |
string |
- | Compatibility API: same as modified |
splitView |
boolean |
true |
true for side-by-side, false for unified/inline |
showDiffOnly |
boolean |
true |
Show only changed lines with collapsible unchanged blocks |
contextLines |
number |
2 |
Number of unchanged lines kept around diff hunks |
extraLinesSurroundingDiff |
number |
- | Compatibility API alias for context lines |
hideLineNumbers |
boolean |
false |
Hide line number columns |
highlightLines |
Array<'L-n' | 'R-n' | range> |
- | Highlight specific lines (L-3, R-5, L-10-15) |
onLineNumberClick |
(lineId) => void |
- | Called when a line number is clicked |
renderContent |
(line: string) => ReactNode |
- | Custom line content renderer (syntax highlighting etc.) |
compareMethod |
"CHARS" | "WORDS" | "WORDS_WITH_SPACE" | "LINES" | "TRIMMED_LINES" | "SENTENCES" | "CSS" |
"LINES" |
Diff compare strategy |
disableWordDiff |
boolean |
false |
Disable inline word-level diff highlighting |
leftTitle |
ReactNode |
- | Left pane title (split view) |
rightTitle |
ReactNode |
- | Right pane title (split view) |
linesOffset |
number |
0 |
Add offset to displayed line numbers |
useDarkTheme |
boolean |
false |
Built-in dark theme |
styles |
Partial<DiffViewerStyles> |
- | Override style slots |
codeFoldMessageRenderer |
({ hiddenCount, expanded }) => ReactNode |
- | Custom fold button content renderer |
height |
number | string |
500 |
Viewport height of the virtual list |
locale |
DiffViewerLocale |
- | UI text localization |
language |
string |
- | Reserved field for future language-related extensions |
| Field | Type | Description |
|---|---|---|
collapse |
string |
Label for collapse button |
showMoreLines |
(count: number) => string |
Label factory for “show hidden lines” |
Included benchmark compares:
react-virtualized-diffreact-diff-viewerreact-diff-viewer-continuedreact-diff-view
Dataset sizes: 1k / 10k / 50k / 100k lines.
Metrics:
- FPS (during auto-scroll)
- initial render time
- memory usage (
usedJSHeapSize)
Quick highlights from the latest report (2026-04-08T06:45:43.686Z):
- At
10klines (react-virtualized-diff):60.8 FPS,127.0 msinitial render,9.5 MBmemory. - At
50k/100klines:react-diff-viewerandreact-diff-viewer-continuedboth timeout (60000 msper case). - At
100klines:104.0 MB(react-virtualized-diff) vs1297.0 MB(react-diff-view).
Run benchmark:
pnpm install
pnpm benchmark- Hosted demo page: https://www.zhangjiahang.com/react-virtualized-diff
- Local demo:
pnpm install
pnpm devapps/demo/ # Vite demo app
apps/benchmark/ # benchmark app
packages/react/ # npm package source
See CHANGELOG.md.
MIT
