三分钟通关一门新技术-StyleX

大家好,我是果汁,最近准备开一个新坑《三分钟通关系列》,旨在给还在观望新技术的童鞋一个快速了解的窗口,如果有兴趣可以关注一下这个系列,Thanks♪(・ω・)ノ。今天我们来通关的是 meta 公司新出的开源产品:StyleX

StyleX 是什么?

按官网原文来说如下

StyleX is a simple, easy to use JavaScript syntax and compiler for styling web apps.

简单来说,是一个快速构建应用样式的 JavaScript 语法编译器,这里注意它的定位并不是单纯的 css 预编译器,具体原因下面会解释。

和现有 cssinjs 库的异同

相同点

  1. 语法上都是用 js 来书写 css 属性,类似下面这样:
tsx 复制代码
// stylex
import * as stylex from '@stylexjs/stylex';

const styles = stylex.create({
  root: {
    width: '100%',
    maxWidth: 800,
    minHeight: 40,
  },
});

// aphrodite
import { StyleSheet } from "aphrodite";

const styles = StyleSheet.create({
    navBarItem: {
        flexDirection: "row",
        fontSize: 16,
        fontWeight: "300"
    }
});

// styled-components
import styled from 'styled-components';

// Create a <Title> react component that renders an <h1> which is
// centered, palevioletred and sized at 1.5em
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

function MyUI() {
  return (
    <Title>Hello World, this is my first styled component!</Title>
  );
}

// emotion
import { css } from '@emotion/css'

const color = 'white'

render(
  <div
    className={css`
      padding: 32px;
      background-color: hotpink;
      font-size: 24px;
      border-radius: 4px;
      &:hover {
        color: ${color};
      }
    `}
  >)

可以看到,基本上语法分为两种,一种是直接按对象书写,另一种是直接写 css 字符串,两种方式各有优点, css 字符串更贴近原生,但是类型没法接入,直接按对象书写虽然要改变书写 css 的习惯,但是可以保留类型。

  1. 都会生成 hash 来保证 css 样式的作用域隔离,类似这样 css-1h3ivcl
  2. 都可以很方便的和 js 进行交互,动态样式和定制主题都会非常方便。

不同点

  1. cssinjs 库的弊端之一,昂贵的运行时消耗(runtime const),基本存在于所有 cssinjs 库, StyleX 不同于常规 cssinjs 库,它几乎可以做到 0 运行时(zero runtime),得益于他的架构,可以把同一文件的样式给抽离成 css 文件,动态样式又可以以极低的成本运行,速度非常快。
  2. 可以很方便的跨文件复用组合样式,现在其他 cssinjs 库很难做到。
  3. 可以准确的预测 css 最终渲染的优先级,最后写的样式的渲染时永远在最前面,而不会随 js 执行顺序发生偏差。
  4. 提供类型支持,可以很方便的约束每个样式对象里的属性。
  5. 并不提供完整的 css 选择器功能,为了使应用可预测,一些伪类选择器可能并不支持,比如 .className > *.className ~ *.className:hover > div:first-child 等,这也是为什么不说他是 css 预编译器的原因,从底层就限制了某些语法。

StyleX 的目标

作为 cssinjs 的终极解决方案

虽然用例都是 React 的例子,但 StyleX 并不是 CSS-in-React 的解决方案,目标是作为通用 cssinjs 的解决方案,本身是支持使用 jsx 或者 模板字符串等的框架。最终是希望在提高开发体验的同时,runtime 的性能也要好。

方便的共享样式

StyleX 旨在创建一个系统,可以轻松可靠地共享样式以及 NPM 上包内的组件。

更快的样式加载速度

StyleX 经过优化,可生成预先加载的单个高度优化的 CSS 包, 目的是以足够快的方式预先加载所有的 css

更简单的上手方式

StyleX 常用的 API 就两个,stylex.createstylex.props,一个用来创建样式,一个用来应用样式,非常简单,心智成本基本没有。

上手体验

了解了 StyleX 的大体能力后,我们现在来实战上手体验一下,首先我们先初始化 vite 脚手架:

pnpm 复制代码
pnpm create vite stylex-demo --template react-ts

初始完之后,安装依赖

pnpm 复制代码
pnpm install --save @stylexjs/stylex

安装编译插件,由于脚手架是 vite,所以我们安装 vite-plugin-stylex 的插件, 具体安装什么根据自己项目的构建器来选择,官网指路

顺便一提,StyleX 是支持快速本地调试开发的,如果觉得短时间不会上线,可以直接用这个包 @stylexjs/dev-runtime 来进行本地开发,就不需要装编译插件了,官网指路

pnpm 复制代码
$ pnpm install --save-dev vite-plugin-stylex

同时我们在 vite.config.ts 里面配置插件

ts 复制代码
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import stylexPlugin from "vite-plugin-stylex";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), stylexPlugin()],
});

准备就绪,现在我们修改 App.tsx 里的样式代码,改成 StyleX 的写法:

diff 复制代码
+ import * as stylex from "@stylexjs/stylex";

+ const styles = stylex.create({
+  stylexTest: {
+    color: "red",
+    fontWeight: "blod"
+  },
+ });

function App() {
  return (
+      <div {...stylex.props(styles.stylexTest)}>
       StyleX Test
      </div>
  );
}

export default App;

然后我们就能在浏览器上看到样式出来了

让我们打开控制台看看,可以发现开发环境下,并不会自动生成 css 文件,而是走正常的编译流程

然后我们再打包看看,会发现打包的时候多了一个 stylex.28b4cb32.css 的样式文件

启动本地服务器查看线上生产环境

可以发现 css 样式已经被固化到 css 文件里了,现在和正常的 htmlcss 页面没啥区别了,已经没有 cssinjs 的运行时开销,现在可以说是零运行时。那问题来了如果是动态样式会怎么样呢?,我们修改下之前的文件

tsx 复制代码
import * as stylex from "@stylexjs/stylex";
import { useState } from "react";

const styles = stylex.create({
  stylexTest: (color) => ({
    color,
    fontWeight: "blod",
  }),
});

function App() {
  const [color, setColor] = useState<"red" | "blue">("red");
  return (
    <div {...stylex.props(styles.stylexTest(color))}>
      StyleX Test
      <br />
      <button onClick={() => setColor(color === "red" ? "blue" : "red")}>
        Change Color
      </button>
    </div>
  );
}

export default App;

运行后发现,之前的静态样式被替换成了 cssvar,没错,这就是 StyleX 对动态样式的解决方案,这样切换样式只需要修改 cssvar 的值,由于原生切换基本没有啥性能损耗,所以我们可以理解为 StyleX 的动态样式的 runtime 性能也是非常好的。

demo 我放到 github 上了,有需要的童鞋自取,戳 stylex-demo

总结

可以看到,StyleX 作为 cssinjs 的解决方案,已经吸取了老牌库的经验教训,摸索出了一条自己的路,目前看来确实比其他库来的更加优秀,性能上也更好。项目目前还在起步阶段,有兴趣的童鞋可以移步官网进行了解,作为 meta 的开源作品,我相信质量是可以保证的,就看后面的生态发展如何了,让我们拭目以待吧!

相关推荐
rzl029 分钟前
java web5(黑马)
java·开发语言·前端
Amy.Wang10 分钟前
前端如何实现电子签名
前端·javascript·html5
今天又在摸鱼13 分钟前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿15 分钟前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再17 分钟前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling55521 分钟前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
拾光拾趣录26 分钟前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css
莫空000027 分钟前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl28 分钟前
深度剖析Kafka读写机制
前端
FogLetter28 分钟前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css