CSS 模块 vs CSS-in-JS,谁更胜一筹?

2025-05-24

CSS 模块 vs CSS-in-JS,谁更胜一筹?

介绍

在现代 React 应用程序开发中,组织应用程序样式的方法有很多。其中一种流行的组织方式是 CSS-in-JS 方法(在本文中,我们将使用styled-components作为最流行的解决方案)和 CSS 模块。在本文中,我们将尝试回答这个问题:CSS-in-JSCSS 模块哪个更好?

让我们回归本质。当网页主要用于存储文本文档,不包含用户交互时,属性就被引入用于设置内容样式。随着时间的推移,网络变得越来越流行,网站规模越来越大,重复使用样式变得必不可少。为此,CSS应运而生。层叠样式表。层叠在这个名字中扮演着非常重要的角色。我们编写的样式就像瀑布一样,覆盖在文档的空隙上,用颜色填充,并突出显示重要的元素。

随着时间的流逝,Web 变得越来越复杂,我们面临的一个问题是样式级联问题。分布式团队各自开发系统的各个部分,将它们组合成可复用的模块,然后像弗兰肯斯坦博士一样,将各个部分拼凑成一个大画布,最终得到意想不到的结果……由于级联的存在,模块 1 的样式可能会影响模块 3 的显示,而模块 4 可能会更改全局样式,最终影响整个应用程序的显示。

开发人员已经开始思考如何解决这个问题。为了避免重叠,他们创建了样式命名约定,例如 Yandex 的 BEM 或 Atomic CSS。其思路很明确:我们使用名称是为了获得可预测性,同时避免重复。

这些方法都被人为因素击溃了。无论如何,我们无法保证 A 团队的开发人员不会使用 C 团队的名称。

命名问题只能通过为 CSS 类分配一个随机名称来解决。这样,我们就得到了一组完全独立的 CSS 样式,它们将应用于特定的 HTML 块,并且我们确信系统的其余部分不会受到任何影响。

随后,两种组织 CSS 的方法应运而生:CSS 模块CSS-in-JS。从本质上讲,它们采用了不同的技术实现,但实际上解决了编写 CSS 时的原子性、可重用性和避免副作用的问题。

从技术上讲,CSS Modules 使用基于文件名、路径和样式名称的哈希值来转换样式名称。Styled-components 在 JS 运行时处理样式,并在它们进入HTML头部(<head>) 时添加它们。

方法概述

让我们看看哪种方法更适合编写现代 Web 应用程序!

假设我们有一个基本的 React 应用程序:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
 render() {
   return (
     <div className="title">
       React application title
     </div>
   );
 }
}
Enter fullscreen mode Exit fullscreen mode

此应用程序的 CSS 样式:

.title {
 padding: 20px;
 background-color: #222;
 text-align: center;
 color: white;
 font-size: 1.5em;
}
Enter fullscreen mode Exit fullscreen mode

依赖项是 React 16.14、 react-dom 16.14

让我们尝试使用 webpack 和所有生产优化来构建此应用程序。

我们有

丑化后的 JS - 129kb
分离并缩小后的 CSS - 133 字节

CSS 模块中的相同代码如下所示:

import React, { Component } from 'react';
import styles from './App.module.css';

class App extends Component {
 render() {
   return (
     <div className={styles.title}>
       React application title
     </div>
   );
 }
}
Enter fullscreen mode Exit fullscreen mode

丑化后的 JS - 129kb
分离并缩小后的 CSS - 151 字节

由于无法压缩生成的长 CSS 名称,CSS 模块版本将占用更多字节。

最后,让我们在 styled-components 下重写相同的代码:

import React, { Component } from 'react';
import styles from 'styled-components';

const Title = styles.h1`
 padding: 20px;
 background-color: #222;
 text-align: center;
 color: white;
 font-size: 1.5em;
`;

class App extends Component {
 render() {
   return (
     <Title>
       React application title
     </Title>
   );
 }
}
Enter fullscreen mode Exit fullscreen mode

丑化 JS - 缺少163kb CSS 文件

