搜索
首页web前端css教程解码 StyleX:Meta 的尖端造型系统

每年十月,最大的国际 React 会议都会在印度果阿举行。是的,我说的是 React India。今年(2024 年)对我来说更加特别,因为我有机会在这场盛大的会议上发言。如果您错过了现场观看的话,这是我的演讲录音。如果您更喜欢阅读而不是观看视频,那么这个博客非常适合您!让我们深入探讨一下。

什么是 StyleX?

StyleX 是 Meta 的新的、可扩展的样式库,现在被用作 Facebook、Instagram 和 WhatsApp 等平台背后的主要系统。它解决了 CSS-in-JS 方法所遇到的痛点,特别是在大规模 React 应用程序中。通过提供融合原子 CSS 和静态 CSS 最佳功能的混合解决方案,StyleX 提供了高效、模块化和可扩展的替代方案。

Meta 如何以及为何创建 StyleX?

  • Meta 构建 StyleX 来解决传统 CSS-in-JS 库在大型项目中遇到的特定挑战:
  1. 未使用的样式:随着项目的增长,CSS 经常会积累未使用的规则,使样式表变得臃肿。
  2. 性能问题: CSS-in-JS 解决方案可能会导致 CSS 文件过大或出现性能瓶颈,尤其是与应用程序捆绑在一起时。
  3. CSS-in-JS 库大小: 许多用于 JavaScript 样式的流行库给包添加了不必要的重量,影响了加载时间。
  • StyleX 简介:它于 2019 年创建,作为 Facebook UI 改造的一部分,并于 2023 年 12 月将其开源。
  • CSS 优化:在使用 StyleX 之前,Facebook 上的单个页面将加载大约 15-45MB 的 CSS 样式。通过利用单个 CSS 捆绑包,StyleX 的大小大大减少到 200-300KB 左右。
  • StyleX 的目的:开发它是为了有效地大规模管理样式的复杂性。它解决了众多开发人员创建数千个组件时出现的挑战,这通常会导致 CSS 内的特殊性冲突。通过提供结构化的样式框架,StyleX 有助于保持样式过程的一致性和清晰度。
  • 原子类生成:从一开始,StyleX 就一致地生成原子类,接受每个组件具有多个类名的权衡,以提高可维护性并减少样式冲突。

StyleX 的主要特点:

  1. 原子 CSS 生成:StyleX 采用原子 CSS 生成,这意味着它为每个样式规则创建小型、可重用的类。这种方法不仅可以最大限度地减少最终 CSS 包中的冗余,还可以通过减小样式表的整体大小来提高性能。

  2. CSS 重复数据删除:通过为每种样式生成唯一的类标识符,StyleX 有效地消除了重复的样式。此重复数据删除过程可确保每个属性值对仅渲染一次,进一步有助于实现更精简的 CSS 输出。

  3. “最后应用的样式总是获胜!”:StyleX 遵循可预测的样式规则,其中最后应用的样式优先。此功能简化了调试并增强了开发人员的信心,因为它减轻了对样式规则冲突的担忧。

  4. 针对 React 进行了优化:StyleX 专为 React 应用程序设计,无缝集成到 React 生态系统中。它允许开发人员直接在其组件中定义样式,从而形成更具凝聚力的开发工​​作流程。

  5. Flow 和 TypeScript 支持:StyleX 是用“Flow”(由 Meta 创建)编写的,它还为 TypeScript 提供强大的支持,为样式和主题启用类型安全的 API。这种类型安全性增强了代码的可靠性和可维护性,使管理复杂的样式场景变得更加容易。

  6. 灵活的条件样式:使用 StyleX,开发人员可以根据组件状态或 props 有条件地应用样式。这种灵活性允许动态样式适应用户交互或应用程序状态的变化。

  7. 范围样式:StyleX 的范围样式功能可确保样式仅应用于其预期的组件。这可以防止大型代码库中经常出现的意外副作用和特异性问题。

  8. 更少的运行时计算:StyleX 通过在编译时将所有样式捆绑到静态 CSS 文件中来最大限度地减少运行时计算。这种优化可以缩短渲染时间并提高性能,尤其是在大型应用程序中。

  9. 更好的代码可维护性:通过将样式与其各自的组件共置并利用原子类,StyleX 提高了代码的可维护性。开发人员可以轻松理解和修改样式,而无需筛选大量样式表。

  10. 最小 CSS 输出:使用原子 CSS 会导致最小 CSS 输出,这对性能特别有利。随着项目规模和复杂性的增加,StyleX 可确保 CSS 捆绑包在不牺牲功能的情况下保持可管理性。

  11. 适用于各种规模的项目:虽然 StyleX 适用于各种规模的项目,但它在大型应用程序中确实表现出色。其架构旨在处理广泛的样式需求的复杂性,而不影响性能或可维护性。

