🌳

Gatsby.js + TypeScript + linaria で環境構築

2021/09/05に公開

以前まで、Emotion を用いてGatsby.jsを使っていたのですが、
iricoさんの「ReactのCSSの選択肢を比較してみた」という記事を読んで、linariaに興味を持ち始めました。
zero runtimeとのことで、パフォーマンス向上が期待できるのは嬉しい点です。

https://linaria.dev/

今回は、linariaGatsbyの組み合わせでの記事が少なかったので忘備録としてこの記事を残します。

今回のコードは、下記リポジトリに保存してあります。何かあった時には参考になればと思います。
https://github.com/tsuki-lab/gatsby-typescript-linaria-sample

この記事は以下のバージョン時点の情報です。

  • gatsby: 3.13.0
  • linaria: 2.1.0
  • gatsby-plugin-linaria: 3.0.0

0.プロジェクトの作成

npx gatsby new gatsby-typescript-linaria-sample

1.typescriptの追加

typescriptのインストールとtsconfig.jsonを作成します。

yarn add -D typescript @types/react-helmet
yarn tsc --init

tsconfig.jsonは以下のように設定してあります。

🔗 tsconfig.json

tsconfig.json
{
  "include": ["./src/**/*"],
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "lib": ["dom", "es2017"],
    "jsx": "react",
    "strict": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "noEmit": true,
    "skipLibCheck": true,
    "moduleResolution": "node"
  }
}

2.各コンポーネントファイルのTypeScript化

各コンポーネントのファイル拡張子を.jsから.tsxに書き換えていきます。

一例として、src/pages/index.tsxは以下のようになります。

🔗 src/pages/index.tsx

src/pages/index.tsx
import * as React from "react"
import { Link, PageProps } from "gatsby"
import { StaticImage } from "gatsby-plugin-image"

import Layout from "../components/layout"
import Seo from "../components/seo"

const IndexPage: React.FC<PageProps> = () => (
  <Layout>
    <Seo title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <StaticImage
      src="../images/gatsby-astronaut.png"
      width={300}
      quality={95}
      formats={["auto", "webp", "avif"]}
      alt="A Gatsby astronaut"
      style={{ marginBottom: `1.45rem` }}
    />
    <p>
      <Link to="/page-2/">Go to page 2</Link> <br />
      <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
    </p>
  </Layout>
)

export default IndexPage

3.linariaをインストール

linaria本体と、gatsbyのプラグインとして提供されているgatsby-plugin-linariaをインストールします。

yarn add linaria gatsby-plugin-linaria gatsby-plugin-typescript

4..linaria-cacheを.gitignoreする

linariaは中間cssファイルとして.linaria-cacheフォルダにcacheを溜めておく機能があります。
これはgitにpushする必要がない情報なので、.gitignoreに追記します。

🔗 .gitignore

.gitignore
.linaria-cache

5.gatsby-plugin-linariaを適応させる

.gatsby-configファイルのプラグインにgatsby-plugin-linariaを追加します。

🔗 gatsby-config.js

gatsby-config.js
module.exports = {
  // ...
  plugin: [
    // ...
    `gatsby-plugin-typescript`,
    `gatsby-plugin-linaria`,
  ]
}

6.linariaでスタイリングをする。

今回はsrc/componetns/layout.tsx内に記載されているstyle属性を置き換えていきたいと思います。

私は、styleを分割したいタイプなのでsrc/componetns/layout.styles.tsを作成します。

🔗 src/componetns/layout.tsx

src/componetns/layout.tsx
  import * as React from "react"
  import PropTypes from "prop-types"
  import { useStaticQuery, graphql } from "gatsby"

  import Header from "./header"
  import "./layout.css"
+ import * as styles from './layout.styles'

  const Layout: React.FC = ({ children }) => {
    const data = useStaticQuery(graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `)
 
    return (
      <>
        <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
+       <div className={styles.container}>
-       <div
-         style={{
-           margin: `0 auto`,
-           maxWidth: 960,
-           padding: `0 1.0875rem 1.45rem`,
-         }}
-       >
          <main>{children}</main>
+         <footer className={styles.footer}>
-         <footer
-           style={{
-             marginTop: `2rem`,
-           }}
-         >
            © {new Date().getFullYear()}, Built with
            {` `}
            <a href="https://www.gatsbyjs.com">Gatsby</a>
          </footer>
        </div>
      </>
    )
  }

  Layout.propTypes = {
    children: PropTypes.node.isRequired,
  }

  export default Layout

🔗 src/components/layout.styles.ts

src/componetns/layout.styles.ts
  import { css } from 'linaria'

  export const container = css`
    margin: 0 auto;
    max-width: 960px;
    padding: 0 1.0875rem 1.45rem;
  `

  export const footer = css`
    margin-top: 2rem;
  `

終わりに

以上が、「Gatsby.js + TypeScript + linaria で環境構築」でした。
Emotionstyled-componentsと記法が基本的に変わらず、import部分さえ置き換えれば大体のコンバートができそうなので置き換えも比較的簡単にできそうです。

参考

Discussion