CSS-in-JSのライブラリとして「emotion」を選択している理由

どうも、[sakito](https://twitter.com/__sakito__)です。

本業や副業でもReactを使っているのですが、CSS-in-JSを実現するためのライブラリとして、[emotion](https://emotion.sh/)を採用しています。
今回はemotionの紹介も交えながら、採用している理由を投稿します。

## emotionとは？
![スクリーンショット 2018-11-04 23.09.49.png](https://qiita-image-store.s3.amazonaws.com/0/108073/83f5389a-0999-bda0-4e98-b2ecca886705.png)

[emotion - Introduction](https://emotion.sh/docs/introduction)でも記載があるとおり、[glam](https://github.com/threepointone/glam/)、[glamor](https://github.com/threepointone/glamor)、[styled-components](https://www.styled-components.com/)、[glamorous](https://glamorous.rocks/)に触発された後発ライブラリです。

たとえばglamorousはpaypalが開発をしていたcss-in-jsのライブラリなのですが途中でメンテナンスが停止しました。
その理由については、[glamorousのGitHub](https://github.com/paypal/glamorous)にこのような記載があります。
> For details on the unmaintained status (and to help people with an automated migration to emotion), see #419.

記載されている#419のIssueは[Deprecate glamorous 💄 in favor of emotion 👩‍🎤](https://github.com/paypal/glamorous/issues/419)のタイトル通り、glamorousを停止しemotionに移行するというものです。
簡単に説明をすると、glamorousでできることはemotionでできるからemotionにというです。
このようにemotionでは多くのCSS-in-JSライブラリの良いところを取り入れています。

現在GitHubスター数は、5000を超えており[npm trends](https://www.npmtrends.com/emotion-vs-styled-components)で調べてみると人気のstyled-componentsに迫るダウンロード数です。
<img width="977" alt="スクリーンショット 2018-11-04 21.49.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/108073/5e4bb881-e749-c8e6-e285-4d802f28ded6.png">

最近ではReactを使用した静的サイトジェネレーターとして人気の高い[GatsbyJS](https://www.gatsbyjs.org/)の[チュートリアル](https://www.gatsbyjs.org/tutorial/)も、styled-componetsからemotionに置き換えられました。

emotionは現在v9からv10への移行をしています。
v10はまだbetaなのですが、すでに[GitHub上のドキュメント](https://github.com/emotion-js/emotion)はv10に対応しています。
現状のv9に関する情報は[ドキュメントサイト](https://emotion.sh/)を参照とのことです。


### emotionの機能

emotionは多くの機能を含んでおり、充実したライブラリです。
代表的な機能をあげたので使用方法については、ドキュメントが充実しているので参照してください。
- [CSSスタイル](https://emotion.sh/docs/css-prop)
- [Styled Componentsと同じstyledの記法](https://emotion.sh/docs/styled)
- [Composition](https://emotion.sh/docs/composition)
- [Object Styles](https://emotion.sh/docs/object-styles)
- [Typescriptサポート](https://emotion.sh/docs/typescript)、[csstype](https://github.com/frenic/csstype)によるcss構文のサポート
- [セレクターのネスト](https://emotion.sh/docs/nested)
- [Media Queriesによるレスポンシブ対応](https://emotion.sh/docs/media-queries)
- [グローバルcss対応](https://emotion.sh/docs/globals)
- [Server Side Rendering](https://emotion.sh/docs/ssr)
- [テーマの作成](https://emotion.sh/docs/theming)
- [JestでSnapshot Testing](https://emotion.sh/docs/testing)

## emotionを採用した理由
数多くのCSS-in-JSの中でなぜemotionを採用しているのか説明します。

### 機能面
冒頭でも述べたようにemotionは後発のライブラリなので、多くのCSS-in-JSのライブラリで実現できることはemotionでも実現可能です。
たとえば、Styled Componentsのような[styledの記法](https://emotion.sh/docs/styled)や[テーマの作成](https://emotion.sh/docs/theming)も実現できます。

styled記法のようにstyleを与えるコンポーネントタグを生成するだけではなく、[css記法をObject Styles機能](https://emotion.sh/docs/object-styles)でスタイルを追加することもできるのがemotionの良さです。

```js
// styledの場合
import styled from 'react-emotion'

const Button = styled('button')({
  color: '#000',
})

render(<Button>This is darkorchid.</Button>)
```

```js
// Object Stylesの場合
import { css } from 'emotion'

const className = css({
  color: '#000',
})

render(<div className={className}>This is darkorchid.</div>)
```

その他にも[awesome-css-in-js](https://github.com/tuchk4/awesome-css-in-js)にはこのような表が記載されています。
表にある通り、emotionは大抵の機能が含まれます。
<img width="841" alt="スクリーンショット 2018-11-04 22.12.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/108073/bc4d8743-4f84-837c-58af-1e154d1612fe.png">

表ではReact Nativeのサポートにチェックがありませんが、すでに[こちらのPR](https://github.com/emotion-js/emotion/pull/658)でReact Nativeの対応がマージされているので、オールチェックになります👏


### 実行速度
[CSS-IN-JS-Benchmarks](https://github.com/A-gambit/CSS-IN-JS-Benchmarks)にこのような[表](https://github.com/A-gambit/CSS-IN-JS-Benchmarks/blob/master/RESULT.md)が記載されています。
Mount TimeとRerender timeを計測した結果ですが、[emotionのcssをObject Stylesで割当てたソース](https://github.com/A-gambit/CSS-IN-JS-Benchmarks/tree/master/packages/benchmarks/emotion/css-mode)では上位の結果になっています。

<img width="630" alt="スクリーンショット 2018-11-04 22.20.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/108073/6ed90875-b7ff-444f-df6c-e68f269a5764.png">

[emotionでstyledを使用したソース](https://github.com/A-gambit/CSS-IN-JS-Benchmarks/tree/master/packages/benchmarks/emotion/simple)と[styled-componentsを使用したソース](https://github.com/A-gambit/CSS-IN-JS-Benchmarks/tree/master/packages/benchmarks/styled-components/simple/client)の結果を比べてもemotionの方が上位です。

### ファイルサイズ
最後にファイルサイズを比較します。
こちらの[styled-components-vs-emotion](https://github.com/jsjoeio/styled-components-vs-emotion)にこのような表が記載されています。
Sizeの項目に注目すると微差ながらemotionのサイズが小さいということが分かります。
<img width="628" alt="スクリーンショット 2018-11-04 22.32.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/108073/0cd08eb7-22ca-dda7-0709-5577d8250b21.png">


## 最後に
これらの比較はstyled-componets v3のときの比較です。
現在styled-componetsはv4になり、[Releasing styled-components v4 final](https://medium.com/styled-components/styled-components-v4-new-final-finalest-for-real-final-final-psd-fa4d83398a77)を参照する限り、かなりの
パフォーマンス向上が果たされたと思われます。
しかし、emotionもv10の開発を行なっているので期待したいところです。

emotionを採用するかどうかは記法の好みにもあるかと思います。
チームで話し合った上でemotionのcss記法が好みであれば採用してもよいと思います。


これでよりemotionの認知が広まればいいな〜〜〜というお気持ちです。