CSS 模块CSS-in-JS(styled-components)之间超过30kb 的差异是由于 styled-components 添加了额外的代码来将样式添加到 HTML 文档的 <head> 部分。

在这个综合测试中,CSS Modules 方法胜出,因为构建系统除了修改类名之外,没有添加任何额外内容来实现它。由于技术实现的原因,Styled-components 添加了依赖项以及用于运行时处理和 <head> 样式的代码。

现在让我们快速了解一下 CSS-in-JS / CSS 模块的优缺点。

优点和缺点

CSS-in-JS

缺点

  • 直到 styled-components 解析这些样式并将其添加到 DOM 中时,浏览器才会开始解释这些样式,这会减慢渲染速度。
  • 缺少 CSS 文件意味着您无法缓存单独的 CSS。
  • 一个关键的缺点是大多数库不支持这种方法,而且我们仍然无法摆脱 CSS。所有原生 JS 和 jQuery 插件都是不使用这种方法编写的。并非所有 React 解决方案都使用它。
  • 样式集成问题。当标记开发人员为 JS 开发人员准备布局时,我们可能会忘记传输某些内容;同步新版本的布局和 JS 代码也会很困难。
  • 我们不能使用 CSS 实用程序:SCSS、Less、Postcss、stylelint 等。

优点

  • 样式可以使用 JS 逻辑。这让我想起了 IE6 中的 Expression,当时我们可以在样式中包装一些逻辑(你好,CSS 表达式 :))。
const Title = styles.h1`
 padding: 20px;
 background-color: #222;
 text-align: center;
 color: white;
 font-size: 1.5em;
 ${props => props.secondary && css`
   background-color: #fff;
   color: #000;
   padding: 10px;
   font-size: 1em;
 `}
`;
Enter fullscreen mode Exit fullscreen mode
  • 在开发小模块时,它简化了与项目的连接,因为您只需要连接一个独立的JS文件。
  • 从语义上讲,在 React 组件中使用 <Title> 比使用 <h1 className={style.title}> 更好。

CSS 模块

缺点

  • 要描述全局样式,您必须使用不属于 CSS 规范的语法。
:global(.myclass) {
    text-decoration: underline;
}
Enter fullscreen mode Exit fullscreen mode
  • 集成到一个项目中,您需要包含样式。
  • 使用 TypeScript 时,您需要自动或手动生成接口。为此,我使用了 Webpack 加载器:

@teamsupercell/typings-for-css-modules-loader

优点

  • 我们采用常规 CSS,因此可以使用 SCSS、Less、Postcss、stylelint 等。此外,您无需浪费时间将 CSS 适配到 JS。
  • 代码中无需集成任何样式,因此代码非常简洁。
  • 除全球风格外,几乎 100% 标准化。

结论

所以,CSS-in-JS 方法的根本问题在于它根本不是 CSS!如果你的团队中只有一位固定的人员负责标记,这种代码会更难维护。由于渲染到文件中的 CSS 是并行处理的,而 CSS-in-JS 无法渲染到单独的 CSS 文件中,因此这类代码的运行速度会更慢。最后一个根本缺陷是无法使用现成的方法和实用程序,例如 SCSS、Less 和 Stylelint 等等。

另一方面,CSS-in-JS 方法对于同时处理标记和 JS 并从头开发所有组件的前端团队来说是一个不错的解决方案。此外,CSS-in-JS 对于集成到其他应用程序的模块也非常有用。

我个人认为,CSS 层叠的问题被高估了。如果我们只与一个团队开发一个小型应用程序或网站,那么我们不太可能遇到名称冲突或组件复用困难的问题。如果您也面临这个问题,我建议您考虑 CSS 模块,因为在我看来,这是针对上述因素的更优解决方案。无论如何,无论您选择哪种方式,都要编写有意义的代码,不要被炒作所迷惑。炒作终将过去,我们都必须接受它。祝愿亲爱的读者们,项目精彩纷呈、妙趣横生!

文章来源:https://dev.to/alexsergey/css-modules-vs-css-in-js-who-wins-3n25
PREV
项目结构。存储库和文件夹。方法回顾。文件夹结构
NEXT
亚马逊软件工程师级别:角色和期望(含薪资)