Next.jsにEmotionを導入してみる

業務でCSS in JSを利用する際はstyled-componentsを採用することが多かったのですが、CSSを当てるコンポーネントの要素名が変わってしまうため「Reactコンポーネントとして用意されたものなのか、単にスタイルを当てただけなのか」の区別が付きづらく、ちょっとコードの見通しが悪いと感じていました。

公式から引用↓

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

render(
  <Wrapper>
    {/* 「Title.tsx」のようなコンポーネントが別に存在するのかな?という見た目になる…… */}
    <Title>
      Hello World!
    </Title>
  </Wrapper>
)

そこで、コンポーネントの名前を変えずに近い使用感で利用できるEmotionを使ってみることにしました。単純に触ってみたかっただけとも言います。

上記のコードをEmotionで書くと、

const Title = css`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

const Wrapper = css`
  padding: 4em;
  background: papayawhip;
`;

render(
  <div css={Title}>
    <h1 css={Wrapper}>
      Hello World!
    </h1>
    {/* コンポーネントと、スタイルを当てているだけの要素との見分けが付きやすい */}
    <HogeComponent />
  </div>
)

このようになります。好みが分かれるかもしれませんが、個人的にはこちらのほうがわかりやすく感じます。

何番煎じかわかりませんが、今回はEmotionをNext.jsに導入する際の備忘録です。

環境

  • Next.js 12.1.5
  • Emotion 11.9.0
  • TypeScript 4.6.3

パッケージの導入

npx create-next-app@latest --tsでTypeScriptテンプレートをインストールした前提です。

Emotionをインストール

yarn add @emotion/react @emotion/babel-plugin

2つ目のbabelプラグインを導入するのは、Emotion固有の書き方であるcss propに対応させるためです(公式)。

//  こういうの
<h1 css={styles}>hoge<h1>

さらに、プロジェクトに.babelrcを追加します。Next.js利用時の設定も上記の公式ページに記載してくれています。親切!

  • .babelrc
{
  "presets": [
    [
      "@babel/preset-react",
      { "runtime": "automatic", "importSource": "@emotion/react" }
    ]
  ],
  "plugins": ["@emotion/babel-plugin"]
}

なお、create-react-appを利用している場合などbabelの設定変更ができない環境では、JSX Pragmaを用いて対応できるようです。ただし、毎回独自コメントの記載が必要になるので少々面倒です。

TypeScript向けに設定

TypeScriptの利用時はcss propの型定義がないと怒られてしまうので、追加します。

  • .tsconfig.json
{
  "compilerOptions": {
    // 略
    "jsxImportSource": "@emotion/react",
  },
  // 略
}

以上で導入は完了です!

Next.jsの公式に記載がありますが、Emotion(styled-componentsでも同様)の利用時はnext/linkを使う際にpassHrefが必要になります。

また、css propを付与するのはLink配下の要素となるため注意しましょう。 毎回書くのは面倒なので、ラップするだけのコンポーネントを作ってあげるとよいと思います。

<Link href="/hoge" passHref>
  <a css={hogeStyles}>リンク</a>
</Link>

おわりに

Emotionはまだ使い始めたばかりですが、なかなか使い勝手がいいです。 今後またEmotionに関する内容を記事にするかもしれません!

Copyright © 2021-2022 tama All Rights Reserved.