前提:singal-sap + systemjs 的微前端体系;子应用挂载在普通dom下,子应用引用第三方库如 antd,自身使用less
关于思路:借鉴CSS Modules,在子应用各样式最外层加一层选择器做隔离; 问题:1,子应用引用的第三方库如antd 按需加载没开启CSS Modules,工程内部使用less部分开启css modules,部分未开启,会导致最外层的选择器被编译后加hash值,导致未开启css modules部分样式不生效,2第三方库等基于绝对定位的组件如modal组件,该组件并未挂载在子应用的dom树下,会使该类组件样式失效。 3,less中 :global {} 下的选择器不被编译hash,导致这部分会失效
解决方案:
自定义postcss plugin
const postcss = require('postcss')
const exceptionCss = (exceptionCssArr, rule)=>{
// 探测是否含有不需要处理的选择器 antd modal类的样式除外,此类样式不加前缀,防止失效,需要特殊处理
return new RegExp(exceptionCssArr.join("|")).test(rule.selector)
}
module.exports = postcss.plugin("self-plugin", (opts)=>{
// IdSelector, classSelector 两个选择器前缀应对css modules 编译hash值和:global 不编译hash值
const {IdSelector, classSelector, exceptionCssArr} = opts
return (root)=>{
root.walkRules(rule=>{
const hasExc = exceptionCss(exceptionCssArr,rule)
if(!hasExc){
const tempSe = rule.selector
// 选择器应对css modules 编译hash值
rule.selector = classSelector + " " + rule.selector
// 选择器应对css modules :global 不编译hash值
rule.selector = tempSe.replace(":global ", ":global "+ IdSelector+ " ")
}
})
}
})
根html
function App() {
return (
<div id="noCssModules">
<div className="cssModules">
<div className="App">
<UglyTree datas={treeDatas}/>
</div>
</div>
</div>
);
}
postcss.config.js
const plugin = require('./cssModulePlugin')
module.exports = {
plugins: [
new plugin({
IdSelector:"noCssModules",
classSelector:"cssModules",
exceptionCssArr:['ant-modal']
})
]
}
后记:代码仅为样例,实际工程需要考虑边界特殊情况,工作原因,投产代码无法展示。类似antd提供prefix功能做样式隔离效果更佳。