初めに
この記事は、DMMグループAdvent Calendar 2021の8日目の記事です
こんにちは。動画配信事業部でフロントエンドエンジニアをしている今西勇太@nisshiiです。
2021年新卒として入社し、研修を経て、現在は動画再生用のプレイヤーを作っています。
この記事では、新卒研修のチーム開発演習をやっていくにあたって、Linariaというライブラリを用いて良い感じにCSS in JS した際にハマったポイントや感じたことを書いていきます。
ここでは触れないこと
DMMの新卒研修について
研修のカリキュラムについてはこちらをご覧ください
チーム開発演習をどう進めていったのかについては、同期が今夜登壇するので是非チェックしていただければ!
スタイル表現の選択肢、結局どれがいいの問題
個人的にはケースバイケース派(規模による)です。ただ、今回のテーマと合わせてしまうと話がブレるので触れません。
LinariaはCSS in JS (特にstyled-componentとほぼ同列に並べられる) に該当するものなので、そのメリット・デメリットについては触れます。以下、目次です。
前提:CSS in JS とは
(知ってるよーという方は読み飛ばしていただいて大丈夫です)
CSS in JS とは、一言で言うと文字通りスタイルの表現をjs側で行うものです。
詳細は省きますが、嬉しい点としては基本的に1ファイルで1つのコンポーネントとして管理することができるようになります。
個人的に、コンポーネントの数が多くなった場合、実装時に開いて読むファイルの数が少なくて済めば済むほど開発効率は上がると考えています。
なので、いわゆるAtomic Designのような設計を取り入れる際にはCSS in JSを選択した方が良いと考えています。
また、ロジック側からスタイル側へ気軽に変数(props)を渡せるのも、柔軟なスタイル表現に威力を発揮します。
Linaria がしてくれること
CSS in JS の大きな問題の1つが、スタイルとロジックが混ざったjsファイルが生成されてしまうということです。
何が辛いかと言うと、スタイルに関係するCSSOM Treeを構築するステップの手前に、ロジックが混ざったjsのScriptingのステップを挟む必要が出てきてしまい、いわゆるブロッキング状態が起こらざるを得なくなってしまう点です。
その点、CSS Modulesをはじめとするcssファイルの形で配信する形式であれば、初めからcssファイルとして分かれて作成しているので、上記のような辛さは起こりません。
Linariaをはじめとするzero runtime CSS in JSなライブラリ達はこの辛さを解決してくれます。
どう解決してくれるかと言うと、ビルド時にスタイルとロジックが混ざったjsファイルを読み、その中からスタイル定義部分を抽出してcssファイルとして生成する、ということをしてくれます。
このおかげで、こういったパターンでのロジックを担うjsファイルによるブロッキングは起こりません。
また、生成されたcssファイルを適宜chunkしたり、それらをキャッシュしておくことで、より効率のいい配信が可能になります。
Linaria の導入とハマりポイント
導入自体はパッケージをインストールして、webpackなどの設定を書けば動きます。簡単。
各バンドラー向けにも設定例を書いてくれています。良心的。
(Ie11はサポートされてません。今時。)
公式ドキュメントのバンドラー設定はjavascriptの場合しか書かれていないですが、typescriptなプロジェクトで使う場合でもこんな感じで@linaria/webpack-loader
に通す前にts-loader等に通せば問題なく動きます。
{ test: /\.tsx?$/, exclude: /node_modules/, use: [ { loader: '@linaria/webpack-loader' }, { loader: 'ts-loader', options: { loader: 'tsx' } } ] },
これまでLinariaの便利なところを紹介してきましたが、欠点もあります。それは、当たり前の話ですがビルド時間が長くなってしまう点です。
スタイルを抽出する工程が含まっているので当然ですね。
ここで自分は、ビルド時間の短縮を求めてts-loader
の代わりにesbuild-loader
を使おうとしてハマりました。
具体的には、それまで出来ていて開発体験の向上につながっていたHMRが上手く効かなくなってしまいました。
これ自体はesbuild側の問題でLinariaの設定からはどうしようもなく、詰んでしまいました…。
より開発体験を良くするには
前章でビルド高速化のためにesbuild-loader
を入れようとしてHMRできなくなった話を書きました。
ただ、Linariaを使うこともビルド高速化もHMRも諦めたくないと思って解決策を探していたところ、以下のOSSを見つけました。感謝!
こちらは、Linariaのvite向けプラグインです。
viteならばビルド時間の高速化もHMRも満たせます。
ちなみに設定例はこんな感じです。
import reactRefresh from '@vitejs/plugin-react-refresh'; import { defineConfig } from 'vite'; import path from 'path'; import VitePluginLinaria from 'vite-plugin-linaria'; export default defineConfig({ plugins: [ reactRefresh(), VitePluginLinaria(), ], resolve: { alias: [ { find: '@', replacement: path.join(__dirname, 'src') } ] }, build: { sourcemap: true, outDir: 'build' } });
おかげでチーム開発演習の期間、CSS in JSの書き心地を維持しつつ、HMRと高速なビルドによる開発体験も維持しつつ、cssファイルとして生成し適宜キャッシュすることでパフォーマンスも高水準で維持できました。
まとめと余談
以上、Linariaでパフォーマンス面をケアしつつ、CSS in JSする環境を整えた話でした。
Linariaで実サービスを開発するタイミングがこの先いつ来るかは分かりませんが、個人的にはとても未来のあるライブラリだと思っているので今後も注視していきたいです。
余ったスペースで、弊社の最高すぎる福利厚生制度の紹介をします。
それがこちら、Tech12 というものです。
こちらは文字通り、社員の「Tech」な分野での自己研鑽に関わる費用(書籍、ガジェット、勉強会参加費などなど) を、1人あたり月に1万円まで、1年間で「12」万円までを会社が補助してくれるという制度です。
この制度を使って、自分はLGの4Kモニターを買いました。作業が捗ります!
32インチ大きい!よい!! pic.twitter.com/jA8rNkGoR4
— ††にっしー†† (@nisshii0313) November 27, 2021