让我们看看它是如何工作的?

本文中的代码示例是用 React 编写的,我们将主要使用两个组件:App.jsx 和 Button.jsx。在添加样式之前,我们先看一下这些组件的基本结构。

import Button from "./components/Button";

const App = () => {
  return (
    <div>
      <h1 id="StyleX-by-Meta">StyleX by Meta</h1>
      <button text="Get Started"></button>
    </div>
  );
};

export default App;
// Button.jsx
import PropTypes from "prop-types";

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

Decoding StyleX: Meta

使用 StyleX 添加样式

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: "black",
    color: "white",
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

要使用这些样式,我们需要从 styleX 包中导入它们,然后使用以对象作为参数的 stylex.create 方法定义样式。然后我们可以使用 stylex.props 方法将样式应用到组件。

在此示例中,base 是我们要应用的样式的名称。我们在 StyleX 中将它们称为 命名空间。这就是我们的按钮组件现在的样子。

Decoding StyleX: Meta

向伪类添加样式

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: {
      default: "black",
      ":hover": "blue",
    },
    color: "white",
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

使用 StyleX,向伪类添加样式非常简单。在前面的示例中,backgroundColor 是一个字符串。在这里,我们将其转换为具有默认值和伪类的对象。

Decoding StyleX: Meta

使用媒体查询

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: {
      default: "black",
      ":hover": "blue",
    },
    color: "white",
    width: {
      default: "100px",
      "@media (max-width: 476px)": "100%",
    },
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

与其他样式库相比,我们在 StyleX 中做的不同的一件事是媒体查询。在这里,我们根据需求将媒体查询应用于每个命名空间。在此示例中,我们将较大屏幕的按钮宽度定义为 100px,较小屏幕或移动设备的按钮宽度定义为 100%。

Decoding StyleX: Meta

让我们看看如何“最后应用的风格总是获胜”

让我们扩展前面的示例,看看如何创建此按钮的不同变体。

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: {
      default: "teal",
      ":hover": "blue",
    },
    color: "white",
    width: {
      default: "100px",
      "@media (max-width: 476px)": "100%",
    },
  },
  highlighted: {
    backgroundColor: "orange",
  },
  danger: {
    backgroundColor: "red",
  },
  primary: {
    backgroundColor: "green",
  },
});

const Button = ({ text, isHighlighted, variant }) => {
  return (
    <button styles.base ishighlighted styles.highlighted conditional styling styles>
      {text}
    </button>
  );
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
  isHighlighted: PropTypes.bool,
  variant: PropTypes.oneOf(["danger", "primary"]),
};

让我们向 stylex.create 方法添加更多命名空间,并为它们提供不同的背景颜色。此外,我们在 Button 组件中接受了 2 个新的 props。 isHighlighted 是一个布尔属性,我们用它来应用突出显示的命名空间。变量是我们用来应用主要、危险或突出显示的命名空间的道具。

// App.jsx
import Button from "./components/Button";

const App = () => {
  return (
    <div>
      <h1 id="StyleX-by-Meta">StyleX by Meta</h1>
      <div>
        <button text="Base Button"></button>
        <button text="Highlighted Button" ishighlighted></button>
        <button text="Danger Button" ishighlighted variant="danger"></button>
        <button text="Primary Button" variant="primary"></button>
      </div>
    </div>
  );
};

export default App;

我们创建了几个 Button 组件的副本,并传递不同的 props。这就是我们的应用程序现在的样子。

Decoding StyleX: Meta

现在,仔细看看“危险按钮”。即使我们将 isHighlighted 传入 true,突出显示的命名空间也不会应用。最后提到了危险变体,因此将应用它。因此,该按钮将具有红色背景颜色。

覆盖父级的样式

我们可以直接从 App.jsx 覆盖此 Button 组件的样式属性。

import Button from "./components/Button";

const App = () => {
  return (
    <div>
      <h1 id="StyleX-by-Meta">StyleX by Meta</h1>
      <button text="Get Started"></button>
    </div>
  );
};

export default App;

Decoding StyleX: Meta

在此示例中,覆盖命名空间当前允许任何属性。然而,StyleX 使我们能够限制哪些属性可以被覆盖。使用 TypeScript 时,此功能变得特别有用。

// Button.jsx
import PropTypes from "prop-types";

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

此限制确保只有 backgroundColor 和 color 属性可以被覆盖。

原子类如何工作(内部)

Decoding StyleX: Meta

