npx create-next-app [app-name]
# or
yarn create next-app [app-name]
typescript 추가
npx create-next-app --typescript
# or
yarn create next-app --typescript
npm install next react react-dom
# or
yarn add next react react-dom
package.json 에 스크립트 추가하기
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
page 디렉토리를 생성하고 내부에 파일을 만들면 해당 파일의 이름으로 기본적으로 라우팅 처리 해준다.
예를들어
/pages/index.js 파일은
"/"가 라우트 path로 적용된다.
/pages/first.파일은
"/first"가 라우트 path이다.
file을 "[value].js" 로 생성한다.
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { value } = router.query
return <p>Post: {value}</p>
}
export default Post
/posts/abc 로 path를 입력하면
tag의 텍스트는 Post: abc로 나온다.
/posts/abc?query=efg
로 입력하면
router.query의 값은
{query:"efg",value:"abc"}
로 출력 된다.
아래는 next에서 사용하는 Link의 예시이다.
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/post/abc">
<a>Go to pages/post/[pid].js</a>
</Link>
</li>
<li>
<Link href="/post/abc?foo=bar">
<a>Also goes to pages/post/[pid].js</a>
</Link>
</li>
<li>
<Link href="/post/abc/a-comment">
<a>Go to pages/post/[pid]/[comment].js</a>
</Link>
</li>
</ul>
)
}
export default Home
react-router-dom에서 사용하는 Link와는 약간다르다.
to 대신에 href를 사용한다.
catch all routes
/posts/abc/qwer?foo=bar
이런형식으로 라우트 뎁스가 더 들어가게 되는경우를 전부받아줘야 하는경우는 어떨까
이런 url이 있는경우
[value].js의 경우에는 404 error가 발생한다.
해당파일을 spread 형태로 이름을 변경한다
[...value].js
아래와 같이 해당 url을 인식함과 동시에 value가 배열로 변경 되었다.
이경우 /posts 까지만 입력된 url은 인식하지 못한다.
optional catch all routes를 이용하자
[[...value]].js
파일명을 위와 같은 형태로 변경한후 /posts 에 접근해보자
해당 컴포넌트가 정상적으로 출력 되지만 콘솔이나 p tag에 출력하려고 했던 쿼리들은 나오지 않는다.
이 방법들을 활용해서 동적 라우팅을 구현하면 된다.
혹시 pages/posts/ 에 create.js라는 파일이 이미 존재한다면
동적 라우팅을 할때 create는 create.js와 자동으로 매치되게 된다.
동적라우팅때문에 파일의 라우트가 겹치게 될 경우를 방지한다.
Link를 사용하면 대부분의 처리가 가능하겠지만 수동으로 route를 변경할수있다.
import { useRouter } from 'next/router'
function ReadMore() {
const router = useRouter()
return (
<span onClick={() => router.push('/about')}>Click here to read more</span>
)
}
export default ReadMore
위와 같이 router.push()를 사용하자.
얕은 라우팅은 페이지는 교체되지 않고 경로만 변경됩니다.
동일 페이지가 아닌 다른페이지로 넘어갈경우 얕은 라우팅처리 되지 않습니다.
router.push('/?counter=10', undefined, { shallow: true })
next js 는 기본적으로 모든 페이지를 pre-rendering합니다.
두가지 형태의 pre-rendering이 있는데 각 형태의 차이점은 페이지에 대한 HTML을 생성할 때 나타납니다.
이 두가지 형태를 nextjs 에서는 선택하여 사용할 수 있습니다.
대부분의 페이지는 정적 생성을 사용하고 사용자의 요청에 의해 변경되는 페이지등은 서버사이드 랜더링을 사용하는 방법을 보통 사용합니다.
일부 페이지는 사전 렌더링을 위해 외부 데이터를 가져와야 합니다. 두 가지 시나리오가 있으며 하나 또는 둘 다 적용될 수 있습니다. 각각의 경우에 nextjs가 제공하는 다음 기능을 사용할 수 있습니다.
예: 블로그페이지는 CMS에서 블로그 게시물 목록을 가져와야한다.
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
export default Blog
pre-rendering에서 데이터를 가져오기 위해 nextjs 는 동일 한 파일에서 export된 async함수
getStaticProps를 허용합니다.
이 함수는 빌드시 호출되며 가져온 데이터를 props로 사전렌더링시에 페이지에 전달 할 수 있습니다.
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,
},
}
}
export default Blog
nextjs 를 사용하면 동적경로가 있는 페이지를 만들수 있습니다.
동적인 경로에 따라 데이터도 동적으로 변경되는경우
// This function gets called at build time
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 }
}