1

background

At present, the community pays more attention to the "isolation" of micro-front-end application styles. There have been many articles on the Internet that introduce the style isolation scheme of micro-front-end applications. However, If the style of the micro-application only has "isolation" but not "manipulability", then the style of the micro-application is fixed: like a function that does not accept external parameters, it will always only do predefined things and not accept Control and configuration of the caller.

Under this inflexible micro-application architecture, it is difficult for the host application to control the style and theme of the entire site, because micro-applications are inherently closed and stubborn. Application scenarios will be greatly reduced, such as the following requirements are difficult to achieve:

  • The theme brand color has been upgraded from orange to light blue
  • Switch light/dark theme online
  • The same micro application is used in multiple hosts. In some hosts, it appears orange; in other hosts, it appears blue.

The past implementation requires a huge cost: for example, for each micro-application, a css is constructed for each theme, and then according to the host's current theme status, js is used to switch the css of each micro-application. Moreover, any modification of the theme requires developers to modify, rebuild, and release multiple micro-applications, which is extremely cumbersome.
The fundamental reason is that the micro-applications have hard-coded the styles (and achieved style isolation), which cannot be changed through the configuration of the host, and there is a lack of information transfer between the main and sub-applications.

Therefore, the need for style control was born: from different projects (different teams, or applications developed at different times) are integrated together, style control is required, and style encapsulation and maneuverability are both .

Style control theory also applies to business components and blocks.

Introduction to Style Control Scheme

This article shares a solution to realize the style control of micro-applications through CSS Variable: the style of micro-applications is no longer fixed, and the host application can control it by "passing parameters". In this scheme, the micro-application style is like a function with optional parameters:

function renderStyle(cssVar1 = defaultVar1, cssVar2 = defaultVar2) {
  // 使用 cssVar1, cssVar2, cssVar3 来渲染样式
  // 其中 cssVar3 是从环境闭包捕获的,无需调用者显式传入
}

only encapsulates the internal style, but also provides a configurable API . More flexible to meet the needs of various scenarios.

According to the default source of style variables, style control modes can be divided into two types:

  • Isolation priority:

    • Micro apps have their own default theme. Use your own theme by default, which is not affected by the host environment. Out of the box, no configuration is required.
    • The host has control. When the host wants to perform style control, it can accurately, on-demand, and explicitly cover the theme variables of each micro-application to ensure that the entire application is harmonious and consistent.
  • Inheritance priority: Micro-application style variables inherit the value of the host environment by default. No explicit overriding by the host is required.

Here are a few simple examples to introduce the realization of this scheme.

Isolation priority mode

Micro apps use their own themes by default and are not affected by the host environment. Hosts may explicitly overridden wherein the variable pattern.

Default theme out of the box

This is the style of micro application mounting:

/* 微应用css */
.widget-k7na5-default-theme {
  --button-bg: orange;
}
.widget-k7na5-btn {
  background-color: var(--button-bg);
}
Among them, widget-k7na5 is the class name prefix of micro-applications, which realizes style isolation. You can use various methods on the Internet to achieve style isolation (such as css module, css-in-js), and they can all be combined with this solution.

Its DOM structure is as follows:

<!--微应用根元素-->
<div classname="widget-k7na5-default-theme">
  <button classname="widget-k7na5-btn">button</button>
</div>

Therefore, this micro-app will display the default orange theme. Out of the box, no configuration is required.

is to define a default style variable on the root element of the micro-application; then use the style variable to implement the style within the micro-application, instead of hard-coding the specific value in the style.

Even if the host accidentally uses a variable name with the same name (for example, the host css has html { --button-bg: red; } ), the micro application will not be affected by it. Because the micro-application root element resets this variable to the default value, this ensures good encapsulation and isolation.

The host explicitly overrides the style variables of the micro application

If the host wants to upgrade the theme of the entire site to blue, then the micro application should not continue to appear orange. Therefore, the host needs to have the ability to cover the default theme of the micro application .

How to do it?

First, the micro-application must provide an API that allows the host to configure the class name root element of the micro-application.

/* 宿主js */
// 宿主加载微应用的时候,定制微应用根元素的类名
function App() {
  return <LoadWidget id="widget-instance-list" className="theme-blue" />
}

So the micro application has the following DOM structure:

<!--微应用根元素-->
<div classname="widget-k7na5-default-theme theme-blue">
  <button classname="widget-k7na5-btn">button</button>
</div>

loading style of the 160b5b0c0682ae micro-app is the same as before, no need to change :

