📘

StyleXはvanilla-extractを諦めた我々の光になるか?

2023/12/12に公開1

プロローグ

私は新規のプロジェクトを立ち上げるときにVanilla-Extractを採用しました。
型安全なCSSがかけることやスコープをもたせることができ、管理画面のような肥大化しやすいプロジェクトでの導入が望ましいと考えたためです。
しかし、この考えは現在打ち砕かれてしまいました。
泣く泣くVanilla-Extractの導入を諦めSASSでの開発をしていたときStyleXのリリースのニュースが飛び込んで来たのです。
https://stylexjs.com/blog/introducing-stylex/

Type-Safeで再利用可能であり、静的なCSSのパフォーマンスとスケーラビリティを手に入れられるとのこと。
これを逃すわけにはいきません。早速詳細を確かめ、次回新規プロジェクトが立ち上げるときに候補にできるのかを確かめましょう。

概要

この記事ではVanilla-Extractで問題だったことを振り返りつつ、StyleXではどのような構文が採用されVanilla-Extractとの違いに触れます。

技術選定の際にVanilla-ExtractとStyleXどちらを採用するのか迷ったときの一助になるといいなと思います。

Vanilla-Extractとの出会いと別れ

Nextjsに導入したVanilla-Extractと半ば喧嘩別れのような別れを経験しました。
何が問題だったのかを完結に記すと【SSRした画面で差分描画した要素にスタイルが適応されない】でした。

これは何が原因なのかというと主にNextjsのWebpackの設定によるものです。
差分で描画した要素にはインライン要素が追加されるのが期待する動きですが、Webpack側でCSSがインポートされず結果として差分の要素にはCSSが当たっていないように見えてしまいます。
この不具合はPage Router/App Routerともに報告されておりフォーラムが建てられていますが未だに解決に対してポジティブな進捗がない状況です。
https://github.com/vanilla-extract-css/vanilla-extract/issues/1088

このような状況からVanilla-Extractでの開発を断念しました。
Type-Safeでコンポーネントごとのスタイルを隠蔽して再利用することに夢にみていましたが断念せざるを得ませんでした。

Vanilla-ExtractとStyleXは何がちがうのか

Vanilla-ExtractはインラインスタイルのCSSを採用していますが、StyleXはCSS Modulesのような存在です。
また、Vanilla-Extractではアトミックビルドとファイルレベルビルドのキャッシュは存在しませんがStyleXではキャッシュを活用できるためビルドの面で高速です。
またStyleXはアトミックなCSSクラス名を生成することでCSSのバンドルサイズをを最小限に抑えることができます。
この点Vanilla-Extractではそのままのクラス名が引き継がれるためこのようにはなりません。

StyleXはどのような構文でCSSが採用されているのか

Nextjsで使うことを想定しています。以下の設定で動きます。
Babel周りの設定が必要ですがそこまで設定が大変ではないのでいいですね。

$ npm install --save-dev @stylexjs/nextjs-plugin
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,
        },
      },
    ],
  ],
};
const stylexPlugin = require('@stylexjs/nextjs-plugin');

module.exports = stylexPlugin({
  rootDir: __dirname,
})({});

stylex.createを使ってスタイルを生成できます。
stylexのインターフェースは非常にシンプルでわかりやすいのが特徴の一つです。複雑な新しいことを覚えることなく比較的基本的なCSSの知識でスタイルを作っていくことが可能です。

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

const styles = stylex.create({
  base: {
    fontSize: 16,
    lineHeight: 1.5,
    color: 'rgb(60,60,60)',
  },
  highlighted: {
    color: 'rebeccapurple',
  },
});

https://stylexjs.com/docs/learn/styling-ui/defining-styles/

ローカル環境でのみの検証でしたが、Vanilla-Extractで出た問題は出ませんでした。
これは次回の技術選定に光明が見えそうです。

まとめ

Vanilla-ExtractとStyleXの違いはインラインスタイルなのか、CSS Modulesのような存在である点です。

StyleXがVanilla-Extractに比べ優位な点は以下3つです。

  • 描画フレームワークに依存しない
  • SSR FRIENDLY
  • ロードタイム、ランタイムともにベンチマークの面ではやい

StyleXは

  • Babelプラグイン
  • 小さなランタイム ライブラリ
  • ESlint プラグイン
    この辺りが動くようになっており、最低限開発に必要なものがそろっているのもありがたい点です。

次回の技術選定の際にはStyleXをぜひ採用して夢に見たType-Safeで高速なCSSを体感したいですね。

株式会社ZOZO

Discussion

りんたろーりんたろー

初めまして!StyleXについての記事があまり無いためとても興味深く拝見させてもらいました!

Vanilla-extractのcssが重複して生成されバンドルされる問題なのですが、どうやら次のリリースで修正されるそうです。もしかしたらremさんの「SSRした画面で差分描画した要素にスタイルが適応されない」問題もこれで解決されるかも?しれないです。

ref: https://github.com/vercel/next.js/pull/61198
ref: https://github.com/vercel/next.js/issues/42082