For

2021.10.9

Next.js + TypeScript + Tailwind + その他 で開発を始める手順

環境

node: v14.17.0
yarn: 1.22.11

Next.js のプロジェクトを作成

terminal_____none_____yarn create next-app --typescript

その後 src ディレクトリを作り、その中に pages と styles を移動する。

terminal_____none_____mkdir src
mv pages src/pages
mv styles src/styles


TypeScript での開発に必要なパッケージをインストール

terminal_____none_____yarn add -D typescript @types/react @types/react-dom @types/node

package.json を編集する。

JSON_____package.json_____  "scripts": {
    "dev": "next dev --port 3100", // ポート番号は適宜変更
    "lint": "next lint --dir src",
    "lint:fix": "eslint src --ext .js,jsx,.ts,.tsx --fix",
},

いったん起動する。

terminal_____none_____yarn run dev


Prettier の導入

Prettier でフォーマットするために、設定ファイルを作成します。

JSON_____.prettierrc_____{
    "trailingComma": "all",
    "tabWidth": 4,
    "semi": false,
    "singleQuote": true,
    "jsxSingleQuote": true,
    "useTabs": true
}


必要なパッケージをインストールします。

terminal_____none_____yarn add -D prettier eslint-config-prettier


ESlint と Prettier が衝突しないよう、設定ファイルを更新します。

JSON_____.eslintrc_____{
    "extends": ["next", "next/core-web-vitals", "prettier"]
}


package.json にフォーマット用のスクリプトを scripts に追記しておきます。

JSON_____package.json_____"format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'",


VSCode 用の設定ファイルを追加します。
VSCode 上で cmd + P でコマンドパレットを開き ext install esbenp.prettier-vscode を入力してインストール。
その後 .vscode ディレクトリを作成し、その中に settings.json を配置する。

terminal_____none_____mkdir .vscode
touch settings.json


JSON_____settings.json_____{
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
        "source.fixAll": true
    }
}


husky の導入

terminal_____none_____yarn add -D husky


husky で commit と push 前に実行してほしいスクリプトを package.json に追記します。

JSON_____package.json_____    "scripts": {
        "test": "npm run lint:fix && npm run format",
    },
    "husky": {
        "hooks": {
            "pre-commit": "npm test",
            "pre-push": "npm test"
        }
    },


Storybook を導入

terminal_____none_____npx sb init
yarn add -D storybook-css-modules-preset


作成された preview.js と main.js を編集する。

javascript_____preview.js_____import '../src/styles/globals.css'


export const parameters = {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
        matchers: {
            color: /(background|color)$/i,
            date: /Date$/,
        },
    },
}


javascript_____main.js_____module.exports = {
    stories: ['../src/**/*.stories.mdx', '../src/components/**/*.stories.tsx'],
    addons: [
        '@storybook/addon-links',
        '@storybook/addon-essentials',
        'storybook-css-modules-preset',
    ],
}


Tailwind を導入

terminal_____none_____yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest


Home.module.css は不要なので削除し globals.css に以下を追記。

css_____globals.css_____@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';


その他の修正

現時点で yarn run dev でエラーが出る箇所を修正しておきます。

TypeScript_____index.tsx_____import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'

const Home: NextPage = () => {
    return <div>test</div>
}

export default Home


TypeScript______document.tsx_____import { Html, Head, Main, NextScript } from 'next/document'

const MyDocument = () => {
    const url = '<https://example.com>'
    const title = 'Demo Next.js'
    const description = 'Demo of Next.js'

    return (
        <Html lang='ja-JP'>
            <Head>
                {/* Change the contents of `<Head>` as needed. */}
                <meta name='description' content={description} />
                <meta name='theme-color' content='#333' />
                <meta property='og:type' content='website' />
                <meta property='og:title' content={title} />
                <meta property='og:url' content={url} />
                <meta property='og:description' content={description} />
                <meta property='og:site_name' content={title} />
                <meta property='og:image' content={`${url}/ogp.png`} />
                <meta name='twitter:card' content='summary_large_image' />
                <meta name='format-detection' content='telephone=no' />
                <link rel='apple-touch-icon' href='/apple-touch-icon.png' />
            </Head>
            <body>
                <Main />
                <NextScript />
            </body>
        </Html>
    )
}

export default MyDocument


TypeScript______app.tsx_____import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
    return <Component {...pageProps} />
}

export default MyApp


JSON_____tsconfig.json_____{
    "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "baseUrl": "./",
        "paths": {
            "@/*": ["src/*"]
        }
    },
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
    "exclude": ["node_modules"]
}