水無瀬のプログラミング日記

Next.js+linariaを試してみる

はじめに

linariaを使ってみたかったのでNextjsと一緒に使ってみる。

TL;DR

今回のコード

前提

create-next-app --tsでNext.jsのテンプレートが出来上がっている状態。

インストール

必要なライブラリのインストールから始める

# next-linariaのreadmeの通りにinstall
$ yarn add next-linaria linaria
# next-linariaの依存のwebpack-loaderの依存のwebpack(4|5)-loaderの依存に@babel/coreが居て
# 入っていないと動かすときに怒られるため追加。
$ yarn add -D @babel/core

試しに起動してみる(yarn dev)と以下のエラーで落ちる。

error - ./pages/_app.tsx:2:12
Syntax error: Unexpected token

  1 | import '../styles/globals.css'
> 2 | import type { AppProps } from 'next/app'
    |             ^
  3 |
  4 | function MyApp({ Component, pageProps }: AppProps) {
  5 |   return <Component {...pageProps} />

このエラーは下記issueと同じ状態。
Syntax error: Unexpected token · Issue #6 · Mistereo/next-linaria
で、それの回答が下記issue。 How to use with NextJS + typescript? · Issue #795 · callstack/linaria

Then add this to your babel config: presets: ['@linaria'] and wrap your next.config.js options with the default export from next-linaria withLinaria()

つまりbabelのpresetsにlinariaのpresetを追加すれば良いとのこと。
回答では@linariaと書かれているが、今インストールしているlinariaベースで書くのであればlinaria/babelと記載すればOK。(@linariaを追加しても動く)
presetsの設定を入れる場合は入れたいものとNext.jsが必要としているpreset(next/babel)も入れる必要がある。

module.exports = {
  presets: ["next/babel", "linaria/babel"], 
}

この状態で起動しエラーが出なければOK。

linariaを使ってみる

実際に使ってみる。
試しに作ったコードは下記の通り。

import type { NextPage } from 'next'
import Head from 'next/head'
import { css } from 'linaria';
import { styled } from 'linaria/react';
import { useState } from 'react';

const color = {
  black: '#000'
} as const;

// cssを定義して使える
const MainStyle = css`
  display: flex;
  flex-direction: column;
  align-items: center;
`;

// 変数の参照もできる
const TitleStyle = css`
  color: ${color.black};
  font-weight: 700;
  font-size: 20px;
`;

// styled-componentsの様な書き方もできる
const Paragraph = styled.p`
  color: #333;
  font-size: 16px;
`;

// propsも受け取れる
const Button = styled.button<{isDisabled: boolean}>`
  background-color: ${props => props.isDisabled ? '#999' : '#fff'};
`;

const Home: NextPage = () => {
  const [isGray, setGray] = useState(false);
  return (
    <>
      <Head>
        <title>Next.js + Linaria sample</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={MainStyle}>
        <h1 className={TitleStyle}>Next.js + Linaria sample</h1>
        <Paragraph>サンプル</Paragraph>
        <Button isDisabled={isGray} onClick={() => setGray((before) => !before)} >ボタン</Button>
      </main>
    </>
  )
}

export default Home

起動できボタンクリックするたびに色が変わればOK。

まとめ

今回はlinariaを触ってみた。
css書くときはstyled-componentsを使うことが多かったが、同じ様な記法が使えるため切り替えることで覚え直しみたいなのは余りなさそうだった。
css-in-jsはパフォーマンスの懸念があるので乗せ換えられるのであれば乗せ換えてしまった方が良さそうではある。
ただし、一部IE11をサポートしていない機能があるため万が一IE11をターゲットにするのであれば注意が必要そう。 https://github.com/callstack/linaria#trade-offs

参考リンク