Qiankun+Vite样式隔离解决方案
问题
Qiankun
+Vite
作为子应用时,样式隔离无效即使配置了
experimentalStyleIsolation: true
也无效解决方案:使用 postcss-prefix-selector 插件为样式添加前缀
配置插件
在子应用
vite.config.ts
中配置插件(官方示例)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import prefixer from 'postcss-prefix-selector';
...
export default defineConfig({
...
css: {
postcss: {
plugins: [
prefixer({
prefix: '[data-qiankun-app]',
transform(prefix, selector, prefixedSelector, filePath, rule) {
if (selector.match(/^(html|body)/)) {
return selector.replace(/^([^\s]*)/, `$1 ${prefix}`);
}
if (filePath.match(/node_modules/)) {
return selector; // Do not prefix styles imported from node_modules
}
const annotation = rule.prev();
if (annotation?.type === 'comment' && annotation.text.trim() === 'no-prefix') {
return selector; // Do not prefix style rules that are preceded by: /* no-prefix */
}
return prefixedSelector;
},
}),
],
}
},
...
});在子应用
main.tsx
中添加data-qiankun-app
属性(下面是示例)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import { createRoot } from 'react-dom/client';
import {
QiankunProps,
qiankunWindow,
renderWithQiankun,
} from 'vite-plugin-qiankun/dist/helper';
import App from './App.tsx';
import './index.css';
const render = (container?: HTMLElement) => {
const app =
container || (document.getElementById('root') as HTMLDivElement);
/**
* 添加属性,用于样式隔离
* 注意:这里的属性名要和 postcss-prefix-selector 插件中的 prefix 保持一致
*/
app.setAttribute('data-qiankun-app', 'true');
// container && container.setAttribute('data-qiankun-app1', 'true');
createRoot(app).render(<App />);
};
/** Qiankun 生命周期钩子 */
const qiankun = () => {
renderWithQiankun({
bootstrap() {},
async mount(props: QiankunProps) {
render(props.container);
},
update: (props: QiankunProps) => {},
unmount: (props: QiankunProps) => {},
});
};
if (qiankunWindow.__POWERED_BY_QIANKUN__) qiankun();
else render();下面是一个示例,可以在控制台中看到样式被添加了前缀,实现了样式隔离
1
2
3
4
5
6
7
8import React from 'react';
import './App.css';
const App = () => {
return <div className="app">Hello, Qiankun!</div>;
};
export default App;1
2
3
4
5
6
7
8.app {
color: red;
}
// 在控制台中被转换成
[data-qiankun-app] .app {
color: red;
}实现跟 qiankun experimentalStyleIsolation 类似的效果
组件库样式隔离
上面样式对自己写的类名生效,但是对于引入的组件库样式隔离可能无效无效
antd ConfigProvider 可以给组件添加前缀
1
2
3
4
5
6import { ConfigProvider } from 'antd';
import App from './App';
<ConfigProvider prefixCls="app">
<App />
</ConfigProvider>;1
2
3.app-btn {
color: red;
}
具体实现参考 qiankun-multiple-subapp
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 小四先生的云!
评论