Create a compact binary patch from two versions of a file, then reconstruct the
new version from the old file and that patch. Android, iOS, and React Native Web
all use the compatible ENDSLEY/BSDIFF43 wire format.
Documentation · Playground · 中文说明 · npm
- One patch format: generate on one supported runtime and apply on another.
- Both React Native architectures: legacy bridge and TurboModule/New Architecture.
- Responsive by default: native work uses dedicated serial queues; Web work reuses a module Worker and cached WebAssembly instance off the page thread.
- Bound untrusted Web work: built-in cancellation and input/output byte limits reject predictably with stable error codes.
- No Web service required: the browser implementation is the same bundled C core compiled to WebAssembly.
| Runtime | Input model | Create a patch | Apply a patch |
|---|---|---|---|
| Android, iOS | Absolute paths | diff |
patch |
| Web | In-memory binaries | diffBytes |
patchBytes |
npm install react-native-bs-diff-patchAfter adding the package, install iOS pods and rebuild the native app:
npx pod-installReact Native autolinking handles native registration. A Metro reload alone is not enough after adding a native dependency.
The native API works with absolute file paths. Use the filesystem library already present in your app to select a writable cache directory.
import { diff, patch } from 'react-native-bs-diff-patch';
type NativeRoundTripOptions = {
oldFilePath: string;
newFilePath: string;
cacheDirectory: string;
};
export async function nativeRoundTrip({
oldFilePath,
newFilePath,
cacheDirectory,
}: NativeRoundTripOptions) {
const runId = Date.now();
const patchPath = `${cacheDirectory}/update-${runId}.patch`;
const restoredPath = `${cacheDirectory}/restored-${runId}.bin`;
await diff(oldFilePath, newFilePath, patchPath);
await patch(oldFilePath, restoredPath, patchPath);
return { patchPath, restoredPath };
}Output paths must not exist, all paths in one call must be different, and the
required input files must already exist. Both functions resolve to 0 on
success.
import { diffBytes, patchBytes } from 'react-native-bs-diff-patch';
export async function webRoundTrip(
oldFile: File,
newFile: File,
signal?: AbortSignal
) {
const oldData = await oldFile.arrayBuffer();
const newData = await newFile.arrayBuffer();
const options = {
signal,
maxInputBytes: 64 * 1024 * 1024,
maxOutputBytes: 64 * 1024 * 1024,
};
const patchData = await diffBytes(oldData, newData, options);
const restoredData = await patchBytes(oldData, patchData, options);
return { patchData, restoredData };
}diffBytes and patchBytes accept ArrayBuffer, any ArrayBufferView
(including typed arrays and DataView), or Blob. They resolve to a new
Uint8Array and leave the caller's buffers usable. Aborted operations reject
with EABORTED; configured size limits reject with ERESOURCE.
| API | Android | iOS | Web |
|---|---|---|---|
diff(oldPath, newPath, patchPath) |
Yes | Yes | No |
patch(oldPath, outputPath, patchPath) |
Yes | Yes | No |
diffBytes(oldData, newData, options?) |
No | No | Yes |
patchBytes(oldData, patchData, options?) |
No | No | Yes |
| Legacy architecture | Yes | Yes | N/A |
| New Architecture / TurboModule | Yes | Yes | N/A |
Calling an API family that is unavailable on the current platform rejects with
EUNSUPPORTED instead of silently choosing different behavior.
- Verify the restored output before replacing application data.
- Authenticate patches from remote or otherwise untrusted sources.
- Use unique native output paths and clean temporary files after success or failure.
- Set product-specific input-size and time 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 error handling, downloads, cross-runtime patch exchange, and integrity checks.
CI directly compiles the Android New Architecture sources against React Native 0.73.11, 0.74.7, and 0.86.0. Packed-consumer tests also verify that browser, ESM, CommonJS, and TypeScript resolution work without installing optional React Native peers for Web-only consumers.
- Getting started
- API reference
- Production recipes
- Platform support
- Architecture and patch format
- 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