24
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Next.js周りのボイラープレート(Typescript + Jest + Storybook + ESLint + Prettier + styled-components)

Last updated at Posted at 2020-01-25

趣味で最近Next.jsを触っています。
業務ではReactを扱うことがあるのですが、タイトルに載せているような、普段業務で使っているライブラリの入れ方がまとまっているところはなかったので、まとめてみました。

尚、本記事で扱うライブラリのバージョンは以下のようになっています。

  • yarn 1.22.15
  • Next.js 11.1.2
  • React 17.0.2
  • Typescript 4.4.3
  • Jest 27.2.4
  • Storybook 6.3.9
  • ESLint 7.32.0
  • Prettier 2.4.1
  • styled-components 5.3.1

プロジェクト作成(with Next.js, ESLint, Typescript)

以前はNextを個別に入れる形になっていたのですが、現在Next.jsの方からテンプレートが提供されています。
これにはNext.js / ReactだけでなくESLintも入っています。(以前はESLintが色々大変だった……)
しかもTypescriptも最初から入っているものも提供されています。

yarn create next-app --typescript

Next.jsの起動

上記手順を行うと package.json にいくつかのnpm scriptsが登録されています。

package.json
"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
}

yarn devと打ってlocalhost:3000でNext.jsのサーバーが立っていれば成功です。

個人的な好みもあるのですが、ソースファイルは src ディレクトリ以下に置きたいと思っています。
公式でこちら対応されており、必要なディレクトリを移動させるだけです。

mkdir src
mv pages src
mv styles src

Typescript

基本的な設定(必要なライブラリのインストール, 設定ファイルの作成)は最初の手順で行われています。
個人の好みもありますが、Typescriptの恩恵をフルで受けるためにtsconfig.jsonの以下のフィールドを変更します。

// true -> false に変更
"allowJS": false

Jest

Typescript環境下でJestを動かす方法はいくつかありますが、ts-jestを使います。
必要なライブラリをインストールします。

yarn add -D jest  ts-jest @types/jest

Jestの実行に必要なファイルを生成します。

yarn ts-jest config:init

jest.config.jsが出力されているはずです。
確認のためにテスト用のファイルを作ります。

mkdir src/util
src/util/sum.ts
const sum = (a: number, b: number) => a + b;

export { sum };
src/util/sum.test.ts
import { sum } from "./sum";

test("adds 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe(3);
});

Jestを動かせるようにpackage.jsonを変更します。

package.json
"scripts": {
    "test": "jest"
}

テストを動かしてみます。

yarn test

テストが動いて通っていることが確認できました。

Storybook

Storybookの公式ページを参考にしています。
以前は必要なライブラリを個別にインストールする形だったのですが、公式からプロジェクトの構成を判別してライブラリ・設定ファイルを生成してくれるスクリプトが用意されています。

npx sb init

storybookを動かすコマンドがscriptsに記載されています。

package.json
"scripts": {
  "storybook": "start-storybook -p 6006",
  "build-storybook": "build-storybook"
}

また、storybookのconfigファイルも自動生成されています。
(昔はwebpack.config.jsとか自分で書く必要があって大変だった……)

賢いことに src ディレクトリの有無で生成するconfigが変わっています。
今回紹介するのは src ディレクトリ付きです。

mkdir .storybook
..storybook/main.js
module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
  ]
}
..storybook/preview.js
export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

上記コマンドでサンプル用のファイルが作成されているのですが、せっかくなので新規でstory用のファイルを作成します。

mkdir src/components
src/components/Text.tsx
type Props = {
  text: string;
};

const Text = ({ text }: Props) => <span>{text}</span>;

export { Text };
src/components/Text.stories.tsx
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Text } from './Text'

export default {
  title: 'Text',
  component: Text,
  argTypes: {
    text: {
      control: { type: 'text' },
    },
  },
} as ComponentMeta<typeof Text>

const Template: ComponentStory<typeof Text> = (args) => <Text {...args} />

export const HelloText = Template.bind({})
HelloText.args = {
  text: 'hello!',
}

yarn storybookとコマンドを打ってStorybookが立ち上がります。
また、staticなファイルを生成したい場合は yarn build-storybookstorybook-static ディレクトリ配下に生成されます。

ESLint

最初のプロジェクト生成で必要なものが生成されます。

package.json
{
  "scripts": {
    "lint": "next lint"
  },
  "devDependencies": {
    "eslint": "7.32.0",
    "eslint-config-next": "11.1.2",
  }
}
.eslintrc.json
{
  "extends": "next/core-web-vitals"
}

これによって設定されるルールは公式のこのページに書かれています。

Prettier

必要なライブラリをインストールします。

yarn add -D prettier --exact

--exactは公式で推奨されているので付けています。

フォーマットしやすいようにコマンドを書きます。

package.json
"scripts": {
  "format": "prettier --write src/**/*.{ts,tsx}"
}

prettierの設定ファイルを書きます。
今回はnext.jsが使っているものをベースに個人的な好みの trailingComma: es5 を追加します。

.prettierrc
{
  // 上2つはnext.jsのリポジトリのものと同一です
  "singleQuote": true,
  "semi": false,
  "trailingComma": "es5"
}

styled-components

Next.jsでCSSを使う方法はいくつかありますが、私は業務で使っていたstyled-componentsに慣れていたので、それを使えるようにセットアップします。

必要なライブラリをインストールします。

yarn add styled-components
yarn add -D @types/styled-components babel-plugin-styled-components

サーバーサイドレンダリングに必要な設定を入れます。
こちらを参考にしています。

.babelrc
{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}
src/pages/_document.tsx
import Document, { DocumentContext } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

styled-componentsを使ったサーバーサイドレンダリングが出来ているかを確認します。

src/pages/index.tsx
import styled from "styled-components";

const Home = () => <H1>Hello world!</H1>;

export default Home;

const H1 = styled.h1`
  color: #6495ed;
`;

yarn devで立ち上げたNext.jsのサーバににアクセスした際に、開発者コンソール等で、レスポンス時のHTML上で既に色が付いていることが分かると思います。

最後に

自分のための備忘録的なものですが、お役に立てれば幸いです。
今回のプロジェクトはここで公開しています。

参考

24
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?