Next 기본 세팅(TS, ESLint, Prettier, Styled-Components)

김은호·2023년 1월 11일
1

1. Next + TS 환경 구성

$ npx create-next-app --typescript

Would you like to se ESLint with this project? -> Yes 선택

2. ESLint + Prettier

$ npx eslint --init
  • Typescript를 사용하냐는 질문에 반드시 Yes

    eslint-plugin-react@latest # 리액트 관련 규칙
    @typescript-eslint/eslint-plugin@latest
    @typescript-eslint/parser@latest
    eslint@latest
    Would you like to install them now? -> Yes

추가 모듈 & Prettier 설치

  • -D 옵션 -> devdependency에 설치, 배포할 때가 아닌 개발할 때만 필요한 라이브러리일 때 사용, 빌드할 때의 시간을 줄일 수 있음

    npm i -D eslint-plugin-react-hooks
    npm i -D eslint-plugin-import
    npm i -D prettier eslint-plugin-prettier eslint-config-prettier
    npm i -D eslint-config-airbnb

  • eslint-plugin-react-hooks: 리액트 훅 관련 규칙
  • eslint-plugin-import: import/export syntax 체크, 파일 경로나 import 이름을 잘못 입력하는지 여부를 체크
  • eslint-config-airbnb: airbnb에서 자바스크립트 코드 규칙
  • eslint-config-prettier: eslint 규칙 중 Prettier과 충돌하는 부분은 비활성화 하도록

eslintrc.json 작성

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "airbnb",
    "plugin:jsx-a11y/recommended",
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "plugin:import/recommended"
  ],
  "overrides": [],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": ["react", "@typescript-eslint", "prettier", "import"],
  "rules": {
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        "js": "never",
        "jsx": "never",
        "ts": "never",
        "tsx": "never",
        "json": "never"
      }
    ],
    "react/jsx-filename-extension": [
      2,
      { "extensions": [".js", ".jsx", ".ts", ".tsx"] }
    ],
    "prettier/prettier": ["error", { "endOfLine": "auto" }],
    "import/prefer-default-export": "off",
    "react/react-in-jsx-scope": "off",
    "import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
    "react/jsx-props-no-spreading": ["warn"]
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"]
      }
    }
  }
}
  • env: eslint를 활성화하고 싶은 환경을 설정, 현재 브라우저와 es2021에서 활성화됨
  • extends: 추가한 플러그인에서 사용할 규칙을 설정
  • overrides: 프로젝트 내의 일부 파일에 대해서만 다른 설정을 주고 싶을 때 사용
  • parser: 구문 분석을 위해 어떤 것을 사용할 것인가?
  • parserOptions: ESLint 사용을 위해 지원하려는 Javascript 언어 옵션을 지정
  • plugins: 설치한 서드파티들
  • rules: 프로젝트에서 사용하는 규칙을 수정할 수 있음

    "off" or 0: 규칙을 사용하지 않음
    "warn" or 1: 규칙을 경고로 사용
    "error" or 2: 규칙을 오류로 사용

root에 .prettierrc 파일 생성 후 작성

{
  "singleQuote": true, 
  "semi": true,
  "useTabs": false,
  "tabWidth": 2,
  "trailingComma": "all",
  "printWidth": 80,
  "arrowParens": "always",
  "orderedImports": true,
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}

settings.json 수정 or 작성

전역 설정 json 파일, settings가 먼저 적용되고 prettierrc 파일이 있으면 그 파일을 뒤에 적용함
내 settings.json

{
  "liveServer.settings.donotShowInfoMsg": true,
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "liveServer.settings.useLocalIp": true,
  "liveServer.settings.host": "192.168.0.46",
  "terminal.integrated.defaultProfile.windows": "Command Prompt",
  "bracket-pair-colorizer-2.depreciation-notice": false,
  "workbench.editorAssociations": {
    "*.docx": "default"
  },
  "code-runner.runInTerminal": true,
  "code-runner.terminalRoot": "/",
  "emmet.triggerExpansionOnTab": true,
  "editor.tabSize": 2,
  "javascript.updateImportsOnFileMove.enabled": "always",
  "materialTheme.accent": "Bright Teal",
  "settingsSync.ignoredExtensions": [],

  "editor.tokenColorCustomizations": {
    "textMateRules": [
      {
        "scope": ["comment", "keyword.control"],
        "settings": { "fontStyle": "bold " } //주석과 키워드에 적용된 이탤릭 폰트스타일 해제
      }
    ],
    "comments": "#16bda7" //주석 색상변경
  },
  "workbench.iconTheme": "eq-material-theme-icons-ocean",
  "workbench.colorTheme": "Community Material Theme Darker High Contrast",
  "prettier.singleQuote": true,
  "javascript.format.enable": false,
  "typescript.updateImportsOnFileMove.enabled": "always",
  "editor.codeActionsOnSave": { "source.fixAll.eslint": true },
  "files.autoSave": "onFocusChange",
  "remote.SSH.remotePlatform": {},
  "window.zoomLevel": -1
}

3. Styled-Components

$ npm i styled-components @types/styled-components

.bablerc 파일 생성 후 작성

styled-components는 문자열 안에 css를 작성하는데 자바스크립트 컴파일러인 babel이 못알아먹어서 .babelrc파일 안에 styled-components에 대해 써줌

$ npm i --save-dev babel-plugin-styled-components

위 플러그인 설치 후 .babelrc를 생성하고 아래와 같이 작성

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      {
        "ssr": true,
        "displayName": true,
        "preprocess": true
      }
    ]
  ]
}

그 후 SSR을 할 때에도 Styled-Components 사용을 위해 _document.tsx를 수정

import Document, { DocumentContext, DocumentInitialProps } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext
  ): Promise<DocumentInitialProps> {
    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();
    }
  }
}

4. _app.tsx 기본 세팅

import type { AppProps } from 'next/app';
import Head from 'next/head';
import { ThemeProvider } from 'styled-components';
import { GlobalStyle } from '../styles/global-style';
import { theme } from '../styles/theme';

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>MyApp</title>
      </Head>
      <GlobalStyle />
      <ThemeProvider theme={theme}>
        <Component {...pageProps} />
      </ThemeProvider>
    </>
  );
}

export default MyApp;

0개의 댓글