如果您向上滚动到前面的示例代码,您将看到我们已将 margin: "1rem" 样式添加到 3 个不同的命名空间 - App.jsx 中的 main、Button.jsx 中的突出显示和主要。当我们使用 Devtools 检查元素时,我们可以看到不同的组件(主容器、突出显示的按钮和主按钮)附加有相同的类名,并且只有 1 个类 x42y017 保留 margin: "1rem" 样式。

这就是 StyleX 通过使用原子类显着减小其包大小的方式。达到一定阈值后,不再生成新的类;相反,他们只是重用现有的类。

全局变量和主题

能够在粒度级别覆盖样式真是太棒了!然而,任何给定的设计系统都需要支持设计标记和主题。这就是 StyleX 的用武之地。StyleX 中主题 API 的设计直接受到 React Context API 的启发。变量的定义默认值与 React Context 的创建方式类似,并且可以创建主题来为 UI 子树的这些变量“提供”不同的值。

我们可以通过创建 x.stylex.js 文件来创建全局样式。确保遵循此命名约定。在此文件中,我们使用 stylex.defineVars,如下所示。

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: "black",
    color: "white",
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

我们指的是用户的首选主题并将其设置为常量值 - DARK。此外,让我们使用此颜色变量创建一个新主题。

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: {
      default: "black",
      ":hover": "blue",
    },
    color: "white",
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

主题创建后,就可以像 StyleX 中的任何其他样式一样使用。

import PropTypes from "prop-types";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  base: {
    fontSize: 18,
    backgroundColor: {
      default: "black",
      ":hover": "blue",
    },
    color: "white",
    width: {
      default: "100px",
      "@media (max-width: 476px)": "100%",
    },
  },
});

const Button = ({ text }) => {
  return <button>{text}</button>;
};

Button.propTypes = {
  text: PropTypes.string.isRequired,
};

export default Button;

这就是我们如何分别在浅色和深色模式下看到与 myCustomTheme 相同的页面。

Decoding StyleX: Meta

这就是裹?

万岁!我们已经成功掌握了与 StyleX 合作的要点。感谢您阅读本文。我希望它能让您更好地理解什么是 StyleX、Meta 是如何创建它以及如何使用它。请在评论部分或 Twitter 上分享您的想法/疑问。如果您对这个博客感兴趣,如果您能给这篇文章点个赞(用您最喜欢的表情符号?),我将不胜感激。

平安✌

参考

  • 关于我的课程
  • 在这里观看我的演讲!
  • React India 对我来说怎么样?

在 Topmate 上与我联系以进行面试准备
Decoding StyleX: Meta

以上是解码 StyleX:Meta 的尖端造型系统的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
什么是CSS网格?什么是CSS网格?Apr 30, 2025 pm 03:21 PM

CSS网格是创建复杂,响应式Web布局的强大工具。它简化了设计,提高可访问性并提供了比旧方法更多的控制权。

什么是CSS Flexbox?什么是CSS Flexbox?Apr 30, 2025 pm 03:20 PM

文章讨论了CSS FlexBox,这是一种布局方法,用于有效地对齐和分布响应设计中的空间。它说明了FlexBox用法,将其与CSS网格进行了比较,并详细浏览了浏览器支持。

我们如何使用CSS使网站迅速响应?我们如何使用CSS使网站迅速响应?Apr 30, 2025 pm 03:19 PM

本文讨论了使用CSS创建响应网站的技术,包括视口元标签,灵活的网格,流体媒体,媒体查询和相对单元。它还涵盖了使用CSS网格和Flexbox一起使用,并推荐CSS框架

CSS盒装属性有什么作用?CSS盒装属性有什么作用?Apr 30, 2025 pm 03:18 PM

本文讨论了CSS盒装属性,该属性控制了元素维度的计算方式。它解释了诸如Content-Box,Border-Box和Padding-Box之类的值,以及它们对布局设计和形式对齐的影响。

我们如何使用CSS动画?我们如何使用CSS动画?Apr 30, 2025 pm 03:17 PM

文章讨论使用CSS,关键属性并与JavaScript结合创建动画。主要问题是浏览器兼容性。

我们可以使用CSS向我们的项目添加3D转换吗?我们可以使用CSS向我们的项目添加3D转换吗?Apr 30, 2025 pm 03:16 PM

文章讨论了Web项目的3D转换,关键属性,浏览器兼容性和性能注意事项的讨论。(角色计数:159)

我们如何在CSS中添加梯度?我们如何在CSS中添加梯度?Apr 30, 2025 pm 03:15 PM

文章讨论了使用CSS梯度(线性,径向,重复)来增强网站视觉效果,添加深度,焦点和现代美学。

CSS中的伪元素是什么?CSS中的伪元素是什么?Apr 30, 2025 pm 03:14 PM

文章讨论了CSS中的伪元素,它们在增强HTML样式方面的使用以及与伪级的差异。提供实用的例子。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器