🦁
next.js環境構築
自分用メモ
create-next-appを使えば楽なんだけどたまには手動でしとかないと忘れるので
インストール
cd ../
mkdir client && cd $_
yarn init -y
yarn add next react react-dom
yarn add -D typescript @types/{node,react,react-dom}
TypeScript設定
基本的には標準のものを使う
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",
    "incremental": true,
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
}
export default nextConfig
src/pages/index.tsx
import { NextPage } from 'next'
interface IndexPageProps {}
const IndexPage: NextPage<IndexPageProps> = () => {
  return (
    <div>
      <div>Hello</div>
    </div>
  )
}
export default IndexPage
package.json
+  "type": "module",
+  "scripts": {
+    "dev": "next dev"
+  },
yarn devで動作すればOK
ESLint + Prettier
yarn add -D eslint eslint-config-{next,prettier} prettier
設定
.eslint.json
{
  "extends": [
    "next/core-web-vitals",
    "plugin:import/recommended",
    "plugin:import/warnings",
    "prettier"
  ],
  "rules": {
    "import/order": [
      "error",
      {
        "alphabetize": {
          "order": "asc"
        }
      }
    ]
  }
}
.prettierrc
{
  "trailingComma": "all",
  "tabWidth": 2,
  "semi": false,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "printWidth": 120
}
StyledComponents
yarn add styled-components
yarn add -d @types/styled-components
next.config.js
+   compiler: {
+       styledComponents: true,
+   },
}
export default nextConfig
src/pages/index.tsx
import { NextPage } from 'next'
+ import styled from 'styled-components'
interface IndexPageProps {}
+ const StyledText = styled.p`
+   & {
+     color: red;
+   }
+ `
const IndexPage: NextPage<IndexPageProps> = () => {
  return (
    <div>
-       <div>Hello</div>
+       <StyledText>Hello</StyledText>
    </div>
  )
}
export default IndexPage
これだけだとProp 'className' did not match. Server: 〜なエラーが出てしまうので、公式に載っているとおりgetInitialPropsの対応を追加する
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()
    }
  }
}
ついでにReset CSSも追加しとく
yarn add styled-reset
src/pages/_app.tsx
import { AppProps } from 'next/app'
import { createGlobalStyle } from 'styled-components'
import reset from 'styled-reset'
const GlobalStyle = createGlobalStyle`
  & {
    ${reset}
    * {
      box-sizing: border-box;
    }
  }
`
function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <GlobalStyle />
      <Component {...pageProps} />
    </>
  )
}
export default MyApp
Discussion