如何高效地给你的css统一加前缀

2,942 阅读1分钟

场景

  1. 输出的产物需要被第三方业务系统集成,若不用命名空间隔绝,可能会存在选择器互相影响的情况
  2. 输出的产物是一个微前端的主应用,若不用命名空间隔绝,可能会存在主应用影响子应用样式的情况

解决方案

github.com/uWydnA/gulp…

思路如下:

  1. 减小开发成本,因此不可能在每个less/sass里手写最外层父选择器
  2. 因此在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;
  }
}