likes
comments
collection
share

🤔CSS 样式隔离在微前端中的应用:以 Ant Design 为例

作者站长头像
站长
· 阅读数 37

引言:在开发中,我们常常会遇到不同项目间样式冲突的问题。尤其是在微前端架构下,不同子应用共享相同的基础依赖库(如 Ant Design),以及使用相同的类名命名方式,会导致样式相互覆盖,影响用户界面的一致性与稳定性。

背景

在开发中,常见的样式冲突问题有:

  1. 基础依赖库的共享:如 antd.css 在多个应用中引入,可能导致样式冲突。
  2. 自定义类名重复:开发者虽然习惯不同,但是可能自定义的class类名相同,导致样式相互覆盖。

🤔CSS 样式隔离在微前端中的应用:以 Ant Design 为例

图中的样式,在接入微前端后,并没有满足我们的 UI 预期。通过查看,发现是 CSS 代码被覆盖了!

🤔CSS 样式隔离在微前端中的应用:以 Ant Design 为例

相同的 padding 属性,在自己的代码中没有发现,却在微前端的某个应用项目中发现!

为了保证每个子应用项目的样式独立,我们需要找到有效的样式隔离方法。下面介绍几种常见的解决方案。(强烈推荐每个项目同时配置方法 2 和方法 3)

解决方案

1. 提高样式的优先级

通过增加样式选择器的优先级,可以确保特定样式优先应用,而不会被其他样式覆盖。

/* 自定义样式 */
.dialogsmodel .ant-modal-content {
  padding: 8px 0 10px; /* 确保优先级高于主应用或者其他应用 */
}

注意:这种方法只能作为临时解决的措施,不可以根除病因,因为只能修改一个 class 类名样式,对其他的 class 类名,还需要每个都去设置样式优先级。

🤔CSS 样式隔离在微前端中的应用:以 Ant Design 为例

因此,强烈推荐使用方法 2 和方法 3,这两个方法配合使用,从根本上解决或者避免了基础依赖库的共享和自定义类名重复的问题。

2. 使用 Ant Design 的 ConfigProvider(强烈推荐使用)

Ant Design 提供的 ConfigProvider 组件可以用来配置全局样式,通过设置 prefixCls 来改变默认的样式前缀,避免样式冲突。

import { ConfigProvider } from 'antd';

function App() {
  return (
    <ConfigProvider prefixCls="my-ant">
      <Button>Button</Button>
    </ConfigProvider>
  );
}

在 Vue 中,同样可以使用 <a-config-provider> 组件来实现样式隔离:

<a-config-provider prefixCls="my-ant">
   <Button>Button</Button>
</a-config-provider>

🤔CSS 样式隔离在微前端中的应用:以 Ant Design 为例

修改 ant.css 源码:

<style scoped lang="less">
:deep(.my-ant-btn){
  font-size: 20px;
}
</style

3. 使用 Scoped Styles in Less 或 SCSS(强烈推荐使用)

通过使用 <style scoped lang="less"><style scoped lang="scss"> 标签,可以实现样式的局部作用域,从而避免样式冲突。

Vue 示例

<template>
  <button class="btn-custom">Button</button>
</template>

<style scoped lang="less">
.btn-custom {
  color: red; /* 自定义样式 */
}
</style>

SCSS 示例

<template>
  <button class="btn-custom">Button</button>
</template>

<style scoped lang="scss">
.btn-custom {
  color: red; /* 自定义样式 */
}
</style>

4. 使用 CSS Modules

CSS Modules 可以将 CSS 样式限定在特定的组件范围内,避免样式污染。使用 CSS Modules 时,样式会被编译成独特的类名,从而避免冲突。

// App.css
.ant-btn {
  color: red;
}

// App.jsx
import styles from './App.css';

function App() {
  return <Button className={styles.ant-btn}>Button</Button>;
}

其他方案

是否还有其他方案可以作为调研的方向呢,当然是有的,但是项目中不常用。

5. 动态加载样式

在子应用加载时动态注入其独立的样式表,以确保样式独立。

function loadStyle(url) {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = url;
  document.head.appendChild(link);
}

// 在子应用启动时调用
loadStyle('子应用的样式地址');

大家可以思考下,这个是借用了什么实现?

6. 使用 Shadow DOM

Shadow DOM 可以完全隔离不同应用的样式,实现样式的独立性。

function App() {
  const shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });
  shadowRoot.innerHTML = `
    <style>
      .ant-btn { color: red; }
    </style>
    <button class="ant-btn">Button</button>
  `;
  return shadowRoot;
}

总结

在微前端架构下,实现样式隔离对于保持各子应用的独立性和一致性至关重要。以上提供的解决方案在实际应用中已经得到验证,真实可用。

通过配置方法2方法3,可以实现合理的样式管理,使开发者在开发过程中无需担心样式覆盖问题。这不仅能有效避免主应用或其他子应用的样式干扰,还能防止自己项目中类名重复导致的冲突,从而大幅提升项目开发的便捷性、稳定性和可维护性。


如果你有任何问题或见解,欢迎在评论区分享!

转载自:https://juejin.cn/post/7394336779792269322
评论
请登录