Turn two versions of a file into a compact binary patch, then reconstruct the new file from the old file plus that patch.
One compatible format across React Native Android, iOS, and Web.
Documentation · Live Playground · 中文说明 · npm
Use it when your app already has an old version of a file and you want to move to a new version without transporting the complete replacement file.
| 1. Create the delta | 2. Deliver it your way | 3. Reconstruct the file |
|---|---|---|
Compare old.bin with new.bin and produce update.patch. |
Send or store the patch with your existing CDN, API, or offline workflow. | Apply update.patch to old.bin and write the restored new.bin. |
The library handles binary diffing and patching. Your application remains in control of transport, authentication, integrity checks, and when an output replaces live data.
- One wire format: Android, iOS, and Web produce compatible
ENDSLEY/BSDIFF43patches. - Every current RN runtime: legacy bridge and TurboModule/New Architecture are both supported.
- Native performance, browser reach: JNI/ObjC++ use the bundled C core; React Native Web runs that core as WebAssembly in a reusable module Worker.
- Control expensive native work: observe progress, cancel cooperatively, cap input/output sizes, and avoid exposing partial output files.
- No patch service required: Web diffing and patching happen locally in the browser.
| Android / iOS | React Native Web | |
|---|---|---|
| Input | Absolute file paths | ArrayBuffer, typed arrays, DataView, or Blob |
| Basic API | diff() / patch() |
diffBytes() / patchBytes() |
| Controlled API | startDiff() / startPatch() |
AbortSignal and binary limits |
| Engine | Native C via JNI / ObjC++ | Same C core via WASM Worker |
npm install react-native-bs-diff-patchFor iOS, install Pods and rebuild the native application:
npx pod-installReact Native autolinking handles native registration. Adding a native module requires a native rebuild; a Metro reload is not enough.
Native APIs use absolute paths. Pick unique output paths in a writable cache or documents directory through the filesystem library already used by your app.
import { diff, patch } from 'react-native-bs-diff-patch';
const patchPath = `${cacheDirectory}/content-v2.patch`;
const restoredPath = `${cacheDirectory}/content-v2.restored`;
await diff(oldFilePath, newFilePath, patchPath);
await patch(oldFilePath, restoredPath, patchPath);Input files must already exist. Output paths must not exist, and all paths in a
single call must be different. Both functions resolve to 0 on success.
Use the job API for work that needs lifecycle control:
import { startPatch } from 'react-native-bs-diff-patch';
const job = startPatch(oldPath, outputPath, patchPath, {
maxInputBytes: 64 * 1024 * 1024,
maxOutputBytes: 128 * 1024 * 1024,
});
const unsubscribe = job.onProgress(({ phase, progress }) => {
renderProgress(phase, progress);
});
try {
await job.result;
// await job.cancel(); // cancel from your UI when needed
} finally {
unsubscribe();
}import { diffBytes, patchBytes } from 'react-native-bs-diff-patch';
const oldBytes = await oldFile.arrayBuffer();
const newBytes = await newFile.arrayBuffer();
const patchBytesValue = await diffBytes(oldBytes, newBytes, {
signal: abortController.signal,
maxInputBytes: 64 * 1024 * 1024,
});
const restoredBytes = await patchBytes(oldBytes, patchBytesValue, {
maxOutputBytes: 64 * 1024 * 1024,
});Web calls return a new Uint8Array and leave caller-owned buffers usable.
Aborted operations reject with EABORTED; configured binary limits reject with
ERESOURCE.
| API | Android | iOS | Web |
|---|---|---|---|
diff(oldPath, newPath, patchPath) |
Yes | Yes | No |
patch(oldPath, outputPath, patchPath) |
Yes | Yes | No |
startDiff(...) / startPatch(...) |
Yes | Yes | No |
diffBytes(oldData, newData, options?) |
No | No | Yes |
patchBytes(oldData, patchData, options?) |
No | No | Yes |
| Legacy architecture, while supplied by RN | Yes | Yes | N/A |
| New Architecture / TurboModule | Yes | Yes | N/A |
Unavailable platform APIs reject with EUNSUPPORTED; the package never
silently switches to a different input model.
- Authenticate patches from remote or otherwise untrusted sources.
- Verify restored output before replacing application data.
- Use unique native output paths and remove outputs you no longer need.
- Set product-specific resource limits. Binary diffing can use several times the input size in peak memory.
- Generate and apply patches with this library. Generic
BSDIFF40patches are not interchangeable withENDSLEY/BSDIFF43patches.
See Production recipes for integrity checks, downloads, cross-runtime exchange, error handling, and cleanup patterns.
CI compiles the Android and iOS APIs against React Native 0.73.11, 0.74.7, and 0.86.0, and runs device-level New Architecture assertions on Android and iOS. Packed-consumer tests verify browser, ESM, CommonJS, Metro, and TypeScript resolution from the real npm package shape.
- Getting started
- API reference
- Production recipes
- Platform support
- Architecture and patch format
- Controllable native operations
- Troubleshooting
- Development and verification
See CONTRIBUTING.md for the local workflow and quality gates. Release history is in CHANGELOG.md; security reports follow SECURITY.md.
MIT