Next.js: https://nextjs.org/
npm install -g create-next-app
설치확인
create-next-app --version
npx create-next-app my-app
파일 종류 및 설명
public: create-next-app으로 개발할 Next.js 프로젝트의 Static 파일들(이미지 파일 등)이 저장된 폴더입니다.
pages: Next.js 프로젝트에서 화면에 표시될 페이지들을 저장하는 폴더입니다.
pages/index.js: index 페이지(/)에 해당하는 파일입니다.
pages/_app.js: 모든 페이지에 공통으로 사용되는 컴포넌트입니다. 모든 페이지에 레이아웃 등을 설정할 때 사용합니다.
styles: 스타일 파일(css)을 저장하는데 사용하는 폴더입니다.
styles/globals.css: 전체 페이지에 적용되는 스타일 파일입니다.
styles/Home.module.css: index.js 파일에서 사용하는 스타일 파일입니다.
.eslintrc.json: 정적 코드 분석 툴인 ESLint 설정에 관한 파일입니다.
next.config.js: Next.js 프로젝트 설정에 관한 파일입니다.
package.json: 개발에 필요한 라이브러리를 관리하는 파일입니다.
npm run dev
ESLint는 설치시 허용함
//tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"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"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
ESLint와 Prettier를 함께 사용하기 위해서 다음과 같이 설치
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
eslintrc.js 설명
//eslintrc.js
module.exports = {
env: {
// 전역 변수 사용을 정의합니다. 추가하지 않으면 ESLint 규칙에 걸리게 됩니다.
browser: true,
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended", // 해당 플러그인의 권장 규칙을 사용합니다.
],
parser: "@typescript-eslint/parser", // ESLint 파서를 지정합니다.
parserOptions: {
ecmaFeatures: {
jsx: true, // JSX를 파싱할 수 있습니다.
},
ecmaVersion: 12, // Modern ECMAScript를 파싱할 수 있습니다.
sourceType: "module", // import, export를 사용할 수 있습니다.
},
plugins: ["react", "@typescript-eslint"],
rules: {
// ESLint 규칙을 지정합니다. extends에서 지정된 규칙을 덮어 쓸수도 있습니다.
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
},
settings: {
react: {
version: "detect", // 현재 사용하고 있는 react 버전을 eslint-plugin-react가 자동으로 감지합니다.
},
},
};
Prettier
//.prettierrc.js
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 160,
tabWidth: 2,
};
// 기본 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
// .babelrc
{
"presets" : ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}
// _document.ts
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
// /pages/_app.tsx
import '../styles/globals.css'
import Layout from "../components/Layout";
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
///components/Layout.tsx
import React from "react";
import NavBar from "./Navbar";
type Props = {
children: React.ReactNode;
};
export default function Layout(props: Props) {
return (
<div className="w-full p-0">
<NavBar />
{props.children}
</div>
);
}