8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CSSAdvent Calendar 2023

Day 14

Meta社の新CSS-in-JSソリューション StyleX を使ってみた

Posted at

つい2週間前12/1にMeta社よりStyleXという新しいCSS-in-JSライブラリが公開されました。

StyleX is a JavaScript library for defining styles for optimized user interfaces.

StyleXの特徴としてはここの公式ドキュメントに記載されています。要するに早くて最適化されていてtype safeと書かれています。

まだ新しいライブラリのため、公式ドキュメントがうまく動作しなかったため記事にしました。しかし、今後仕様は変わる可能性があります。

使ってみた

本番環境で使用する

今回はNext.jsに組み込んでみます。基本的には公式ドキュメント通りに実行します。

ちなみに公式のサンプルもあります。

早速既存のプロジェクトに導入だ!と言いたところですが、動きません。動かすためにいくつか手伝ってあげましょう。

インストール

この5つを入れてください。

yarn add @stylexjs/stylex
yarn add -D @stylexjs/nextjs-plugin
yarn add -D @stylexjs/babel-plugin
yarn add -D @stylexjs/eslint-plugin # eslintを使っている場合
yarn add -D @stylexjs/dev-runtime # 開発環境でも使用したい場合

TypeScriptのバージョンを上げる

どこから動くかは調べていませんが、5以上なら動きます。

next.config.jsの修正

公式ドキュメントと違いますが、公式サンプルと似たコードになっています。

next.config.js
/** @type {import('next').NextConfig} */
const stylexPlugin = require("@stylexjs/nextjs-plugin");
const babelrc = require("./.babelrc.js");
const plugins = babelrc.plugins;
const [_name, options] = plugins.find(
  (plugin) => Array.isArray(plugin) && plugin[0] === "@stylexjs/babel-plugin",
);
const rootDir = options.unstable_moduleResolution.rootDir ?? __dirname;

const stylexConfig = stylexPlugin({
  rootDir,
  useCSSLayers: true,
})({});

module.exports = {
  ...stylexConfig,
  output: "export", // Static Site Generateする場合のみ
};

babelの設定

公式ドキュメントに書かれているbabel.config.jsは不要でした。代わりに.babelrc.jsは必要です。

これは基本的にドキュメントの通りで問題ありませんが、後述の「開発環境で使用する」を実施する場合はコメントの通り 1 行だけ変えてください。

.babelrc.js
module.exports = {
  presets: ["next/babel"],
  plugins: [
    [
      "@stylexjs/babel-plugin",
      {
        dev: process.env.NODE_ENV === "development",
        runtimeInjection: true, // ここだけ変えた
        genConditionalClasses: true,
        treeshakeCompensation: true,
        unstable_moduleResolution: {
          type: "commonJS",
          rootDir: __dirname,
        },
      },
    ],
  ],
};

.eslintrc.jsonの設定

公式ドキュメントの通りで大丈夫です。

.eslintrc.js
module.exports = {
  plugins: ["@stylexjs"],
  rules: {
    "@stylexjs/valid-styles": ["error", {...options}],
  },
};

開発環境で使用する

先ほどまでのコードは環境変数にNODE_ENV=productionが入った場合のみスタイルを適用するようになっています。そのため、next devで開発している際にもスタイリングしてあげましょう。

ちなみにこれは公式ドキュメント通りでは動かないので注意です。

_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import inject from "@stylexjs/dev-runtime";

if (process.env.NODE_ENV !== "production") {
  inject({
    classNamePrefix: "x",
    dev: true,
    test: false,
    useRemForFontSize: false,
    runtimeInjection: false,
    styleResolution: "application-order",
  });
}

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;

スタイルを適用する

こんな感じでかけます。

index.ts
import { NextPage } from "next";
import stylex from "@stylexjs/stylex";

export const s = stylex.create({
  redOrBlueText: {
    color: {
      default: 'red',
      ":hover": 'blue'
    }
  },
  backYellow: {
    backgroundColor: 'yellow'
  }
})
const Home: NextPage = () => {
  return <div {...stylex.props(s.redOrBlueText, s.backYellow)}>ABC</div>
}

通常時
スクリーンショット 2023-12-16 17.40.59.png

カーソルをホバーしたとき
スクリーンショット 2023-12-16 17.41.30.png

🎉🎉🎉

おわり

多分数日後にはこの記事が動かなくなっていますが、その時はすみません。

8
2
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
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?