Frontend Development 15 min read

Analysis of Qiankun Micro‑frontend Framework Sandbox Implementations

This article examines the sandbox mechanisms employed by the micro‑frontend framework Qiankun, detailing three implementations—SnapshotSandbox, LegacySandbox, and ProxySandbox—explaining their principles, code structures, advantages, and drawbacks, and illustrating how they isolate JavaScript global state across micro‑applications.

政采云技术
政采云技术
政采云技术
Analysis of Qiankun Micro‑frontend Framework Sandbox Implementations

Introduction

This article discusses the sandbox implementation strategies of the micro‑frontend framework qiankun , aiming to deepen readers' understanding of JavaScript sandbox isolation.

What is a JS sandbox

In computer security, a sandbox isolates the execution environment of a program to prevent untrusted code from affecting the host system. The same concept applies to the front‑end: a JS sandbox prevents a micro‑application from polluting or modifying the global window object.

When multiple micro‑applications define the same global variable (e.g., city ), they can interfere with each other. Traditional solutions rely on communication or naming conventions, which become fragile as the number of applications grows. A JS sandbox records the global variables created or modified by each micro‑application and restores the original state when the application is unloaded, ensuring isolation.

Qiankun sandbox implementation schemes and their pros/cons

Qiankun provides three sandbox schemes, each reflecting the evolution of micro‑frontend technology.

SnapshotSandbox (snapshot scheme)

During the active (load) phase, Qiankun copies the entire window object to a snapshot. During inactive (unload), it compares the current window with the snapshot, records changes, and restores the original state.

active() {
    // Record current snapshot
    this.windowSnapshot = {} as Window;
    iter(window, (prop) => {
        this.windowSnapshot[prop] = window[prop];
    });

    // Restore previous changes
    Object.keys(this.modifyPropsMap).forEach((p: any) => {
        window[p] = this.modifyPropsMap[p];
    });

    this.sandboxRunning = true;
}

In the inactive phase, it records modifications and restores the original window state.

inactive() {
    this.modifyPropsMap = {};

    iter(window, (prop) => {
        if (window[prop] !== this.windowSnapshot[prop]) {
            // Record change, restore environment
            this.modifyPropsMap[prop] = window[prop];
            window[prop] = this.windowSnapshot[prop];
        }
    });
    this.sandboxRunning = false;
}

Summary: Simple and compatible, but traverses the entire window on each activation/deactivation, leading to poor performance and supporting only a single sub‑application.

LegacySandbox (proxy snapshot scheme)

Creates a virtual fakeWindow and proxies it. Changes to fakeWindow are recorded in three maps:

addedPropsMapInSandbox : newly added globals, removed on unload.

modifiedPropsOriginalValueMapInSandbox : original values of updated globals, restored on unload.

currentUpdatedPropsValueMap : all changes, used for later restoration.

export default class LegacySandbox implements SandBox {
    private addedPropsMapInSandbox = new Map
();
    private modifiedPropsOriginalValueMapInSandbox = new Map
();
    private currentUpdatedPropsValueMap = new Map
();
    // ... constructor and proxy logic omitted for brevity ...
}

The active method restores previously modified globals, and the inactive method restores original values and deletes newly added ones.

active() {
    if (!this.sandboxRunning) {
        this.currentUpdatedPropsValueMap.forEach((v, p) => this.setWindowProp(p, v));
    }
    this.sandboxRunning = true;
}

inactive() {
    this.modifiedPropsOriginalValueMapInSandbox.forEach((v, p) => this.setWindowProp(p, v));
    this.addedPropsMapInSandbox.forEach((_, p) => this.setWindowProp(p, undefined, true));
    this.sandboxRunning = false;
}

Summary: Uses a proxy to avoid full window traversal, improving performance, but compatibility is lower than SnapshotSandbox and still supports only one sub‑application.

ProxySandbox (proxy snapshot scheme)

Similar to LegacySandbox, it creates a fakeWindow and proxies it. When a global variable is set, the proxy updates fakeWindow and, if the variable is whitelisted, also updates the real window . Reads first check fakeWindow , then fall back to the real window .

constructor(name: string, globalContext = window) {
    this.name = name;
    this.globalContext = globalContext;
    this.type = SandBoxType.Proxy;
    const { updatedValueSet } = this;
    const { fakeWindow, propertiesWithGetter } = createFakeWindow(globalContext);
    const proxy = new Proxy(fakeWindow, {
        set: (_, p, value) => {
            if (this.sandboxRunning) {
                // Record change, possibly update real window if whitelisted
                // ... omitted for brevity ...
                updatedValueSet.add(p);
                this.latestSetProp = p;
                return true;
            }
            return true;
        },
        get: (_, p) => {
            this.registerRunningApp(name, proxy);
            const value = propertiesWithGetter.has(p)
                ? (globalContext as any)[p]
                : p in fakeWindow
                ? (fakeWindow as any)[p]
                : (globalContext as any)[p];
            const boundTarget = useNativeWindowForBindingsProps.get(p) ? nativeGlobal : globalContext;
            return getTargetValue(boundTarget, value);
        },
        // getOwnPropertyDescriptor omitted for brevity
    });
    this.proxy = proxy;
    activeSandboxCount++;
}

The active method simply marks the sandbox as running, while inactive marks it as stopped.

active() {
    if (!this.sandboxRunning) activeSandboxCount++;
    this.sandboxRunning = true;
}

inactive() {
    this.sandboxRunning = false;
}

Summary: No need to restore globals on load/unload, giving the best performance and supporting multiple sub‑applications, though its compatibility is still lower than the first scheme.

How Qiankun Calls the Sandbox

To set a global variable like window.city = "Hangzhou" inside a micro‑application, Qiankun uses the import-html-entry package to bind the sub‑application's window to the sandbox's proxy. The code is executed with fn.bind(window.proxy) , so window.city actually becomes window.proxy.city , ensuring isolation.

function fn(window, self, globalThis) {
    // Your JavaScript code
    window.city = "Hangzhou";
}
const bindedFn = fn.bind(window.proxy);
bindedFn(window.proxy, window.proxy, window.proxy);

Reference

Qiankun principle detailed analysis – JS sandbox isolation (https://www.zhangshengrong.com/p/Z9a2Q3jk1V/)

Call to Action

If you found this article helpful, please click “In view” to let more people see it, and follow the public account “Zhengcaiyun Front‑end” for more curated articles.

Recruitment

The Zhengcaiyun front‑end team (ZooTeam) is a young, passionate group within the R&D department, based in Hangzhou. With over 80 front‑end engineers, the team works on material systems, engineering platforms, performance, cloud applications, data analysis, and visualization, constantly exploring new front‑end boundaries. If you are interested in joining a dynamic team that values both technical depth and product impact, send your resume to [email protected] .

Proxymicro‑frontendqiankunJS Sandboxisolation
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.