Why is the current micro-frontend sandbox not a real sandbox

Foreword

In the previous article, why single-spa is the correct development model for micro-frontends, we talked about the birth background of the qiankun sandbox. Here we review:

  • The project technology stack is disorganized and the code quality is low
  • There is a lack of specifications during project development, which will cause mutual influence once the projects are integrated (css conflicts, js conflicts, etc.)
  • The labor cost of project transformation is high, and new functions need continuous iteration

Faced with these problems, the best solution currently adopted is to develop a set of micro-front-end frameworks that can greatly reduce access costs while avoiding mutual influence between projects, which is why domestic micro-front-end frameworks cost a lot of money The reason for the resources to implement the sandbox.

However, various micro-frontend solutions do not have a standard concept of sandbox, nor have they explained in detail what problems the sandbox solves, and a large number of developers follow suit. Therefore, this article will analyze the current problems and future development trends in the micro-frontend sandbox from the perspective of ShadowRealm.

What is a sandbox?

Domestic micro-frontends repeatedly mention the concept of sandbox, but its definition is not accurate and cannot represent the general sandbox concept in the computer field. The sandbox concept in the computer field is as follows:

Sandbox (Sandbox) is an isolated running mechanism of a program, and its purpose is to limit the permissions of untrusted processes. Sandboxing is often used to execute untested or untrusted client programs. In order to prevent untrusted programs from disrupting the operation of other programs, the sandbox technology provides virtualized disk, memory and network resources for untrusted client programs. Because the resources in the sandbox are virtualized, the malicious behavior of the untrusted program in the sandbox is often limited in the sandbox.

It can be seen that the sandbox in the computer field is a technology that focuses on the field of computer security.

What exactly is the domestic micro-frontend sandbox?

First of all, the sandbox mentioned in the domestic micro front-end solution is not rigorous compared with the above-mentioned standard sandbox concept. ShadowRealm is still in the TC39 standard proposal (stage 3), and has not yet been implemented.

At present, the sandboxes of various domestic micro-frontends are all self-created, non-standard official sandboxes implemented by simulation means still have many limitations, and the implementation methods are mostly:

  • iframe + webcomponent realize sandbox – wujie.
  • Window proxy + shadowdom/scoped css realize sandbox – qiankun.

The sandbox in the micro frontend is mainly divided into two parts, one is the js sandbox, and the other is the css sandbox.

js sandbox

During project integration, the following scenarios are usually encountered:

  • Global variables are defined in the project. When multiple projects coexist, if they have the same name, they will affect each other.
  • The UMD module mounts the dependencies to the global (such as window), and affects each other when multiple projects coexist.

It can be seen that the main source of global pollution mainly comes from definition and dependence, so in summary, the purpose of the js sandbox is to shield the mutual pollution when multiple projects are integrated, Dependency conflict. Compared with foreign micro-frontends, which rely more on governance plus runtime modularity (systemjs) or MF to solve such problems, domestic micro-frontends Mostly rely on the js sandbox, the essence of which is to give up governance and turn to isolation.

bad case of simulated JS sandbox

Is the current “simulated js sandbox” a “flawless” JS sandbox? The answer is no. The ShadowRealm mentioned above is the “official” JS sandbox in the future, which is more rigorous.

Non-iframe sandbox FAQ

  • Prototype Chain Modification
Array.prototype.cf = 'xxx';
  • DOM level 0 events
// A system
window.onclick = () => {<!-- -->
// xxx
}

// B system
window.onclick = () => {<!-- -->
// xxx
}

Here are just a few, and there will be many such examples in real-world scenarios.

iframe sandbox FAQ

Identity discontinuity is a prominent problem in iframe-based sandboxes. All non-primitive types have this problem in cross-iframe transmission.

onst globalOne = window;
let iframe = document. createElement('iframe');
document.body.appendChild(iframe);
const iframeArray = iframe. contentWindow. Array;

console.assert(iframeArray !== Array);

const list = iframeArray('a', 'b', 'c');

list instanceof Array; // false
[] instanceof iframeArray; // false
Array.isArray(list); // true

Identity discontinuity (identity loss problem) is the official name of this problem in TC39. The above example is also derived from TC39. The biggest impact of the identity loss problem is to hinder communication between applications. Non-simple types may have misjudgment or inability to judge when communicating.

Correct handling – avoid contamination

From the above analysis, it is not difficult to see that the root of the global pollution problem of the modern front-end is bad development habits. The fundamental solution to such problems is not to impose additional technical means, but to standardize the development model to avoid problems. During project development

  • Use UMDs correctly
  • Reduce or avoid defining global variables
  • Avoid writing js code that is not in the scope of the function
  • Avoid polluting the prototype chain
  • Reduced use of DOM0 level events

When the package is developed

  • reduce side effects
  • Module supports multiple instances
  • avoid polluting the global

Summary

