The container lifecycle management functionality provides comprehensive APIs for creating, loading, and managing Fluid containers throughout their operational lifecycle.
The main Loader class provides the primary interface for container operations.
class Loader implements IHostLoader {
constructor(loaderProps: ILoaderProps);
createDetachedContainer(
codeDetails: IFluidCodeDetails,
createDetachedProps?: {
canReconnect?: boolean;
clientDetailsOverride?: IClientDetails;
}
): Promise<IContainer>;
rehydrateDetachedContainerFromSnapshot(
snapshot: string,
createDetachedProps?: {
canReconnect?: boolean;
clientDetailsOverride?: IClientDetails;
}
): Promise<IContainer>;
resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer>;
readonly services: ILoaderServices;
}import { Loader } from "@fluidframework/container-loader";
import type { ILoaderProps, IFluidCodeDetails } from "@fluidframework/container-loader";
// Create loader with required services
const loaderProps: ILoaderProps = {
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver,
configProvider: myConfigProvider,
logger: myLogger
};
const loader = new Loader(loaderProps);
// Create a new detached container
const codeDetails: IFluidCodeDetails = {
package: "my-fluid-package",
config: {}
};
const detachedContainer = await loader.createDetachedContainer(codeDetails, {
canReconnect: true,
clientDetailsOverride: { capabilities: { interactive: true } }
});
// Load an existing container
const existingContainer = await loader.resolve({
url: "https://myfluidservice.com/tenants/my-tenant/documents/my-doc"
});These utility functions provide simplified APIs for common container operations.
function createDetachedContainer(
createDetachedContainerProps: ICreateDetachedContainerProps
): Promise<IContainer>;
function loadExistingContainer(
loadExistingContainerProps: ILoadExistingContainerProps
): Promise<IContainer>;
function rehydrateDetachedContainer(
rehydrateDetachedContainerProps: IRehydrateDetachedContainerProps
): Promise<IContainer>;
function loadContainerPaused(
loaderProps: ILoaderProps,
request: IRequest,
loadToSequenceNumber?: number,
signal?: AbortSignal,
): Promise<IContainer>;import {
createDetachedContainer,
loadExistingContainer,
rehydrateDetachedContainer
} from "@fluidframework/container-loader";
import type {
ICreateDetachedContainerProps,
ILoadExistingContainerProps,
IRehydrateDetachedContainerProps
} from "@fluidframework/container-loader";
// Create detached container using utility function
const createProps: ICreateDetachedContainerProps = {
codeDetails: { package: "my-package", config: {} },
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver,
allowReconnect: true
};
const newContainer = await createDetachedContainer(createProps);
// Load existing container using utility function
const loadProps: ILoadExistingContainerProps = {
request: { url: "https://myfluidservice.com/documents/my-doc" },
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver,
pendingLocalState: serializedState
};
const loadedContainer = await loadExistingContainer(loadProps);
// Rehydrate container from serialized state
const rehydrateProps: IRehydrateDetachedContainerProps = {
serializedState: snapshotString,
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver
};
const rehydratedContainer = await rehydrateDetachedContainer(rehydrateProps);function waitContainerToCatchUp(container: IContainer): Promise<boolean>;This function waits for a container to finish catching up with the latest state from the service.
import { waitContainerToCatchUp } from "@fluidframework/container-loader";
// Wait for container to catch up after reconnection
const success = await waitContainerToCatchUp(container);
if (success) {
console.log("Container is now up to date");
} else {
console.log("Container failed to catch up");
}interface ICreateAndLoadContainerProps {
readonly allowReconnect?: boolean | undefined;
readonly clientDetailsOverride?: IClientDetails | undefined;
readonly codeLoader: ICodeDetailsLoader;
readonly configProvider?: IConfigProviderBase | undefined;
readonly documentServiceFactory: IDocumentServiceFactory;
readonly logger?: ITelemetryBaseLogger | undefined;
readonly options?: IContainerPolicies | undefined;
readonly protocolHandlerBuilder?: ProtocolHandlerBuilder | undefined;
readonly scope?: FluidObject | undefined;
readonly urlResolver: IUrlResolver;
}interface ICreateDetachedContainerProps extends ICreateAndLoadContainerProps {
readonly codeDetails: IFluidCodeDetails;
}
interface ILoadExistingContainerProps extends ICreateAndLoadContainerProps {
readonly pendingLocalState?: string | undefined;
readonly request: IRequest;
}
interface IRehydrateDetachedContainerProps extends ICreateAndLoadContainerProps {
readonly serializedState: string;
}Note: These interfaces are deprecated and maintained for backward compatibility only.
interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {
load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
}
interface IFluidModuleWithDetails {
details: IFluidCodeDetails;
module: IFluidModule;
}// Create detached container
const detachedContainer = await createDetachedContainer({
codeDetails: myCodeDetails,
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver
});
// Work with detached container
const myDataObject = await detachedContainer.getEntryPoint();
await myDataObject.initialize();
// Attach to service when ready
await detachedContainer.attach(attachRequest);// Load container with reconnection support
const container = await loadExistingContainer({
request: myRequest,
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver,
allowReconnect: true
});
// Monitor connection state
container.on("connected", () => {
console.log("Container connected");
});
container.on("disconnected", () => {
console.log("Container disconnected, will attempt reconnection");
});
// Wait for container to catch up after reconnection
container.on("connected", async () => {
const success = await waitContainerToCatchUp(container);
if (success) {
console.log("Container fully synchronized");
}
});// Serialize container state for offline storage
const snapshot = detachedContainer.serialize();
await localStorage.setItem("containerSnapshot", snapshot);
// Later, rehydrate from stored state
const storedSnapshot = await localStorage.getItem("containerSnapshot");
if (storedSnapshot) {
const rehydratedContainer = await rehydrateDetachedContainer({
serializedState: storedSnapshot,
codeLoader: myCodeLoader,
documentServiceFactory: myDocumentServiceFactory,
urlResolver: myUrlResolver
});
}