page
page 디렉토리 내 .js, .jsx, .ts, tsx 확장자를 가지는 파일들을 filename 기반으로 라우팅 됨
// pages/about.js
export default function About() {
return <div>About</div>
}
dynamic Rountes
pages/posts/[id].js -> posts/1 처럼 동적인 url 을 가지는 페이지를 구성할 수 있음
// pages/[id].tsx
import { useRouter } from "next/router";
export default () => {
const router = useRouter();
return (
<>
<h1>post</h1>
<p>postid: {router.query.id}</p>
</>
);
};
pre-rendering
- static generation: HTML 이 빌드시에 생성되고 각 request 에서 재사용됨
- server-side rendering: HTML 이 각 request 마다 생성됨
next 는 두가지를 hybrid로 섞어 두가지 rendering 방식을 동시에 사용할 수 있음
page with data
ssg(static site generation)
- page내에 content가 외부 데이터에 의존적일때
export default function Blog({ posts }) {
// Render posts...
}
// This function gets called at build time
export async function getStaticProps() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}
2. page내에 path가 외부데이터에 의존적일때
export default function Post({ post }) {
// Render post...
}
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
ssr
export default function Page({ data }) {
// Render data...
}
// This gets called on every request
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}
Layouts
single shared layout
전체 application 을 하나의 layout으로 관리할때
// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
per-page layouts
여러개의 중첩된 layout을 사용하는 경우
page에 getLayout 속성을 추가하여 layout에 react component를 반환하는것을 가능하게 해줌
// pages/index.js
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
export default function Page() {
return (
/** Your content */
)
}
Page.getLayout = function getLayout(page) {
return (
<Layout>
<NestedLayout>{page}</NestedLayout>
</Layout>
)
}
이미지 최적화
이미지 컴포넌트를 사용하여 src로 local 또는 remote 경로를 받아 사용
1. local file
- width와 height가 자동으로 설정됨
import Image from 'next/image'
import profilePic from '../public/me.png'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src={profilePic}
alt="Picture of the author"
/>
<p>Welcome to my homepage!</p>
</>
)
}
2. remote file
- 빌드시에 접근할 수 없기때문에 width, height를 설정해줘야함
metafile
_document.tsx
meta 태그를 정의하거나, 전체 페이지에 관여하는 컴포넌트
서버에서만 렌더링됨
- console은 서버에서만 노출되고 클라이언트에서 실행되지 않음
- react lifecycle 훅도 실행되지 않고, staticd 한 상황에서만 실행
- <Main> 컴포넌트 외부는 browser에서 초기화 되지 않으므로 application logic을 추가하면 안되고 layout에 추가하길 권장
-
// 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>
);
}
}
_app.tsx
이곳에서 렌더링 하는 값들은 모든 페이지에 영향을 줌
최초 실행되는 component
각페이지가 update 되기전에 전처리
function MyApp({ Component, pageProps }) {
// component -> 요청한 페이지 ex) /pages/index.js 의 component
// pageProps => 페이지의 getInitialProps를 통해 내려받은 props
return <Component {...pageProps} />;
}
export default MyApp;
server side lifeCycle
- nextJs 서버가 GET 요청을 받는다.
- GET 요청에 맞는 pages/Component를 찾는다.
- _app.tsx의 getInitialProps가 있다면 실행한다.
- route에 맞는 페이지의 Component의 (getServerSideProps, getStaticProps)가 있다면 실행한다. pageProps들을 받아온다.
- _document.tsx의 getInitialProps가 있다면 실행한다. pageProps들을 받아온다.
- 모든 props들을 구성하고, _app.tsx -> page Component 순서로 렌더링
- 모든 Content를 구성하고 _document.tsx를 실행하여 html 형태로 출력한다.
dynamic component import
lazy component import 를 위한 방식
초기 데이터 없이 사용될 수 없는 component의 경우 import 하지 않음으로 초기 화면 렌더링 속도가 상승함
import React, { useState } from "react";
import dynamic from "next/dynamic";
const DynamicComponent = dynamic<{ nowTab: number }>(() =>
import("./DynamicComponent")
);
const Index = () => {
const [nowTab, setNowTab] = useState(0);
return (
<>
{nowTab === 0 && <div>0 tab</div>}
{nowTab === 1 && <DynamicComponent nowTab={nowTab} />}
</>
);
};
환경변수
https://nextjs.org/docs/basic-features/environment-variables
참고자료
https://kyounghwan01.github.io/blog/React/next/basic/
'Front-end > React' 카테고리의 다른 글
controlled & uncontrolled input (0) | 2023.02.02 |
---|---|
useRef & Refs (0) | 2023.01.30 |
Styled-component (0) | 2022.12.05 |
React Query (0) | 2022.11.28 |
Redux (0) | 2022.11.23 |