Next.프로젝트 설정

개시하다


다음 설정에 맞는 항목 설정을 진행합니다.
  • Next.js
  • TypeScript
  • Tailwind
  • Storybook
  • ESLint
  • Prettier
  • husky
  • 설치된 항목은 이쪽창고.에서 "Usethis template"를 클릭하면 다음 순서에 따라 창고를 새로 만들 수 있습니다.

    작업 환경


    node, yarn이 설치되었습니다.
    $node -v
    v12.16.3
    $yarn -v
    1.22.10
    
    동작 검증 후 MacOS 버전이 여기에 있습니다.
    $sw_vers
    ProductName:    Mac OS X
    ProductVersion: 10.15.7
    BuildVersion:   19H2
    

    Next.js 프로젝트 만들기


    우선 넥스트.js 프로젝트를 만듭니다.
    npx create-next-app nextjs-with-typescript-tailwind-storybook
    
    이런 정보가 나오면 제작이 완료된다.

    다 만들면 메시지대로 일어서서 해볼게요.
    cd nextjs-with-typescript-tailwind-storybook
    yarn dev
    
    http://localhost:3000에 액세스하면 다음 페이지가 표시됩니다.

    TypeScript 설정


    tsconfig.json을 만듭니다.
    touch tsconfig.json
    
    제작 후 yarn dev를 실행하면 다음과 같은 오류가 발생할 수 있습니다.
    It looks like you're trying to use TypeScript but do not have the required package(s) installed.
    Please install typescript, @types/react, and @types/node by running:
    yarn add --dev typescript @types/react @types/node
    If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).
    지시에 따라 필요한 포장을 첨가하다.
    yarn add --dev typescript @types/react @types/node
    
    가방의 추가 완성 후 yarn dev로 시작합니다.
    그래서 tsconfig.json 설정은 다음과 같습니다.
    tsconfig.json
    {
      "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": false,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve"
      },
      "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
      "exclude": ["node_modules"]
    }
    
    
    또 넥스트-env.d.ts가 자동으로 생성됩니다.
    next-env.d.ts
    /// <reference types="next" />
    /// <reference types="next/types/global" />
    
    기존 파일 확장자 변경
    pages/_app.js -> pages/_app.tsx
    pages/index.js -> pages/index.tsx
    pages/api/hellow.js -> pages/api/hello.tsx
    yarn dev를 다시 실행하고 를 시작하면 Type Script 가져오기가 완료됩니다.

    Tailwind 설정


    Tailwind에 필요한 모듈을 추가합니다.
    yarn add tailwindcss postcss autoprefixer
    
    다음 명령을 수행합니다.
    npx tailwindcss init -p
    
    tailwind.config.js postcss.config.js 만들기
       tailwindcss 2.0.2
       ✅ Created Tailwind config file: tailwind.config.js
       ✅ Created PostCSS config file: postcss.config.js
    
    tailwind.config.js 변경
    tailwind.config.js
     module.exports = {
    -   purge: [],
    +   purge: ['./pages/**/*.tsx', './components/**/*.tsx'],
        darkMode: false, // or 'media' or 'class'
        theme: {
          extend: {},
        },
        variants: {
          extend: {},
        },
        plugins: [],
      }
    
    globals.css를 다음과 같이 덮어씁니다.
    ./styles/globals.css
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
    Tailwind index가 적합한지 여부tsx의 Welcome to Next입니다.js 아래에 아래의 내용을 추가하여 확인합니다.
    pages/index.tsx
    <p className="text-3xl text-red-500 font-bold">Hello Tailwind</p>
    
    이렇게 className이 지정한 것을 반영하면Tailwind 설정이 완성됩니다

    Storybook 설정


    스토리북이 추가됩니다.
    npx sb init
    
    모듈을 추가하여 시동을 걸어 보십시오.
    yarn storybook
    
    PostCSS 오류가 발생해야 합니다.
    ERROR in ./stories/button.css (./node_modules/css-loader/dist/cjs.js??ref--11-1!./node_modules/postcss-loader/src??ref--11-2!./stories/button.css)
    Module build failed (from ./node_modules/postcss-loader/src/index.js):
    Error: PostCSS plugin tailwindcss requires PostCSS 8.
    
    Tailwind 및 Storybook의 PostCSS 종속성 제거 필요
    공식문서에 따라 Tailwind에서 PostCSS7을 사용하도록 변경합니다.
    yarn remove tailwindcss postcss autoprefixer
    yarn add tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
    
    yarn storybook 다시 방문http://localhost:6006/
    스토리북을 확인하고 일어나세요.

    components 변경 및 Tailwind 반영


    디렉터리를stories에서components로 변경합니다.
    mv stories components
    
    storybook에서 지정한 디렉터리를 변경합니다.
    .storybook/main.js
      module.exports = {
        "stories": [
    -     "../stories/**/*.stories.mdx",
    -     "../stories/**/*.stories.@(js|jsx|ts|tsx)"
    +     "../components/**/*.stories.mdx",
    +     "../components/**/*.stories.@(js|jsx|ts|tsx)"
        ],
        "addons": [
          "@storybook/addon-links",
          "@storybook/addon-essentials"
        ]
      }
    
    tailwind를 반영하는 것처럼 스타일즈/globls.import css.
    ./storybook/preview.js
    +   import "../styles/globals.css"
    
        export const parameters = {
          actions: { argTypesRegex: "^on[A-Z].*" },
        }
    
    우선 button, Buton만 만들기 위해.stories.tsx、Button.tsx 이외의 파일을 삭제하면 이렇게 됩니다.
    components/
    ├── Button.stories.tsx
    └── button.tsx
    
    storybook의 샘플로 제공된button의 스타일을 tailwind로 교체해 보았습니다.
    자신의 색상과 글꼴을tailwind로 지정합니다.json의 각 colors, font Family에 기술되어 있습니다.
    tailwind.config
    module.exports = {
      purge: ['./pages/**/*.tsx', './components/**/*.tsx'],
      darkMode: false, // or 'media' or 'class'
      theme: {
        extend: {
          colors: {
            blue: {
              450: '#1ea7fd',
            },
          },
        },
        fontFamily: {
          sans: ['Nunito Sans', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'],
        },
        boxShadow: {
          inner: 'rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset',
        },
      },
      variants: {
        extend: {},
      },
      plugins: [],
    }
    
    
    Buton의 스타일을 Tailwind로 바꾸기
    Button.tsx
    import React from 'react'
    
    export interface ButtonProps {
      primary?: boolean
      backgroundColor?: string
      size?: 'small' | 'medium' | 'large'
      label: string
      onClick?: () => void
    }
    
    export const Button: React.FC<ButtonProps> = ({
      primary = false,
      size = 'medium',
      backgroundColor,
      label,
      ...props
    }) => {
      const baseButton = 'rounded-full font-bold'
      const sizeMode =
        size === 'small'
          ? 'py-1.5 px-4 text-xs'
          : size === 'medium'
          ? 'py-2 px-5 text-sm'
          : size === 'large'
          ? 'py-3 px-6 text-base'
          : ''
      return primary ? (
        <div>
          <button
            type="button"
            className={`text-white bg-blue-450 ${baseButton} ${sizeMode}`}
            {...props}
          >
            {label}
          </button>
        </div>
      ) : (
        <button
          type="button"
          className={`text-gray-600 bg-transparent shadow-inner ${baseButton} ${sizeMode}`}
          style={{ backgroundColor }}
          {...props}
        >
          {label}
        </button>
      )
    }
    
    
    
    yarn storybook에서 시작하면 button의 스타일이tailwind에서 적응되었는지 확인할 수 있습니다.

    ESLit 설정


    ESLitt, Pretter에 필요한 패키지를 추가합니다.
    yarn add --dev eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin
    
    dependencies에 추가하면 다음과 같다.
    package.json
    {
      ...
       "dependencies": {
         "autoprefixer": "^9",
         "@storybook/react": "^6.1.11",
         "@types/node": "^14.14.10",
         "@types/react": "^17.0.0",
    +    "@typescript-eslint/eslint-plugin": "^4.10.0",
    +    "@typescript-eslint/parser": "^4.10.0",
         "babel-loader": "^8.2.2",
    +    "eslint": "^7.15.0",
    +    "eslint-config-prettier": "^7.0.0",
    +    "eslint-plugin-prettier": "^3.3.0",
    +    "eslint-plugin-react": "^7.21.5",
    +    "prettier": "^2.2.1",
         "typescript": "^4.1.2"
       }
    }
    
    
    eslint의 프로필과 esliting nore를 만듭니다.
    touch .eslintrc.json .eslintignore
    
    eslintrc를 다음과 같이 설정합니다.
    eslintrc.json
    {
      "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/eslint-recommended",
        "plugin:prettier/recommended",
        "prettier/@typescript-eslint"
      ],
      "settings": {
        "react": {
          "version": "latest"
        }
      },
      "plugins": ["@typescript-eslint"],
      "parser": "@typescript-eslint/parser",
      "env": {
        "browser": true,
        "node": true,
        "es6": true
      },
      "rules": {
        "prettier/prettier": [2, { "singleQuote": true, "semi": false }],
        "react/react-in-jsx-scope": 0,
        "react/display-name": 0,
        "react/prop-types": 0,
        "@typescript-eslint/explicit-function-return-type": 0,
        "@typescript-eslint/explicit-member-accessibility": 0,
        "@typescript-eslint/indent": 0,
        "@typescript-eslint/member-delimiter-style": 0,
        "@typescript-eslint/no-explicit-any": 1,
        "@typescript-eslint/no-var-requires": 2,
        "@typescript-eslint/no-use-before-define": 0,
        "@typescript-eslint/no-unused-vars": [
          2,
          {
            "argsIgnorePattern": "^_"
          }
        ],
        "no-console": [
          2,
          {
            "allow": ["warn", "error"]
          }
        ]
      }
    }
    
    prettier와 관련된 extends는 eslint와prettier 충돌을 피하기 위해 extends 배열 내의 마지막 기술을 사용해야 합니다.
    rules의prettier/prettier에 대해 다음에 기술한 vscode의 자동 성형을 기록할 때,eslint과prettier가 충돌했습니다.
    개발 규약과 취향에 따라 rules를 설정합니다.
    eslint에서 대상 밖의 파일을 설정합니다.
    **/node_modules/*
    **/out/*
    **/.next/*
    storybook-static
    
    package.json에 lint의script를 추가합니다.
    package.json
    {
      ...
      "scripts": {
         "build": "next build",
         "start": "next start",
         "storybook": "start-storybook -p 6006",
    -    "build-storybook": "build-storybook"
    +    "build-storybook": "build-storybook",
    +    "lint": "eslint . --ext .ts,.js,.tsx,.jsx",
    +    "lint:fix": "eslint --fix . --ext .ts,.js,.tsx,.jsx"
       },
       ...
    }
    
    실행
    yarn lint
    
    많은 오류가 발생할 것 같아서 fix를 해볼게요.
    yarn lint:fix
    
    돈 나오면 OK.
    ...
    ✨  Done in 2.25s.
    

    Proettier 설정


    touch .prettierrc.json .prettierignore
    
    .prettierrc.json
    {
      "semi": false,
      "singleQuote": true,
      "bracketSpacing": true,
      "tabWidth": 2,
      "printWidth": 100
    }
    
    .prettierignore
    node_modules
    .next
    yarn.lock
    package-lock.json
    public
    storybook-static
    
    scripts에 다음 내용을 추가합니다.
    package.json
    ...
    "scripts":{
      ...
      "format": "prettier --write ."
    }
    
    
    prettier를 실행합니다.
    yarn format
    
    코드가 성형되었다.
    yarn format
    yarn run v1.22.10
    $ prettier --write .
    .eslintrc.json 33ms
    .prettierrc.json 10ms
    .vscode/settings.json 2ms
    components/Button.stories.tsx 203ms
    components/Button.tsx 40ms
    package.json 5ms
    pages/_app.tsx 7ms
    pages/api/hello.tsx 9ms
    pages/index.tsx 42ms
    README.md 49ms
    tsconfig.json 6ms
    ✨  Done in 0.83s.
    

    VScode 저장 시 자동 성형


    vscode에save를 설정할 때 자동으로 성형할 수 있습니다.
    VSCODE 확장 도구의 ESLight가 미리 필요하므로 설치합니다.
    https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
    mkdir .vscode
    touch ./.vscode/settings.json
    
    settings.json
    {
      "editor.formatOnSave": true,
      "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
      }
    }
    
    
    오류가 감지된 파일에 저장하면 자동으로 성형됩니다.

    husky 설정


    Husky는git의commiit와push에서 특정 명령을 실행하는 도구입니다.
    이번에commiit로 설정할 때 아까 설정한eslint와prettier 달리기.
    yarn add --dev husky lint-staged
    
    아래 내용 추가
    package.json
    {
      "scripts": {
        ...
      },
      "husky": {
        "hooks": {
          "pre-commit": "lint-staged"
        }
      },
      "lint-staged": {
        "*.{js,jsx,ts,tsx}": [
          "yarn lint",
          "yarn format"
        ]
      },
      ...
    }
    
    
    제출할 때 lint-staged를 통해 설정된scripts가 실행됩니다.
    next-typescript-storybook-tailwind-sandbox  (main=)  $git commit -m "husky test"
    husky > pre-commit (node v12.16.3)
    ✔ Preparing...
    ✔ Running tasks...
    ✔ Applying modifications...
    ✔ Cleaning up...
    [main 015cc25] husky test
     1 file changed, 1 insertion(+)
    
    프로젝트 설치가 완료되었습니다.

    참고 자료

  • https://nextjs.org/learn/basics/create-nextjs-app
  • https://tailwindcss.com/docs/guides/nextjs
  • https://storybook.js.org/docs/react/get-started/install
  • https://github.com/vercel/next.js/tree/master/examples
  • https://eslint.org/docs/user-guide/configuring#configuring-rules
  • https://tech.ga-tech.co.jp/entry/2020/01/refactoring-type-safety-with-eslint
  • https://medium.com/better-programming/start-a-component-library-with-storybook-tailwind-css-and-typescript-ebaffc33d098
  • https://github.com/prettier/prettier/issues/2280
  • 좋은 웹페이지 즐겨찾기