dogc之样式方案选型

587 阅读3分钟

目的

  • 为了提高开发者效率,提高组件库的可定制化,组件库需要提供换肤功能以及多种类组件中的样式定制功能,允许用户将应用切换不同主题风格的皮肤,也允许开发者对指定组件进行样式改造。
  • 为了减少代码的体积,组件库需要提供按需引入的功能,组件只用在被手动引入的时候,才会被打包进项目当中,无论是html、js,还是css,都需要做到按需引入。

样式选择

sass/lesscss in js
完全支持样式覆盖❗(需要使用className支持)
支持rem布局❗(大部分库支持)
可读性
上手成本
是否支持SSR天然支持需要额外支持
是否支持流式渲染天然支持需要额外支持
支持postcss❗(有自己的plugin生态)

样式按需引入

使用组件库时, 需要加载组件库的全部样式, 但是我们大部分时候不需要使用到组件库所有的组件, 更不需要载入所有组件的样式。所以组件库需要提供按需引入。

比如我们现在需要使用Button组件,我们会写如下代码:

import {Button} from "@bufang/dogc"

因为此时没用引入全部样式文件,按钮样式不会生效,需要我们手动引入Button样式:

import "@bufang/dogc/lib/button/style"

到这里的要解决如下两个问题。

要做到组件的样式单独引入,在打包的时候就需要把组件的样式单独打包,如何实现单独打包?
  • 安装npm install rollup-plugin-styles,可以与 preserveModules 做适配,即输出按照组件维度拆分的 css 文件。
  • 配置rollup.config.js
output = {
    dir: "cjs",
    format: "cjs",
    preserveModules: true,
    preserveModulesRoot: "components",
    exports: "named",
    assetFileNames: ({ name }) => {
      const { ext, dir, base } = path.parse(name);
      if (ext !== ".css") return "[name].[ext]";
      // 规范 style 的输出格式
      return path.join(dir, "style", base);
    },
};
plugins:[
    styles({
      mode: "extract", // 使得 css 是抽离的,而不是打包进 js 的
      less: { javascriptEnabled: true },
      extensions: [".less"],
      minimize: false,
      use: ["less"],
      url: {
        inline: true,
      },

      sourceMap: true, // 必须开启,否则 rollup-plugin-styles 会有 bug
      onExtract(data) {
        const { name } = data;
        const { base } = path.parse(name);
        if (base !== "index.css") return false;
        return true;
      },
    }),
]
每引入一个组件都需要手动引入样式,是不是比较繁琐,如何自动引入组件的样式?
  • npm install babel-plugin-import --save-dev
  • 配置babel
module.exports = {
  plugins: [
    [
      "import",
      {
        libraryName: "@bufang/dogc",
        libraryDirectory: "es", // default: lib
        camel2DashComponentName: true,
        style: name => {
          // 注意这里的name为组件所在的路径,按需加载样式配置提取对应组件名称的css即可
          return `${name}/style/index.less`;
        },
      },
    ],
  ]
};

主题配置

  • 方案一:css3 Variables 定义一个全局颜色变量,改变这个变量的值页面内所有引用这个变量的元素都会进行改变。
@import "./color/index.less";

body,
body[theme-mode="dark"] .dogc-always-light {
  --dogc-color-white: rgba(
    var(--dogc-white),
    1
  ); // 浅色模式下深色背景内容Inverse
  --dogc-color-black: rgba(
    var(--dogc-black),
    1
  ); // 深色模式下浅色背景内容Inverse

  --dogc-color-primary: rgba(
    var(--dogc-blue-5),
    1
  ); // 主要颜色。仅在需要非常强调的情况下使用。
}

如果要修改主题色时: document.body.style.setProperty('--dogc-color-primary', 'blue');即可,非常方便。

  • 方案二:less modifyVars modifyVars方法是是基于 less 在浏览器中的编译来实现。所以在引入less文件的时候需要通过link方式引入,然后基于less.js中的方法来进行修改变量。操作起来比较麻烦,如果有兴趣可以自己去研究一下。

所以,最终选择了css variables方案。