中后台 CSS Modules 最佳实践

简介: 中后台 CSS Modules 最佳实践


图片.png

图片.png

工作中发现前端 CSS 的使用五花八门,有用 Sass,Less 这种预处理语言,还有 CSS in JS 这种奇葩玩法,还有 TailWindCSS 这种原子化的 CSS 方案,还有 CSS Modules 这种专注解决局部作用域和模块依赖问题的单纯技术。这么多种类,我们该怎么选呢,下面我介绍一种在现在微前端趋势下,在中后台项目中最好用的,开发体验最佳组合方式。

image.gif

图片.png

为什么要选择 CSS Modules



我们的这个最佳实践是以 CSS Modules 为基础的,为什么要选择他呢?在真实的工作中,我们遇到最痛的问题,就是样式的隔离,尤其是在微前端框架下,子应用之间,子应用和主应用之间,甚至同一个项目的不同页面之间都会有样式的覆盖,即使各种微前端框架都试图去解决样式隔离问题,不论是通过工程化加命名空间,还是 shadow DOM 的方式,都无法一劳永逸的解决,都有其弊端,相比于 Less ,Sass 这个技术,都要在每个页面或者组件上人为的想一个命名空间,这个过程没有技术上的约束,单靠人之间的口头规范是没有用的,但 CSS Modules 无疑是一种彻底解决样式冲突问题的方法。

CSS Modules 的文档相当简单,10 分钟内就能学会,而且基本主流的工程化工具和脚手架都是支持的,比如 vite 默认支持,CRA 也是天然支持,不需要任何额外的配置。

CSS Modules 开发体验极佳,写 CSS 从未如此丝滑,后面会详细介绍。



CSS Modules + Less



CSS Modules 由于他非常的单纯,因此 module.css 文件,依然是遵循 CSS 文件的规范的,因此不能写嵌套。为了解决这个问题,我们引入 Less,也就是使用 module.less 的文件格式,这样我们就可以借助 Less 的能力,写嵌套的代码了。

为什么不用 Sass 呢?其实 Sass 和 Less 本质上没有太多区别,也没有什么好坏之分,我选择 Less 的原因是,我的项目中大量使用 antd 的组件库,而 antd 使用的是 Less 的方案,而且如果要定制 antd 的主题,就必须用 Less。

有了 Less 以后就可以有效的弥补,CSS Modules 的很多不足,尤其是嵌套,比如下面的代码。

.container {
  .header {
    color: red;
  }
}


变量的定义和使用


Less、CSS Modules 都支持变量的定义和使用,我们挨个看看是怎么用的:

// 定义 common.less 
@width: 10px;
@height: @width + 10px;
// 使用
@import './common.less';
.header {
  width: @width;
  height: @height;
}
// 定义 colors.css
@value blue: #0c77f8;
@value red: #ff0000;
@value green: #aaf200;
// 使用
@value colors: "./colors.css";
@value blue, red, green from colors;
.title {
  color: red;
  background-color: blue;
}

这两种方式在定义和使用上,都比较麻烦,尤其是在使用的时候,需要显式的导入,而我推荐的是另一种方式:就是 CSS 原生支持的方式。使用文档查看:MDN CSS Variables 基本使用方式如下:

// 定义全局变量
:root {
  --main-color: #fff;
}
// 定义局部变量
.container {
  --main-color: #000;
}
// 使用变量
.component {
  color: var(--main-color);
}

我们可以看到,变量有明确的 -- 前缀,比较容易区分,而且使用方便不需要导入,而且很容易做覆盖。如果我们看最新版本的 antd-mobile 的组件库中,就大量使用这种原生的方式做主题的定制和样式的覆盖。

至于兼容性这块,在中后台场景下,Chrome 的支持是非常好的,基本不需要考虑。

image.gif

图片.png

Class 的复用


在 Less 中有基于 extend 和 Mixins 的继承方式,但我觉得都没有 CSS Modules 的继承方式更方便,尤其是 Mixins 这种反常识的使用方式,一旦写不好代码就很容易散、并且不便于维护、新手难以理解。使用 CSS Modules 的 composes 的方式如下:

