패스트컴퍼스 강의를 듣고 정리한 내용입니다.
pages/index.js => /
pages/ssg.js => /ssg
pages/products/[slug].js => /products/[slug]
Pre-rendering
: next.js 는 모든 페이지를 Pre-rendering 함
( * Pre-renders : HTML와 같은 기초적인 UI요소들을 미리 그린다.)
NO Pre-rendering : 백지 상태에서 js가 실행이 된 후에 화면을 그린다.
SEO : 검색엔진 최적화
Pre-rendering 를 하면 Client 처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공 할 수 있다.
: NextJs에서 제공하는 최적화 image component
npx create-next-app --example image-component image-app
참고 사이트 : https://github.com/vercel/next.js/tree/canary/examples/image-component , https://nextjs.org/docs/api-reference/next/image
.prettierignore 파일 추가
node_modules
.next
public
.prettierrc 파일 추가
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false
}
package.json 파일
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"prettier-fix": "prettier --write ."
},
.jsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
}
}
Q : pages/index.js & src/pages/index.js 둘 중 어떤게 우선순위가 높을까?
A : pages/index.js 가 더 높다. pages 폴더가 있으면 src/pages 폴더는 반영이 안된다.(무시됨)
pages/product/first-item.js => /product/first-item
pages/settings/my/info.js => /settings/my/info
/settings/my/ 에 접근 하고 싶다면 /pages/settings/my/index.js 를 생성
/settings/ 에 접근 할때도 /pages/settings/index.js 를 생성
pages/category/[slug].js => /category/[slug] (ex. /category/apple)
pages/[username]/info.js => /[username]/info (ex. /jimmy/info)
pages/cart/[...slug].js => /cart/[...slug]
(ex. /cart/2022/06/24 , [slug].js의 여러 depth 버전)
* useRouter 훅 사용
//localhost:3000/category/food
import {useRouter} from "next/router";
export default function CategorySlug() {
const router = useRouter()
const {slug} = router.query
return (
<>
<h1 className="title"> SLUG : {slug}</h1>
</>
)
}
SLUG : food
//localhost:3000/category/food?from=event
router.query 는 url 상 ? 뒤에 오는 값(쿼리 값) 도 사용 가능 함
export default function CategorySlug() {
const router = useRouter()
const {slug, from} = router.query
return (
<>
<h1 className="title"> SLUG : {slug} , FROM : {from}</h1>
</>
)
}
SLUG : food , FROM : event
이렇게 url/? 뒤의 커리 값(from)도 받아올 수 있다.
//localhost:3000/category/food?from=
SLUG : food , FROM :
from값이 없을땐 undefined 로 처리 됨.
//localhost:3000/category/food?from=event&slug=book
: 또 다른 예시 쿼리 안에 slug값이 있다면?
SLUG : food , FROM : event
페이지 구조 안에 있는 [slug] 값이 적용된다.
즉 위 URL은 food 값이 적용 됨. book값은 무시
//localhost:3000/category/food?from=event&from=book
: 또 다른 예시 쿼리 안에 from값이 중복으로 있다면?
SLUG : food , FROM : eventbook
쿼리 값은 둘다 갖고온다.
//localhost:3000/dorikoo/food
export default function UserNameInfo() {
const router = useRouter()
const {username,info} = router.query
return (
<>
<h1 className="title"> {username}'s {info} Info</h1>
</>
)
}
dorikoo's food Info
//localhost:3000/cart/1999/12/31
export default function CartDateSlug() {
const router = useRouter();
const {date} = router.query
return (
<>
<h1 className="title"> CartDateSlug{JSON.stringify(date)}</h1>
</>
)
}
CartDateSlug["1999","12","31"]
: 배열로 데이터가 들어온다.
//localhost:3000/cart/ 로 접근할때, pages/cart/index.js 를 안 만들고 접근 할 수 있는 방법.
<Link href="/cart/2023/01/01"><a>2023년 1월 1일 로</a></Link>
<button onClick={()=>{router.push('/cart/2023/01/01')}}>2023년 1월 1일로</button>
2023년 1월 1일 로 와 2023년 1월 1일로 가 같은 개념 - button ui의 차이
: getServerSideProps / getStaticProps 등을 다시 실행시키지 않고, 현재 상태를 잃지 않고 url을 바꾸는 방법 (ex. 스크롤 이벤트시 페이지 번호를 주고 싶을때)
location.replace(“url”): 로컬 state 유지 안됨(리렌더)
<button onClick={()=>{
alert('edit');
setClicked(true);
location.replace('/settings/my/info?status=editing')
}}>edit(replace)</button>
router.push(url): 로컬 state 유지 / data fetching은 일어남
<button onClick={()=>{
alert('edit');
setClicked(true);
router.push('/settings/my/info?status=editing')
}}>edit(push)</button>
router.push(url, as, { shallow: true }): 로컬 state 유지 / data fetching
<button onClick={()=>{
alert('edit');
setClicked(true);
router.push('/settings/my/info?status=editing',undefined,
{shallow : **true**})
}}>edit(shallow)</button>
Shallow Routing 테스트
export async function getServerSideProps() {
console.log('server')
return {
props: { time: new Date().toISOString() },
}
}
export default function MyInfo() {
const router = useRouter()
const [clicked, setClicked] = useState(false)
const {status = 'initial'} = router.query
return (
<>
<h1 className="title"> My Info</h1>
<h1 className="title"> Clicked : {String(clicked)}</h1>
<h1 className="title"> Status : {status}</h1>
<button onClick={()=>{
alert('edit');
setClicked(true);
location.replace('/settings/my/info?status=editing')
}}>edit(replace)</button>
<br/>
<button onClick={()=>{
alert('edit');
setClicked(true);
router.push('/settings/my/info?status=editing')
}}>edit(push)</button>
<br/>
<button onClick={()=>{
alert('edit');
setClicked(true);
router.push('/settings/my/info?status=editing',undefined,{shallow : true})
}}>edit(shallow)</button>
</>
)
}
두번째 버튼 클릭시(router.push) : Clicked = true , Status : editing 둘다 데이터 변경됨. getServerSideProps() 도 동작.
세번째 버튼 클릭시(router.push {shallow : true}) : 두번째 버튼과 화번은 동일, Clicked = true , Status : editing 둘다 데이터 변경됨. 하지만 getServerSideProps() 가 동작하지 않음. (서버는 실행하지 않음)