emotion v10 になって変わったこと

CSS-in-JS ライブラリの emotion が v10 から、だいぶ使い方が変わっていました。

package の変更

v9 では emotion package を import していました。

import { css } from "emotion"

v10 では React を使っている場合は @emotion/core を、それ以外の場合は emotion を import するようになっています。 (後述しますが React も emotion package を利用することも可能です)

https://emotion.sh/docs/install

React の場合

/** @jsx jsx */
import { jsx, css } from "@emotion/core"

const style = css`
  color: red;
`;

function Foo() {
  return (
    <div css={style}>
      <p>Foo Component</p>
    </div>
  );
}

それ以外の場合

import { css } from "emotion"

const style = css`
  color: red;
`;
const foo = document.querySelector(".foo");
foo.classList.add(style);

@emotion/core について

emotion は css で定義した style を class 名に指定することで css を適用可能で、利用しているライブラリ(React や Vue)への依存を少なくできる点が特徴的でした。
しかし v10 からは React の場合 @emotion/core という別 package を利用することになってしまいました。 この理由ですが、Server Side Rendering (SSR) を行う際の手間を省略するためのようです。

React では @emotion/core から jsxcss の2つを import したうえで /** @jsx jsx */ という JSX Pragma を記載します。

/** @jsx jsx */
import { jsx, css } from "@emotion/core"

この JSX Pragma は、JSX をコンパイルする際に利用する関数を変更するマジックコメントです。 初期値は React.createElement になっています。

emotion v10 では、JSX の処理を自前の jsx で行うことで css prop に指定された style を処理しています。
React.ceateElement の差し替えは少し不安になりますが、これによって Server Side Rendering を行う際に、style を別で処理する必要を無くしたようです。

import { renderToString } from 'react-dom/server';
import App from './App'

let html = renderToString(<App />)

https://emotion.sh/docs/ssr より引用

一方で、vanilla Emotion を利用した場合の Server Side Rendering の方法も記載されています。

import { renderStylesToString } from 'emotion-server'
import { cache } from 'emotion'
import { CacheProvider } from '@emotion/core'
import { renderToString } from 'react-dom/server'

let element = (
  <CacheProvider value={cache}>
    <App />
  </CacheProvider>
)

let html = renderStylesToString(renderToString(element))

https://emotion.sh/docs/ssr より引用

ということで、emotion v10 で React でも引き続き emotion package の css で作成した style を className prop に指定する方法が使えるみたいです。

まとめ

  • emotion v10 から用途に合わせて package が分割
    • React では @emotion/core or emotion
    • それ以外では emotion
  • @emotion/core では JSX Pragma を利用して css prop の処理を JSX と一緒に行う
    • Server Side Rendering を行う際に style の処理を気にしなくて良い