// 定义
.container {
  color: #fff;
}
// 相同文件下调用
.component {
  composes: container;
}
// 不同文件下调用
.component {
  composes: container from './index.module.less';
  color: #000;
}

如上述的代码,最终会被编译成 <div class="_container_i32us _component_iw22a"/> 且最终生效的 color 是 #000。


如何覆盖第三方组件样式?


我们在平时的编码中经常会去覆盖第三方组件的样式,比如我们使用了 antd 中 Button 的样式,在 module.less 中,我们可以使用  :global关键字,只要使用他的地方都不会在编译时自动添加 Hash,而且这种方式下,也可以给他设定唯一的父元素的 class ,这样你改变的第三方组件的样式就不会影响别的也同样引用该组件的地方的样式。

.container {
  :global(.ant-button) {
    color: var(--main-color);
  }
}


计算样式 classnames


如果一个组件的 class 可能需要多个,或者有可能需要一定的计算,传统的 CSS Modules 的使用方式是比较丑陋的,因此我们使用一种更为优雅的方式来解决,就是借助第三方 NPM 包,classnames 的能力。如下:

// 当 className 需要多个 class 的时候,我们直接使用 classnames 传多个参数的方式
<div className={classnames(style.container1, style.container2)} />
// 最终会编译成 <div class="_contianer1_i323u _container2_i889k" />
// 如果某个 class 是需要一定的逻辑判断的,可以把一个对象传入,用 value 的 false 或者 true 
// 来控制 class 的有无
<div className={classnames({ [style.container1]: true, [style.container2]: false })} />
// 这种方式,是上面两种方式的组合,classnames 可以接收多参数,对象,甚至是数组
<div className={classnames('body', {[style.container1]: true, [style.container2]: false })} />


让人欲罢不能的开发体验


传统写 css 是很难通过编辑器在 JSX  的 div className 上,按住 cmd + 点击快速显示或者定位到样式代码的,但如果我们使用了 CSS Modules ,并且在安装了 VSCode CSS Modules 扩展以后。

image.gif图片.png

如下图所示:我们就可以轻松实现定位和显示,甚至不需要切换到 Less 文件里。

image.gif图片.png

当时真正使用的时候就知道有多爽了。

当然,使用 CSS Modules 还有一个巨大且显而易见的好处是,我们不需要纠结 class 的命名,不同组件内我们甚至可以定义相同的名字,比如:

import style from './index.module.less';
const Login = () => (
  <div className={style.container}>
    <div className={style.header}>登录</div>
  </div>);
const Register = () => (
  <div className={style.container}>
    <div className={style.header}>注册</div>
  </div>);

我们看到,Login 和 Register 组件,我们都使用了 container 和 header 两个 class ,而不需要在前面加组件的前缀。这样更有利于代码的复用,而且可以很好的表达页面的结构。


如果是写 NPM 组件怎么办?


CSS Modules 用在项目的业务代码里是没有问题的,但如果我们想把一些组件做成 NPM 包给别人使用,如果我们用了 CSS Modules ,编译后的 NPM 包,也会把 class 上都加上 Hash 的,是动态变化的。因此当别人想覆盖你的样式的时候,就非常困难了。这个问题怎么解决呢?

确实,社区给出了一些答案,可以看看下面的文档:customizing-components

这里面提出了两个观点,一个是妄图去覆盖别人组件的样式,这本身就是一种 Hack 的行为,我们应该使用更优雅的方式实现,应该让 NPM 组件提供对应的 API 让外部调用修改,第二就是社区提供了一个工具包,react-css-themr,每个 NPM组件接受外部传 theme 参数(css module 对象),用来定义所有样式。示例如下:

import React from 'react';
import { AppBar } from 'react-toolbox/lib/app_bar';
import theme from './PurpleAppBar.css';
const PurpleAppBar = (props) => (
  <AppBar {...props} theme={theme} />
);
export default PurpleAppBar;


总结


上述最佳实践经过本人的多年验证,真实有效,童叟无欺,如果大家喜欢或者不喜欢都可以尝试用起来,早用早享受,晚用晚开心。

