趣味で最近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が登録されています。
"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
const sum = (a: number, b: number) => a + b;
export { sum };
import { sum } from "./sum";
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});
Jestを動かせるようにpackage.json
を変更します。
"scripts": {
"test": "jest"
}
テストを動かしてみます。
yarn test
テストが動いて通っていることが確認できました。
Storybook
Storybookの公式ページを参考にしています。
以前は必要なライブラリを個別にインストールする形だったのですが、公式からプロジェクトの構成を判別してライブラリ・設定ファイルを生成してくれるスクリプトが用意されています。
npx sb init
storybookを動かすコマンドがscriptsに記載されています。
"scripts": {
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
}
また、storybookのconfigファイルも自動生成されています。
(昔はwebpack.config.jsとか自分で書く必要があって大変だった……)
賢いことに src
ディレクトリの有無で生成するconfigが変わっています。
今回紹介するのは src
ディレクトリ付きです。
mkdir .storybook
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials"
]
}
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
上記コマンドでサンプル用のファイルが作成されているのですが、せっかくなので新規でstory用のファイルを作成します。
mkdir src/components
type Props = {
text: string;
};
const Text = ({ text }: Props) => <span>{text}</span>;
export { Text };
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-storybook
で storybook-static
ディレクトリ配下に生成されます。
ESLint
最初のプロジェクト生成で必要なものが生成されます。
{
"scripts": {
"lint": "next lint"
},
"devDependencies": {
"eslint": "7.32.0",
"eslint-config-next": "11.1.2",
}
}
{
"extends": "next/core-web-vitals"
}
これによって設定されるルールは公式のこのページに書かれています。
Prettier
必要なライブラリをインストールします。
yarn add -D prettier --exact
--exact
は公式で推奨されているので付けています。
フォーマットしやすいようにコマンドを書きます。
"scripts": {
"format": "prettier --write src/**/*.{ts,tsx}"
}
prettierの設定ファイルを書きます。
今回はnext.jsが使っているものをベースに個人的な好みの trailingComma: es5
を追加します。
{
// 上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
サーバーサイドレンダリングに必要な設定を入れます。
こちらを参考にしています。
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
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
を使ったサーバーサイドレンダリングが出来ているかを確認します。
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上で既に色が付いていることが分かると思います。
最後に
自分のための備忘録的なものですが、お役に立てれば幸いです。
今回のプロジェクトはここで公開しています。