이번 솝트 28기 웹잼을 하며 처음으로 Next.js + Typescript 조합으로 프로젝트를 진행하게 되었습니다. 이번 웹잼을 위해 공부한 내용들을 공유하고자 합니다:D
npx create-next-app --typescript
# or
yarn create next-app --typescript
npm install next react react-dom
# or
yarn add next react react-dom
dev - Runs next dev which starts Next.js in development mode
build - Runs next build which builds the application for production usage
start - Runs next start which starts a Next.js production server
lint - Runs next lint which sets up Next.js' built-in ESLint configuration
$ lsof -i tcp:3000
$ kill -9 (PID숫자)
yarn add -D eslint
prettier
eslint-plugin-prettier
eslint-config-prettier
eslint-plugin-import
eslint-plugin-react
eslint-plugin-react-hooks
@typescript-eslint/parser
@typescript-eslint/eslint-plugin
{
"extends": ["react-app", "prettier/prettier"],
"plugins": ["react-hooks", "simple-import-sort", "prettier"],
"rules": {
"prettier/prettier": "error",
"react-hooks/rules-of-hooks": "error",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0 }],
"comma-dangle": ["error", "always-multiline"],
"object-curly-spacing": ["error", "always"],
"space-in-parens": ["error", "never"],
"computed-property-spacing": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"eol-last": ["error", "always"],
"quotes": ["error", "single"],
"no-tabs": "error",
"semi": ["error", "never"],
"import/no-anonymous-default-export": 0,
"object-shorthand": "error",
"padding-line-between-statements": [
"error",
{ "blankLine": "always", "prev": "*", "next": "return" }
],
"@typescript-eslint/no-redeclare": 0
}
}
{
"printWidth": 80,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"bracketSpacing": true,
"endOfLine": "auto",
"useTabs": false
}
global.css
) _app.tsx에서만 사용 가능home.module.css
) 다른 컴포넌트 등에서 import 해서 사용 (다양하게 생성 가능)index.tsx
: 홈페이지. 기본 페이지. global.css를 가져옴_app.tsx
_document.tsx
// pages/_document.tsx
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class CustomDocument extends Document {
render() {
return (
<Html>
<Head>
// 모든페이지에 아래 메타테크가 head에 들어감
// 루트파일이기에 가능한 적은 코드만 넣어야 함!
//전역 파일을 엉망으로 만들면 안된다
// 웹 타이틀 같은 것 넣음
<meta property="custom" content="123123" />
</Head>
<body>
<Main />
</body>
<NextScript />
</Html>
);
}
}
component 폴더를 만들어 Layout.tsx를 만든 뒤 pages/_app.tsx를 Layout으로 감싼다
원하는 전역 스타일링이나 모든 페이지에서 나왔으면 하는 요소를 Layout.tsx 에서 제어.
Nav바 등등 모든 페이지에서 필요한 화면을 component 파일에 만든 뒤 Layout.tsx로 보낸다
→ 대충 _papp
pages 폴더 내부에서 원하는 페이지 루트를 만들고 필요한 컴포넌트들은 component 폴더 내부에서 만들어서 import한다.
import Head from 'next/head'
를 통해 넣어서 그 테그에 값을 넣으면 SEO가 잘 찾는 형태로 구현됨. → 안에 테그에 넣으면 웹 페이지 탭 이름이 그 이름으로 구현됨.
import Link from 'next/link'
import { useRouter } from 'next/router'
사용하려면 추가적으로 초기 세팅이 필요하다!
// 기본 styled-components
yarn add styled-components @types/styled-components
// 문자열 안에 스타일 들어가는 것 처리를 위한 설치
yarn add -dev babel-plugin-styled-components
//전역 스타일링에서 이용하기 위함
yarn add styled-reset
├── styles
│ ├── global-styles.ts # reset 또는 공통적으로 사용하는 css
│ ├── theme.ts # 공통적으로 사용할 테마(media query, color 등 -> 필요할 때 ... )
import reset from 'styled-reset'
import { createGlobalStyle } from 'styled-components'
const GlobalStyle = createGlobalStyle`
${reset}
* {
box-sizing: border-box;
}
body{
font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
input, button {
background-color: transparent;
border: none;
outline: none;
}
h1, h2, h3, h4, h5, h6{
font-family:'Maven Pro', sans-serif;
}
@media only screen and (max-width: 768px) {
body {
font-size: 12px;
}
}
@media only screen and (max-width: 576px) {
body {
font-size: 10px;
}
}
`
export default GlobalStyle
{
"presets" : ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from 'next/document'
import { ServerStyleSheet } from 'styled-components'
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()
}
}
render() {
return (
<Html>
<Head>
<meta charSet="utf-8" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
.env.local
에 설정한 이름대로 (NEXT_PUBLIC) 포함해서 접근할 것
깔끔하게 정리해주셔서 잘 봤습니다! 감사합니다