😁

CSS-in-JS派がMeta社製CSS-in-JSのStyleXを使ってみた

2023/12/06に公開

導入

今までCSS-in-JS派だった私が、Next.jsのApp Routerで新プロジェクトを立ち上げるにあたってTailwind CSSを導入するしか選択肢がありませんでした。なぜかというとApp Routerの肝となるReact Server ComponentsではまだまだCSS-in-JSライブラリがサポートされておらず、クライアントコンポーネントでのみサポートされている状態だったからです。 [1]

Warning: CSS-in-JS libraries which require runtime JavaScript are not currently supported in Server Components. Using CSS-in-JS with newer React features like Server Components and Streaming requires library authors to support the latest version of React, including concurrent rendering.

公式でもTailwind CSSやCSS Modulesをお勧めしていました。

If you want to style Server Components, we recommend using CSS Modules or other solutions that output CSS files, like PostCSS or Tailwind CSS.

しかし、2023/12/06にMeta社製のCSS-in-JS、Stylexが発表されました🙌
https://stylexjs.com/

そこで自分の備忘録がてら触ってみたいと思います。

StyleXとは

Meta社製のライブラリで、全てのスタイルに型がついており型安全なCSS-in-JSです。
また、同じくMeta社製のReactで最適に動くよう調整されているとのことです。 CSS-in-Reactではないとのことで、他のフレームワークでも動くようにはなっているとのことです。[2]

StyleX is a CSS-in-JS solution, not a CSS-in-React solution. Although StyleX has been tailored to work best with React today, it is designed to be used with any JavaScript framework that allows authoring markup in JavaScript. This includes frameworks that use JSX, template strings, etc.

また、コンポーネント数が増えてもCSSサイズが変わらないとのことなので、既存の大きめなプロジェクトなどのリプレイス候補などにもなってきそうですね!!

The CSS size plateaus even as the number of components grows

コンパイル時に静的なCSSに変換されるとのことで早さの方も期待できます!
CSSが静的なCSSに変換されるのでRSCでも動くんですね〜

All styles are bundled in a static CSS file at compile-time

実際に触ってみる

Next.jsのApp Routerで実際に触ってみます。

  1. create-next-appする[3]
npx create-next-app@latest

いろいろ聞かれるけど大体そのままエンターを押す。Typescriptだけはデフォルトで入れる選択になっているはずだけど確認する。

  1. StyleX関連のモジュールをインストール[4]
npm install --save @stylexjs/stylex
npm install --save-dev @stylexjs/nextjs-plugin
  1. .babelrc.jsnext.config.jsにプラグイン周りの設定を書く
module.exports = {
  presets: ['next/babel'],
  plugins: [
    [
      '@stylexjs/babel-plugin',
      {
        dev: process.env.NODE_ENV === 'development',
        runtimeInjection: false,
        genConditionalClasses: true,
        unstable_moduleResolution: {
          type: 'commonJS',
          rootDir: __dirname,
        },
      },
    ],
  ],
};
/** @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;

module.exports = stylexPlugin({
  rootDir,
})({});
  1. app.tsxに以下のプログラムを書いてみて赤い四角を表示する
import stylex from "@stylexjs/stylex";
const s = stylex.create({
  redbox: {
    backgroundColor: "red",
    width: 100,
    height: 100,
  },
});

export default function Home() {
  return (
    <main>
      <div className={stylex(s.redbox)}></div>
    </main>
  );
}

感想

結構簡単に導入できました。
サーバーサイドでレンダリングされているコンポーネントでCSS-in-JSを利用することができました!!!
babel周りが競合しなければ、部分的に導入するのもできそうだし、Next.jsのApprouterでCSS-in-JSを利用する選択肢の上位に入ってくるのではないでしょうか✨

参考

脚注
  1. https://nextjs.org/docs/app/building-your-application/styling/css-in-js ↩︎

  2. https://stylexjs.com/docs/learn/thinking-in-stylex/ ↩︎

  3. https://nextjs.org/docs/app/api-reference/create-next-app ↩︎

  4. https://stylexjs.com/docs/learn/installation ↩︎ ↩︎

  5. https://stylexjs.com/docs/learn/installation/#production ↩︎

  6. https://github.com/facebook/stylex/blob/main/apps/nextjs-example/next.config.js ↩︎

Discussion