The existing js sandbox scheme implemented by simulation has more or less defects, and it is not the sandbox concept in the traditional computer field. The js sandbox is still meaningful and valuable in system integration, but it cannot cure all the pollution problems encountered in integration development, it can only “mitigate”.

  • There is still only one document in the overall system, and there will still be problems if multiple React versions less than 17 coexist in an isolated sandbox.

  • For routing libraries such as vue-router and react-router, there will be conflicts between their own versions and between different routing libraries.

    Note: Although the iframe isolation is in a different context, I personally think that there will still be some conflicts, which will need to be practiced later.

css sandbox

During project integration, the style problem is also a headache. After our project integration, I suddenly found that my style did not work, or why my style was covered by another style. There may be reasons a lot of:

  • Irregular naming leads to duplication
  • For simplicity, use global styles directly in the project
  • Introduction of third-party Ui libraries under multiple instances (antd, element-ui)

It can be seen that the main sources of style pollution mainly come from definition and dependency. Therefore, in summary, the purpose of css sandbox is to shield the mutual pollution of styles when multiple projects are merged. Like the js sandbox, domestic micro frontends mostly rely on the css sandbox, whose essence is to abandon governance and instead isolate.

The following are several ways of implementing css sandbox in current micro frontends:

shadowdom (wujie, qiankun, Garfish)

Shadow dom can be summed up simply as follows: Turn a node in the Dom document tree into an isolated node, and the style and behavior of the child nodes in the isolated node will be isolated from the outside world (the style in the isolated node will not be affected by the outside, nor will it affect External nodes, events in the isolated node will only bubble up to the isolated node)

Benefits

  • Browser Basic Style Isolation
  • Support master-sub-application style isolation
  • Support for multiple instances

Disadvantages

  • Libraries that cause some dependency events to bubble up do not work properly.

    React16’s synthetic event relies on event bubbling, and collects all events into document, but it will fail in shadowdom, so the event system processing mechanism has been changed in React17.

    Byte’s micro-frontend framework Garfish manually propagates events upwards to avoid the failure of React’s library that relies on event delegation

  • Unable to deal with the failure of component styles such as dialog and modal mounted on the body of the parent application.

    In order to avoid being affected by the style of the parent element, components such as modal, dialog, and message will be mounted under the body of the parent container, and then break away from the original css sandbox, eventually causing the style to fail.

    Tencent micro front-end framework wujie mounts modal, dialog, message and other components into the sandbox through the agent of document, thus solving the style problem.

  • For other issues, please refer to this issue.

scoped css (qiankun)

Scoped css is a component-level style isolation solution implemented by vue loader. To use it, you only need to add a scoped attribute to the style of the component:

<style scoped>
  .example {<!-- -->
    color: red;
  }
</style>

<template>
  <div class="example">hi</div>
</template>

Conversion result:

<style>
  .example[data-v-f3f3eg9] {<!-- -->
    color: red;
  }
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

This limits the scope of component styles, and qiankun has introduced an experimental style isolation feature experimentalStyleIsolation based on the idea of scoped css. When enabled, qiankun will rewrite the added content of the sub-application. , add a special selector rule to all style rules to limit their scope of influence:

// Suppose the application name is react16
.app-main {<!-- -->
  font-size: 14px;
}

Conversion result:

div[data-qiankun-react16].app-main {<!-- -->
  font-size: 14px;
}

We have seen that qiankun has added a data-qiankun=”application name” selector to all styles to isolate them. qiankun official support will focus on investing in this solution and no longer recommend shadowdom.

Benefits

  • Users do not need to manually increase the configuration.

Disadvantages

  • @keyframes, @font-face, @import, @page are not supported.
  • Nodes of sub-applications are affected by the main application.
  • Unable to deal with the failure of component styles such as dialog and modal mounted on the body of the parent application.

Correct handling – avoid contamination

From the above analysis, it is not difficult to see that the root of the style pollution problem of the modern front-end is the same as the global pollution of js, which is due to bad development habits. In the last article, I mentioned how single-spa treats the problem of style pollution-first treatment and then isolation. Business Development

  • Prioritize the use of css module, stylesd-component, Emotion and other libraries to avoid style pollution.

Third-party libraries

  • Prefixing with PostCSS Prefix (antd)

Is the simulated sandbox useless?

No, it is definitely useful, such as meeting a few scenes:

  • The system is old and has variable pollution, which cannot be improved in the short term, but needs to be integrated
  • Assuming that a customer of Party A has a poor system technology, is old, and has a lot of global pollution, then we need a function to embed into the system in the form of SDK. At this time, because we cannot ask customers to modify the system. Therefore, it is very helpful to use the js sandbox for isolation to ensure that the SDK has an independent and pure operating environment

Summary

With the development of the Internet, front-end systems have become more and more complex, and the problem of micro-front-ends has become increasingly prominent. The “official” (w3c, tc39, browser vendors) did not clearly define and solve the “micro-frontend” problem, but they actually took action and proposed some related solutions

  • web Component – stack-agnostic component
  • shadow DOM – style isolation
  • browser es module – depends on runtime control
  • shadowRealm – js sandbox

What we can do at this stage is to control the project well, prevent pollution, try to unify the technology stack as much as possible, and negotiate with the team for dependent versions.