v-code-diff: rendering diffs inside a Vue app without writing the UI
A vue code diff display plugin, support Vue2 / Vue3
At a glance
- What is it?
- v-code-diff is a Vue component that takes two strings and draws the difference between them, in line by line or side by side form, for Vue 2.6, Vue 2.7 and Vue 3. It renders at most 1,000 visible lines at a time and loads the rest on demand.
- Who is it for?
- v-code-diff suits a product team that has to show a diff to a user inside an existing Vue application, for Vue 2.6, 2.7 or 3, and that wants to hand off comparison UI rather than build it. It does not suit a project that compares files in a build script, that cannot run install scripts, or that needs a hundred thousand changed lines rendered at once.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 61 days ago.
- What is it written in?
- Mainly SCSS, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A component, not a diff engine you call directly
The unit v-code-diff gives you is a Vue component called CodeDiff. You hand it the text before a change and the text after it, and it draws the difference.
The props table defines the contract. oldString and newString are the two texts, both strings, both required in practice. language selects the syntax highlighting language, such as javascript, and defaults to plain text. context is the number of unchanged lines shown around each change and defaults to 10. outputFormat picks the display mode, either line-by-line or side-by-side, and defaults to line-by-line. diffStyle sets the inline difference granularity, words or characters.
That last prop is the one that changes what the component is for. Word level or character level inline highlighting is what separates a diff viewer for prose from one for source code, and it is the part of the work that is tedious to reimplement.
The component targets Vue 2.6, Vue 2.7 and Vue 3, and the repository ships a playground for each: vue2-playground/, vue2.7-playground/ and vue3-playground/, plus a demo directory with its own Vite config. The primary language of the repository is listed as SCSS, which is where the styling lives, and the behaviour is TypeScript with type declarations published under types/.
The 0.x line is over. The README states that the 0.x line ended at 0.3.12 and is no longer maintained, that it was based on vue-code-diff by ddchef, and that version 1.x aims to preserve its core behaviour while keeping migration straightforward.
One package, three builds, chosen by a postinstall script
Installing v-code-diff from npm gives you a package whose build is picked for your Vue version at install time:
# npm
npm i v-code-diff
# yarn
yarn add v-code-diff
# pnpm
pnpm add v-code-diffThe mechanism is a postinstall script that selects the build for your Vue version. The README warns not to install with --ignore-scripts, and if pnpm reports that the build script was blocked, you approve it and let pnpm run the script:
pnpm approve-builds v-code-diffThe package manifest explains why this is needed. The exports map has four entry points: the root, then ./vue2, ./vue2.7 and ./vue3, each with its own ES module and CommonJS build under dist/. The build scripts in package.json use vue-demi-switch to flip the project between Vue versions, with separate build and build:umd targets for 2, 2.7 and 3.
So the package ships three builds and picks one for you, which is convenient and also the source of the sharpest edge in the install story. A blocked or skipped postinstall leaves you with a build for the wrong Vue version, and the README says so in plain terms. In CI, a package manager configured to skip lifecycle scripts, or a cached install that predates the change, will produce a component that fails in ways that look like your own code.
The package is a native ES module package with type set to module, MIT licensed, and the repository pins pnpm as the package manager at [email protected].
Registering the component in a Vue 3 or Vue 2 app
Local registration is the recommended path, and the README recommends it for tree shaking support. In Vue 3 with script setup it is two pieces:
<script setup>
import { CodeDiff } from 'v-code-diff'
</script>
<template>
<div>
<CodeDiff
old-string="12345"
new-string="3456"
output-format="side-by-side"
/>
</div>
</template>Global registration in Vue 3 installs the component as a plugin on the app:
import { createApp } from 'vue'
import CodeDiff from 'v-code-diff'
import App from './App.vue'
createApp(App).use(CodeDiff).mount('#app')After that, the component can be used in any template as code-diff with the same props.
Vue 2 uses the options API shape instead:
<script>
import { CodeDiff } from 'v-code-diff'
export default {
components: {
CodeDiff
}
}
</script>and the global form for Vue 2 is:
import Vue from 'vue'
import CodeDiff from 'v-code-diff'
Vue.use(CodeDiff)One extra step applies to Vue 2.6 only. Those users must also install and register @vue/composition-api:
pnpm add @vue/composition-apiimport Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)That is the composition API plugin being backported to Vue 2, and the component needs it because it is written in the Vue 3 style. Vue 2.7 has the composition API built in, which is why the split is only documented for 2.6.
Rendering stops at 1,000 visible lines
The performance section is unusually specific, and the key architectural decision sits in its last paragraph. Rendering is limited to the first 1,000 visible lines, with later batches highlighted on demand. In other words, the component computes the diff but does not paint every hunk of a very large comparison at once.
That single design decision is what makes the rest of the numbers possible. The reference results are for v1.16.0 on an Apple M4 Max with 36 GB of RAM, Node.js 24.15.0 and Chrome 151, using language="plaintext" and context=3. The README states that results vary by hardware and input, and that the 100,000-line cases are stress tests, not a supported size guarantee.
The diff benchmark medians show the shape of the work. 15,000 identical lines take 1.3 ms. 15,000 lines with one change take 8.5 ms line by line and 8.2 ms side by side. 15,000 lines all changed take 37.9 ms. A 100 KB single line JSON with one change takes 0.9 ms, while 100,000 lines with one change take 37.3 ms and 40,000 lines with 9 percent changed take 40.0 ms.
The Chrome rendering results are given as render time and retained JS heap after forced garbage collection. 4,000 lines with one change render in 14.3 ms with 4.1 MB retained line by line, and 13.7 ms with 4.3 MB side by side. 10,000 lines all changed render in 68.9 ms with 10.6 MB. At the far end, 100,000 lines all changed take 243.5 ms and 52.7 MB line by line, and 261.4 ms and 53.9 MB side by side.
Both suites are reproducible from the repository, with the diff and SSR benchmarks run by:
pnpm benchmarkThe package script behind that command builds the Vue 3 target first, runs vitest bench, and then executes benchmarks/render.mjs under node with garbage collection exposed.
Repeated updates do not leak, which is the harder half
The stability check deserves as much attention as the speed numbers, because a diff viewer is usually mounted on a page that the user navigates in and out of.
Updating a mounted 10,000 line comparison 20 times changed the retained heap by at most 0.2 MB. Mounting and unmounting a 100,000 line comparison five times showed no retained growth. Those two sentences describe the behaviour a component library has to get right, and they are the ones a consumer of a diff viewer cares about most in practice, since a comparison view that grows on every navigation is a memory problem in a long lived session.
The mechanism behind it is the batching already mentioned. Only the visible portion is rendered, and later batches are highlighted on demand, so the component never holds the entire rendered result of a huge diff in the DOM at once. The diff computation itself still happens, which is why the diff benchmark figures for 100,000 lines are in the tens of milliseconds rather than a fraction of a millisecond.
The trade-off is that a user scrolling through a very large comparison sees batches being processed, so the experience of a hundred thousand line comparison is explicitly a stress test scenario rather than the target case. For the sizes a product would actually show, a handful of changed files or a few hundred lines of code, the numbers are unremarkable in the best way.
Where v-code-diff stops being the right tool
Several boundaries are worth naming before you commit.
The first is the install script. A package whose build is chosen by a postinstall hook is a package that can be installed correctly and still be wrong, and the README warns about both --ignore-scripts and pnpm's build approval. If your organisation blocks lifecycle scripts in CI, or you use a package manager configuration that skips them, this component needs a different distribution story.
The second is Vue 2.6, which needs @vue/composition-api installed and registered. That is an extra dependency and an extra registration step for a version that has been superseded twice over.
The third is the scope of the work. The component compares two strings. It does not read files, does not compute a diff between two commits, and does not walk a repository. If you need that, you compute it elsewhere and pass the two strings in, which is fine but means the component is the last 10 percent of the problem rather than the whole of it.
The fourth is rendering at scale. A comparison where every line changed renders in 243.5 ms and retains 52.7 MB, and the README is explicit that the 100,000-line cases are stress tests rather than a supported size guarantee. If your product needs to show a whole file rewritten, this is not the component to reach for.
One more limitation is documentation. The README covers props, events, a demo, performance, extending languages and migration from 0.x, but the events section is not reproduced in the visible part of the documentation, so anyone relying on emitted events should read the source rather than assume.
Where it sits against the projects it grew out of
The README credits the projects that shaped it: vue-diff by hoiheart, vue-code-diff by ddchef, and GitHub's own code diff view. The 0.x line of v-code-diff was itself based on vue-code-diff.
So the realistic alternatives are concrete. vue-code-diff is the direct ancestor and the closest substitute, and it is where the 0.x line came from. vue-diff is the other Vue specific diff component in the same space. And a third option, which is not a library at all, is to build the comparison view yourself on top of a diff library and your own styles, which gives you full control over the interaction but costs you the part of this project that is genuinely hard to reproduce: the word and character level inline highlighting, the 1,000 line batching, and the heap behaviour under repeated updates.
What v-code-diff adds over its ancestors is coverage of the Vue version matrix and the packaging to go with it. The 1.x line ships builds for Vue 2.6, Vue 2.7 and Vue 3 with type declarations for each, supports both line-by-line and side-by-side output, adds character level diffing, and documents its performance and memory behaviour rather than leaving it to guesswork.
On maintenance, the record is recent. The last push was on 2026-08-23, and three releases landed the same day: v1.14.1, v1.15.0 and v1.16.0. The licence is MIT, which is the permissive option with no obligations beyond keeping the notice, and there is a separate Simplified Chinese README, a changelog-history.md and a docs directory for the long form documentation.
Editorial conclusion
v-code-diff suits a product team that has to show a diff to a user inside an existing Vue application, for Vue 2.6, 2.7 or 3, and that wants to hand off comparison UI rather than build it. It does not suit a project that compares files in a build script, that cannot run install scripts, or that needs a hundred thousand changed lines rendered at once. Verify first by running pnpm benchmark in a clone of the repository to see the diff and render numbers on your own hardware, then by checking the postinstall step in your CI pipeline, because pnpm blocks it by default and the component silently ships the wrong Vue build if the script never runs.
Frequently asked questions
How do I install v-code-diff?
It is published on npm and installs with npm i v-code-diff, yarn add v-code-diff or pnpm add v-code-diff. The package uses a postinstall script to select the build for your Vue version, so do not install it with --ignore-scripts, and run pnpm approve-builds v-code-diff if pnpm reports the build script was blocked.
Which Vue versions does v-code-diff support?
The component supports Vue 2.6, Vue 2.7 and Vue 3, with separate builds published under the ./vue2, ./vue2.7 and ./vue3 export paths. Vue 2.6 users must also install and register @vue/composition-api.
How many lines can v-code-diff render at once?
Rendering is limited to the first 1,000 visible lines, with later batches highlighted on demand. The reference results state that the 100,000-line cases are stress tests rather than a supported size guarantee.
What props does the CodeDiff component take?
oldString and newString hold the two texts, language sets the highlighting language and defaults to plaintext, context sets the number of unchanged lines shown around a change and defaults to 10, outputFormat chooses line-by-line or side-by-side, and diffStyle chooses word or character granularity.
Can I run the performance benchmarks myself?
Yes. The repository has a benchmark script that builds the Vue 3 target, runs vitest bench and then runs benchmarks/render.mjs, and it is invoked with pnpm benchmark. The published numbers were measured on an Apple M4 Max with Node.js 24.15.0 and Chrome 151.
What happened to the 0.x versions of v-code-diff?
The 0.x line ended at 0.3.12 and is no longer maintained. It was based on vue-code-diff by ddchef, and the 1.x line aims to preserve its core behaviour while keeping migration straightforward.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/shimada666-v-code-diff)Was this useful?