/* 微应用css */
.widget-k7na5-default-theme {
  --button-bg: orange;
}
.widget-k7na5-btn {
  background-color: var(--button-bg);
}
Therefore, there is always only one copy of the micro-application style, no need to use js for dynamic switching, and the implementation and maintenance are very simple.

host contains the following theme variable definitions:

/* 宿主css */
/* 选择器权重高于微应用自己的变量定义 */
.theme-blue.theme-blue {
  --button-bg: blue;
}

carry out! Now the button in the micro application will be displayed as a blue theme!
The key point here is that the host overrides the cssVar style variable definition on the root element of the micro application.

The host only needs to use this method to add .theme-blue to each micro-application, and the entire site can be unified into a blue theme. In the process of upgrading this theme, each micro-application does not need to make any changes or releases.

Maintain encapsulation through style API

Note that the host has never invaded the realization of the micro-application, maintaining the encapsulation the micro-application. The host uses only the following APIs:

  • Customize the root element class name through className.
  • The micro application supports the configured cssVar variable name. They are just like the named parameters of a function, and they are also an API.
If the micro-application has some internal cssVar variable names that do not want to be used externally, special naming rules can be used to avoid them.

As long as these two APIs can be maintained stable, the host and micro-application can iterate independently. Packaging and flexibility have both.

Advanced example: precise control capabilities

This solution is simple and flexible, and the host can precisely control each micro-application and pass in different style variables to different micro-applications.

The host js is as follows, and the theme class name is passed in to each micro application:

/* 宿主js */
// 宿主加载微应用的时候,可以定制微应用根元素的类名
function App() {
  return (
    <>
      <LoadWidget id="widget-instance-list" className="theme-blue" />
      <LoadWidget id="widget-instance-list" className="theme-green" />
    </>
  );
}

host style contains variable definitions for each theme class name:

/* 宿主css */
/* 选择器权重高于widget自己的变量定义 */
.theme-blue.theme-blue {
  --button-bg: blue;
}
.theme-green.theme-green {
  --button-bg: green;
}

In this case, the former will be displayed as a blue theme, while the latter will be displayed as a green theme. does not interfere with each other and is completely controlled by the host.

Inheritance priority mode

In the previous isolation priority mode, micro-applications display their own themes by default. The host can cover the theme of the micro application, but needs to explicitly customize the class name for each micro application, which has some trouble .

cssVar can also implement the inheritance priority scheme: the micro-application inherits the host’s style variables by default, and the host does not need to pass in additional configuration to the micro-application.

Some control clarity is lost (in the isolation priority mode, the micro-app theme is clearly controlled by the root element class name) in exchange for convenience.

Host js:

/* 宿主js */
function App() {
  return <LoadWidget id="widget-instance-list" disableDefaultTheme />
}

Among them, disableDefaultTheme makes the root element of the micro application not have the class name of the default theme. Therefore, the micro-application DOM structure is as follows:

<!--微应用根元素-->
<div classname="">
  <button classname="widget-k7na5-btn">button</button>
</div>

Host css:

/* 宿主css */
html {
  --button-bg: blue;
}

Note that the host directly defines theme variables in the global scope. There is no need to define variables for the root element of each micro application.

micro-application is the same as before, no need to change :

/* 微应用css */

/* 注意,现在根元素没有.default-theme类名,因此这条规则不生效 */
.widget-k7na5-default-theme {
  --button-bg: orange;
}
.widget-k7na5-btn {
  background-color: var(--button-bg);
}

In this way, the micro application will read --button-bg from the host environment by default, which is displayed in blue.

Of course, the host can still explicitly override the style variables of the micro application.

to sum up

This article discusses two style control modes between micro-applications and hosts:

  • Isolation first: The micro-app’s own style variables are used by default, and the host can explicitly override them
  • Inheritance first: inherit the style variables of the host environment by default

These two modes can be used in combination. For example, some style variables of micro-applications use [Isolation Priority Mode], and other style variables use [Inheritance Priority Mode].

Note that In all the previous examples, the css loaded by the micro application has not changed. We can realize the above-mentioned micro-application style control mode by only manipulating the root element class name. Therefore, micro-applications do not need to package a css for each mode. The implementation of js is also very simple (just manipulate the root element class name). The host application is easy to control and switch the style of the overall site.

The implementation of these two modes can be built into the micro front-end framework. Micro application developers only need to define the theme variables, variable default values, and variable control modes they want to use. The class name of the root element is managed by the micro application loader.


csRyan
1.1k 声望198 粉丝

So you're passionate? How passionate? What actions does your passion lead you to do? If the heart doesn't find a perfect rhyme with the head, then your passion means nothing.