在微前端架构中,子应用的样式隔离和共享是一个重要问题。我们需要确保子应用的样式不会互相干扰,同时也需要支持共享一些全局样式。
样式隔离
样式隔离可以通过多种方式实现,包括CSS Modules、Shadow DOM、以及CSS-in-JS等方法。
- CSS Modules
CSS Modules通过生成唯一的类名来确保样式的局部性,从而避免样式冲突。
- 在Vite中配置CSS Modules:
-
创建一个React组件并使用CSS Modules:
// src/components/MyComponent.module.css .myComponent { color: blue; }
// src/components/MyComponent.tsx import React from 'react'; import styles from './MyComponent.module.css';
const MyComponent = () => (
This is a CSS Module component.);export default MyComponent;
- 在Vite项目中启用CSS Modules:
-
Vite默认支持CSS Modules,因此不需要额外配置。
-
Shadow DOM
Shadow DOM是一种浏览器原生技术,它允许我们将样式封装在组件内部,避免与外部样式冲突。
- 使用Shadow DOM:
-
创建一个自定义元素并将其挂载到Shadow DOM:
// src/components/ShadowComponent.tsx import React, { useEffect, useRef } from 'react';
const ShadowComponent = () => { const shadowRootRef = useRef<ShadowRoot | null>(null);
useEffect(() => { if (shadowRootRef.current) { const shadowRoot = shadowRootRef.current; const style = document.createElement('style'); style.textContent =
.shadowComponent { color: red; }; shadowRoot.appendChild(style);const div = document.createElement('div'); div.className = 'shadowComponent'; div.textContent = 'This is inside Shadow DOM'; shadowRoot.appendChild(div); }}, []);
return <div ref={el => { if (el && !shadowRootRef.current) { shadowRootRef.current = el.attachShadow({ mode: 'open' }); } }} />; };
export default ShadowComponent;
-
CSS-in-JS
CSS-in-JS允许我们将样式定义在JavaScript文件中,并动态地将其应用到组件中。
- 使用Styled Components:
-
安装Styled Components:
npm install styled-components @types/styled-components
-
创建一个使用Styled Components的React组件:
// src/components/StyledComponent.tsx import React from 'react'; import styled from 'styled-components';
const StyledDiv = styled.div
color: green;;const StyledComponent = () => ( This is a styled component. );
export default StyledComponent;
样式共享
在微前端架构中,有时需要共享一些全局样式,例如重置样式或公共UI组件的样式。我们可以通过多种方式实现样式共享。
- 全局样式
将全局样式定义在主应用中,并确保所有子应用都能引用这些样式。
-
定义全局样式:
/* src/styles/global.css */ body { margin: 0; font-family: Arial, sans-serif; }
-
在主应用中引入全局样式:
// src/main.tsx import './styles/global.css';
-
共享样式库
创建一个独立的样式库项目,并将其作为依赖引入到主应用和子应用中。
-
创建样式库:
-
创建一个新的项目并定义共享样式:
/* styles-library/src/styles.css */ .shared-button { background-color: blue; color: white; padding: 10px; border: none; border-radius: 5px; }
-
- 在主应用和子应用中引入样式库:
-
将样式库发布到npm,并在主应用和子应用中安装:
npm install styles-library
// src/main.tsx import 'styles-library/styles.css';
-
CSS Variables
使用CSS Variables(CSS自定义属性)来定义和共享样式。
-
定义CSS Variables:
/* src/styles/variables.css */ :root { --primary-color: #4CAF50; --secondary-color: #FFC107; }
-
在组件中使用CSS Variables:
// src/components/VariableComponent.tsx import React from 'react'; import './variables.css';
const VariableComponent = () => (
This is using CSS variables.);export default VariableComponent;
示例代码
以下是一个完整的示例,包括主应用和子应用的样式隔离与共享配置。
主应用
// src/App.tsx
import React, { useEffect } from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import { registerMicroApps, start } from 'qiankun';
import Home from './pages/Home';
import About from './pages/About';
import './styles/global.css';
const App = () => {
useEffect(() => {
registerMicroApps([
{
name: 'sub-app-1',
entry: '//localhost:7100', // 子应用入口
container: '#subapp-container',
activeRule: '/subapp1',
},
]);
start();
}, []);
return (
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/subapp1">Sub App 1</Link></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/subapp1/*" element={<div id="subapp-container"></div>} />
</Routes>
</div>
);
};
export default App;
子应用
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './styles/global.css'; // 引入全局样式
function render(props: any) {
const { container } = props;
const root = ReactDOM.createRoot(container ? container.querySelector('#root') : document.querySelector('#root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('React app bootstraped');
}
export async function mount(props: any) {
render(props);
}
export async function unmount(props: any) {
const { container } = props;
const root = container ? container.querySelector('#root') : document.querySelector('#root');
ReactDOM.unmountComponentAtNode(root);
}
通过本节内容,我们了解了如何在微前端架构中实现样式隔离与共享。我们探讨了CSS Modules、Shadow DOM、CSS-in-JS等样式隔离方法,以及全局样式、共享样式库和CSS Variables等样式共享策略。接下来,我们将继续探索微前端架构中的性能优化技术。