IncrementalBundler
A watch-mode bundler that maintains an internal dependency graph, module cache, and module map across rebuilds. Only re-transforms changed files and their affected dependents.
Usage
import {
IncrementalBundler, VirtualFS, reactRefreshTransformer
} from "browser-metro";
const config: BundlerConfig = {
resolver: { sourceExts: ["ts", "tsx", "js", "jsx"] },
transformer: reactRefreshTransformer,
server: { packageServerUrl: "https://esm.reactnative.run" },
hmr: { enabled: true, reactRefresh: true },
plugins: [myPlugin],
};
const bundler = new IncrementalBundler(vfs, config);Methods
async build(entryFile: string): Promise<IncrementalBuildResult>
Performs the initial full build. Must be called before rebuild().
const result = await bundler.build("/index.tsx");
// result.bundle -- full bundle string
// result.type -- "full"
// result.hmrUpdate -- null (initial build)async rebuild(changes: FileChange[]): Promise<IncrementalBuildResult>
Incrementally rebuilds based on file changes. Returns a result that may include an HMR update.
const result = await bundler.rebuild([
{ path: "/App.tsx", type: "update" },
]);
if (result.hmrUpdate && !result.hmrUpdate.requiresReload) {
// Send HMR update to iframe
iframe.postMessage({
type: "hmr-update",
updatedModules: result.hmrUpdate.updatedModules,
removedModules: result.hmrUpdate.removedModules,
});
} else {
// Full reload needed
loadBundle(result.bundle);
}updateFS(fs: VirtualFS): void
Replaces the internal VirtualFS. Call after modifying files, before rebuild().
IncrementalBuildResult
interface IncrementalBuildResult {
bundle: string; // full bundle (always available as fallback)
hmrUpdate: HmrUpdate | null; // null for initial build
type: "full" | "incremental";
rebuiltModules: string[];
removedModules: string[];
buildTime: number; // milliseconds
}HmrUpdate
interface HmrUpdate {
updatedModules: Record<string, string>; // module ID → new code
removedModules: string[];
requiresReload: boolean;
reloadReason?: string;
}When requiresReload is true, the entry file itself changed or no accept boundary was found, and a full reload is needed.