场景
- 输出的产物需要被第三方业务系统集成,若不用命名空间隔绝,可能会存在选择器互相影响的情况
- 输出的产物是一个微前端的主应用,若不用命名空间隔绝,可能会存在主应用影响子应用样式的情况
解决方案
思路如下:
- 减小开发成本,因此不可能在每个
less/sass
里手写最外层父选择器 - 因此在
webpack/gulp/rollup
等构建工具处理代码时候进行「统一前缀」
的增加,似乎成了必然
结合到项目情况,我这边需要给一个组件库统一加前缀,组件库使用了gulp,因此写了一个gulp的插件实现该功能
const through = require("through2");
const PLUGIN_NAME = "gulp-prefixer";
function gulpPrefixer({ prefix, prefixInCss }) {
if (!prefix || !prefixInCss) {
throw new Error(PLUGIN_NAME, "Missing prefix text!");
}
prefix = new Buffer(`${prefixInCss}${prefix} {`);
const prefixTextEnd = new Buffer("}");
const stream = through.obj(function (file, enc, cb) {
if (file.isStream()) {
this.emit("error", new Error(PLUGIN_NAME, "Streams are not supported!"));
return cb();
}
const fileContents = file.contents.toString();
const isHasImport = fileContents.includes("@import");
if (file.isBuffer() && !isHasImport) {
file.contents = Buffer.concat([prefix, file.contents]);
file.contents = Buffer.concat([file.contents, prefixTextEnd]);
}
this.push(file);
cb();
});
return stream;
}
module.exports = gulpPrefixer;
使用方法
gulp接入
const { src, dest, parallel } = require("gulp");
const gulpPrefixer = require("./plugins/index.js");
function copyLess(toDir) {
return function copyAssets() {
return src("src/**/*.less")
.pipe(
gulpPrefixer({
prefix: "privateKey", //前缀字符串
prefixInCss: "#", // 选择器前缀,#或者.
})
)
.pipe(dest(toDir));
};
}
exports.default = parallel(copyLess("lib"), copyLess("es"));
html适配
// prefixInCss为#,prefix为privateKey
<html lang="en" id="privateKey">
// prefixInCss为.,prefix为privateKey
<html lang="en" class="privateKey">
产物与源码的对比
源码
//index.less
@import "./custom.less";
//custom.less
.box {
color: red;
}
.content {
font-size: 12px;
}
产物
//index.less
@import "./custom.less";
//custom.less
#privateKey {
.box {
color: red;
}
.content {
font-size: 12px;
}
}