This guide installs the package, selects the correct API family, and completes a patch round trip.
npm install react-native-bs-diff-patchInstall iOS pods after adding or updating the native dependency:
npx pod-installReact Native autolinking handles Android and iOS registration. Rebuild the native application after installation; reloading Metro does not change the native modules inside an already-installed binary.
| Runtime | Use | Do not use |
|---|---|---|
| Android, iOS | diff/patch or native jobs |
Binary-data APIs |
| Web | diffBytes and patchBytes |
File-path APIs |
The unavailable family rejects with EUNSUPPORTED, which helps catch imports
that resolved to an unexpected platform entry.
Native APIs operate on absolute file paths. The library does not choose a storage directory or manage file lifetime; use the filesystem solution already present in your application.
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}/release-${runId}.patch`;
const restoredPath = `${cacheDirectory}/release-${runId}.restored`;
await diff(oldFilePath, newFilePath, patchPath);
await patch(oldFilePath, restoredPath, patchPath);
return { patchPath, restoredPath };
}Before calling diff:
oldFilePathandnewFilePathmust exist.patchPathmust not exist.- All three paths must be non-empty and different.
Before calling patch:
oldFilePathandpatchPathmust exist.restoredPathmust not exist.- All three paths must be non-empty and different.
Use a content hash or byte comparison from your filesystem layer to verify that
restoredPath matches newFilePath. Clean the patch and restored file when
they are no longer needed.
Use a job when the operation is user-controlled or processes untrusted input:
import { startPatch } from 'react-native-bs-diff-patch';
const job = startPatch(oldFilePath, restoredPath, patchPath, {
maxInputBytes: 64 * 1024 * 1024,
maxOutputBytes: 128 * 1024 * 1024,
});
const unsubscribe = job.onProgress(({ phase, progress }) => {
setOperationState({ phase, percent: Math.round(progress * 100) });
});
try {
await job.result;
} catch (error) {
if ((error as { code?: string }).code !== 'ECANCELLED') throw error;
} finally {
unsubscribe();
}
// Wire this to the screen's Cancel action while result is pending.
cancelButton.onPress = () => void job.cancel();startDiff accepts the same options. Native jobs write through a sibling
temporary file, so cancellation or a limit failure does not expose a partial
destination.
React Native Web uses binary values instead of filesystem paths:
import { diffBytes, patchBytes } from 'react-native-bs-diff-patch';
const encoder = new TextEncoder();
const oldData = encoder.encode('version 1');
const newData = encoder.encode('version 2 with web support');
const controller = new AbortController();
const options = {
signal: controller.signal,
maxInputBytes: 32 * 1024 * 1024,
maxOutputBytes: 32 * 1024 * 1024,
};
const patchData = await diffBytes(oldData, newData, options);
const restoredData = await patchBytes(oldData, patchData, options);
const matches =
restoredData.length === newData.length &&
restoredData.every((byte, index) => byte === newData[index]);
if (!matches) {
throw new Error('Patch round trip did not reproduce the target data');
}Inputs are copied before being transferred to the module Worker, so the
caller's buffers remain usable. Each result is a new Uint8Array.
Call controller.abort() to reject the active operation with EABORTED.
Configured byte limits reject with ERESOURCE. Calls without a signal reuse a
shared Worker and WebAssembly instance; calls with a signal use a dedicated
Worker so aborting one operation cannot interrupt another.
import { diffBytes } from 'react-native-bs-diff-patch';
export async function downloadPatch(oldFile: File, newFile: File) {
const patchData = await diffBytes(oldFile, newFile);
const url = URL.createObjectURL(
new Blob([patchData], { type: 'application/octet-stream' })
);
const link = document.createElement('a');
link.href = url;
link.download = 'update.patch';
link.click();
URL.revokeObjectURL(url);
}The Web API is client-only. Importing it during server-side rendering is safe,
but call it only after a browser Worker is available.
- Copy a recovery pattern from Production recipes.
- Review all signatures and error codes in the API reference.
- Review controllable native operations.
- Check platform and bundler support.
- Try the live Playground.