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

Chrome拡張機能向けの内容です。
ビルドツールはviteを使用しています。

要約

vanilla-extractは

  • ビルド時にcssファイルを生成してくれるのでパフォーマンスが他のcss-in-jsライブラリよりも魅力的だった
  • 型安全でプロパティの構文エラーをエディタで見ることができる
  • CssModulesから乗り換えるメリットを感じた

1. 背景

業務でChrome拡張機能をノーフレームワークで開発しています。

ノーフレームワークのプロジェクトでcssファイルを以下のようなtsファイルで管理していました。

css.ts
export const css = `<style>
.className {
    margin-top: 1rem;
    float: left;
}
</style>`

これだと以下の問題があります

  • cssの記法が誤っている場合にエディタで気づきづらい
  • トランスパイルの対象となり、型チェック、バンドルの時間が余分にかかる
  • CSSのグローバルスコープ問題

1.1. CssModulesの課題

前にCssModulesの調査をしましたが、以下の問題がありました。

typed-css-modules

毎回cssファイルが作成されるごとに型定義ファイルを作成する手間がある

viteのCssModulesの型定義

存在しないスタイルのプロパティにアクセスしてもエディタ上でエラーにならない

1.2. vanilla-extractを知った

以下のイベントでvanilla-extractの存在を知りましたので調査します。

2. そもそもcss-in-jsとは

外部ファイルでスタイルを定義するのではなく、
JavaScriptを用いて CSSを記述するために設計されたライブラリのことです。
CSS in JSを利用することで、コンポーネント内にCSSを定義することができ、
外部のCSSファイルに依存することなく、コンポーネント単体で独立させることができます。

2.1. 問題点

css-in-jsの仕組みは以下です。

JavaScriptオブジェクトで作成された動的なCSSオブジェクトをランタイムで<style />タグに挿入する
JavaScriptで作成したCSSオブジェクトをタグにinsert可能な形式にするために、シリアライズと呼ばれる処理を施す必要があります

これにより以下の問題点があります。

コンポーネントのレンダリングの度にランタイムでスタイルのシリアライズ処理と挿入処理を行う必要があるためにどうしてもパフォーマンスのオーバーヘッドがあります

3. vanilla-extractとは

npm trends
image.png

Use TypeScript as your preprocessor. Write type‑safe, locally scoped classes, variables and themes, then generate static CSS files at build time.

型安全でローカルにスコープされたクラス、変数、テーマを記述

colorrを消して存在しないプロパティ名coloにすると以下のようにエディタでエラーが表示されます。
image.png

TypeScriptをプリプロセッサとして使用し、ビルド時に静的なCSSファイルを生成

ビルド時に静的なCSSファイルを生成してくれるので従来のcss-in-jsよりもランタイムパフォーマンスが向上します。

4. vanilla-extractをVite,ノーフレームワークのChrome拡張機能で使ってみる

4.1. vanilla-extractをinstall

npm install @vanilla-extract/css

4.2. style.css.ts(styleという命名は例)ファイルを作成する

vanilla-extractでは.css.tsという拡張子でcssを管理します。
これがビルド時にcssファイルに変換されます。

style.css.ts
import { style } from '@vanilla-extract/css';

export const button = style({
  color: 'red'
});
call.ts
import { button } from "../css/styles.css";
export const btnAreaElm = `<button type="button" class=${button}></button>`

これだけだと使えません。

image.png

content_scriptファイルでエラーになります。

4.3. viteのプラグインを設定

viteのプラグインを設定しないとcssファイルに変換してくれないということでした。

4.3.1 viteのプラグインをinstall

npm i --save-dev @vanilla-extract/vite-plugin
npm install --save-dev @vanilla-extract/vite-plugin
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: iimon-chrome@1.0.0
npm ERR! Found: vite@3.2.10
npm ERR! node_modules/vite
npm ERR!   dev vite@"^3.2.7" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer vite@"^4.0.3 || ^5.0.0" from @vanilla-extract/vite-plugin@4.0.7
npm ERR! node_modules/@vanilla-extract/vite-plugin
npm ERR!   dev @vanilla-extract/vite-plugin@"*" from the root project
npm ERR!

viteは4.0.3以降のものでないとエラーになります。

npm i vite@4.0.3

4.3.2 vite.config.tsに設定

vite.config.ts
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';

export default {
  plugins: [vanillaExtractPlugin()]
};

4.3.3. viteのrollupOptions.output.assetFileNamesのファイル名を固定

vite.config.ts
rollupOptions: {
    output: {
        ~~~~~~,
        assetFileNames: "override.css"
    },
}

4.3.4. cssをサイトに注入

manifest.json
"content_scripts": [
        {"css": ["override.css"]}
]

4.3.5. ブラウザで見てみる

自動的にrandom文字列が付与されていました。
ローカルスコープになっています。

image.png

image.png

5. 応用

5.1. セレクタにprefixを設定

vite.config.ts

const makeRandomStr = () =>{/* ランダム文字列生成 */ return 'prefix_'}

vanillaExtractPlugin({
      identifiers: ({ hash }) => `${makeRandomStr()}${hash}`
    })

以下のようにprefix_がセレクタについていることが確認できます

.prefix_1hmbdbt0 {
  color: red;
}

6. その他メリット

こちらの記事でメリットを紹介されていましたのでご覧ください

6.1. CSS変数が使える

theme.css.ts
import { createTheme } from '@vanilla-extract/css';

export const [themeClass, vars] = createTheme({
  color: {
    brand: 'blue'
  },
  font: {
    body: 'arial'
  }
});
button.css.ts
import { vars } from "../css/theme.css";

export const button = style({
    color: vars.color.brand,
    fontFamily: vars.font.body,
});

7. 最後に

  • 「トランスパイルの対象となり、型チェック、バンドルの時間が余分にかかる」というのは解消されませんが他2つの問題点は解消されました
  • 前回調査した際のCssModulesの問題点を解消かつ、プロパティのチェックをしてくれるのはありがたいなと思いました
  • Linariaについても調査したいと思います

本記事を読んで頂き、ありがとうございました。
いいねいただけると記事執筆の励みになりますので、参考になったと思われた方は是非よろしくお願い致します🙏

弊社は積極採用活動中です。
もし気になっていただけたら採用ページまでよろしくお願いします。

8. 参考

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