12
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

この記事の概要

Meta 社製の CSS in JS ライブラリである StyleX が登場しました。

2021 年には言及されていたようですが、2023 年 12 月 5 日(現地時間)に一般公開されたみたいです。

普段自分は Vite を使うことが多いので、Vite + StyleX の組み合わせを試してみます。

Vite の準備

まずは作成します。

bun create-vite 

React, TypeScript, SWC を選択しました。

StyleX の準備

まずは公式ドキュメントにある通り進めます。

bun i @stylexjs/stylex

続いて、Vite は Rollup を使っているので @stylexjs/rollup-plugin を入れて動かそうとしましたが、駄目でした。

Issue で議論されていて、Pull Request も作成中なようで、近いうちに公式からサポートされそうではありますが、2023 年 12 月 11 日現在は上手く動きません。

しかし調べたら個人の方がプラグインを作ってくださっていました。
ありがたく使わせていただきます。

bun i -d vite-plugin-stylex
vite.config.ts
  import { defineConfig } from "vite";
  import react from "@vitejs/plugin-react-swc";
+ import styleX from "vite-plugin-stylex";

  export default defineConfig({
-   plugins: [react()],
+   plugins: [react(), styleX()],
  });

これで準備は完了です。
以下は依存関係とバージョンの一覧です。

package.json
{
  // 省略
  "dependencies": {
    "@stylexjs/stylex": "^0.3.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.37",
    "@types/react-dom": "^18.2.15",
    "@typescript-eslint/eslint-plugin": "^6.10.0",
    "@typescript-eslint/parser": "^6.10.0",
    "@vitejs/plugin-react-swc": "^3.5.0",
    "eslint": "^8.53.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.4",
    "typescript": "^5.2.2",
    "vite": "^5.0.0",
    "vite-plugin-stylex": "^0.1.0"
  }
}

基本の書き方

stylex を import した上で

import * as stylex from "@stylexjs/stylex";

stylex.create() でスタイルを生成して

const styles = stylex.create({
  foo: {
    color: 'red',
    fontSize: '2em'
  },
  bar: {
    backgroundColor: 'blue',
  },
});

stylex.props() で使用します。

{/* 個別に適用 */}
<div {...styles.props(styles.foo)}>foo</div>
<div {...styles.props(styles.bar)}>bar</div>

{/* あわせて適用 */}
<div {...styles.props(styles.foo, styles.bar)}>foo bar</div>

通常のスタイルを書く

create-vite で生成された App.tsx にスタイルを当ててみます。

App.tsx
  import { useState } from "react";
  import reactLogo from "./assets/react.svg";
  import viteLogo from "/vite.svg";
  import "./App.css";
+ import * as stylex from "@stylexjs/stylex";

+ const styles = stylex.create({
+   title: {
+     color: "#55c500",
+   },
+ });

  function App() {
    const [count, setCount] = useState(0);

    return (
      <>
        {/* 省略 */}
        <h1 {...stylex.props(styles.title)}>Vite + React</h1>
        {/* 省略 */}
      </>
    );
  }

  export default App;
before after

ただ色を変えただけですが、上手く動いています。

以下は出力されたコードです。

HTML
<h1 class="App__styles.title x1g81dyc">Vite + React</h1>
CSS
.x1g81dyc {
    color: rgb(85, 197, 0);
}

少しスタイルを追加してみます。

App.tsx
  const styles = stylex.create({
    title: {
      color: "#55c500",
+     fontSize: "5rem",
+     marginBlock: 0,
    },
  });

出力されるコードも変わりました。
1 つのプロパティにつき 1 つのクラスが追加されるようです。

HTML
<h1 class="App__styles.title x1g81dyc xn7rfii x10im51j">Vite + React</h1>
CSS
.x10im51j {
    margin-block: 0px;
}

.xn7rfii {
    font-size: 5rem;
}

.x1g81dyc {
    color: rgb(85, 197, 0);
}

先ほどリンクを貼ったブログ内で atomic class names と書かれていた作りです。
Tailwind CSS のアプローチと同じような感じです。

state にあわせたスタイルを書く

特別紹介するほどのものでもないかもしれませんが、state にあわせてスタイルを変更するのも問題ないようです。

App.tsx
  const styles = stylex.create({
    title: {
      color: "#55c500",
      fontSize: "5rem",
      marginBlock: 0,
    },
+   button: {
+     backgroundColor: "#ddd",
+   },
+   active: {
+     backgroundColor: "#212121",
+     color: "white",
+   }
  });

{/* 中略 */}

  <button
    onClick={() => setCount((count) => count + 1)}
+   {...stylex.props(count > 0 ? styles.active : styles.button)}
  >
    count is {count}
  </button>

想定通り変化しています。

最後に

まだバージョンは 1 にも満たないので本番適用するのは怖いですが、Meta が出しているなら React との相性は良いはずでは?とも思えます。

期待しつつ引き続き見ておきます。

12
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?