相关文章
|
6月前
|
前端开发 JavaScript
webpack成长指北第8章---webpack的CSS Modules打包
webpack成长指北第8章---webpack的CSS Modules打包
69 0
|
5月前
|
前端开发 JavaScript 开发者
CSS进阶 - CSS Modules与预处理器简介
【6月更文挑战第17天】前端开发中,CSS Modules和预处理器(如Sass、Less)解决了大规模项目中CSS的管理难题,提升代码复用和维护性。CSS Modules提供局部作用域的类名,避免全局冲突,而预处理器扩展CSS功能,使代码更像编程语言。常见问题包括命名冲突和过度嵌套,可通过自动哈希、少嵌套、合理变量规划来解决。结合两者使用,遵循模块化和适度预处理原则,集成到构建工具中,能优化开发流程。这些技术是现代前端不可或缺的工具。
69 2
|
3月前
|
前端开发 JavaScript API
Vue 3 新特性:在 Composition API 中使用 CSS Modules
Vue 3 新特性:在 Composition API 中使用 CSS Modules
|
3月前
|
前端开发 JavaScript
vite中css最佳实践:使用postcss完善项目中的css配置
【8月更文挑战第3天】使用postcss完善项目中的css配置
809 1
|
3月前
|
前端开发 JavaScript 开发工具
CSS Modules与Styled Components:提升CSS可维护性
CSS Modules与Styled Components皆提升了现代Web开发中的CSS可维护性。前者通过本地作用域限制CSS选择器范围,生成唯一类名防止全局样式冲突;后者采用CSS-in-JS方式,在JavaScript中定义样式,实现样式与组件的紧密耦合,并支持动态样式。两者各有优势:CSS Modules适合习惯CSS的开发者,提供了局部作用域和导入机制;Styled Components则适用于需要复杂样式逻辑的场景,利用JavaScript的强大功能。选择哪一种取决于项目需求和个人偏好,也可以根据情况将两者结合使用,以充分利用它们的优点。
46 0
|
4月前
|
前端开发 JavaScript
css相对单位 rem 和 em 的最佳实践
css相对单位 rem 和 em 的最佳实践
30 0
|
6月前
|
Java BI 数据库
基于SSM框架实现面向小微企业的简历管理系统企业简历管理系统(分前后台spring+springmvc+mybatis+maven+jsp+css+echarts)
基于SSM框架实现面向小微企业的简历管理系统企业简历管理系统(分前后台spring+springmvc+mybatis+maven+jsp+css+echarts)
|
6月前
|
资源调度 前端开发 JavaScript
《CSS 简易速速上手小册》第9章:CSS 最佳实践(2024 最新版)
《CSS 简易速速上手小册》第9章:CSS 最佳实践(2024 最新版)
108 1
《CSS 简易速速上手小册》第9章:CSS 最佳实践(2024 最新版)
|
6月前
|
移动开发 缓存 前端开发
【专栏:HTML与CSS实践篇】网页性能优化:CSS与HTML的最佳实践
【4月更文挑战第30天】本文探讨了优化CSS和HTML以提升网页性能的最佳实践。HTML优化包括:精简结构、压缩代码、异步加载脚本和利用缓存。CSS优化则涉及:精简代码、合并文件、使用CSS Sprite、善用CSS3属性、避免@import及响应式设计。这些方法能加快加载速度,改善用户体验。
86 6
|
6月前
|
前端开发 JavaScript UED
【专栏】CSS Modules是一种将CSS与模块系统结合的技术,解决传统CSS管理中的全局样式污染和可维护性问题
【4月更文挑战第29天】CSS Modules是一种将CSS与模块系统结合的技术,解决传统CSS管理中的全局样式污染和可维护性问题。它提供局部作用域、模块隔离和自动生成唯一类名,保证样式安全性。与现有CSS语法兼容,且与React、Vue等现代框架集成良好,支持动态样式和主题切换。通过引入CSS Modules,开发者能提升代码的可维护性、可读性和稳定性。了解和使用CSS Modules对于前端开发至关重要。
232 2