[공식문서 읽기] Next.js 12

April·2022년 1월 27일
0

Nextjs🚀

목록 보기
8/14
post-thumbnail

21.10.27 업데이트 된 next.js 12의 업데이트 내용 정리하기.

next.js 12의 업데이트 내용


✔️ 설치

npm i next@latest
또는
npm i next@12


주요 사항

  • 프레임워크에서 사용하던 컴파일러를 Rust 컴파일러로 대체함 : 프로젝트 빌드 속도 증가, 새로고침 속도 증가.
  • 미들웨어 : 서버 단에서 미들웨어 처리가 가능한 기능 추가.
  • React 18 지원 : React 18 버전을 지원.
  • <Image />AVIF 지원 : webP보다 20% 압출률이 더 좋은 AVIF 포맷 지원.
  • 봇 인식 ISR 폴백 : Google Bot 등의 웹 크롤러에 최적화된 SEO 동작 관련 내용.
  • 네이티브 ES 모듈 지원 : 표준화된 모듈 시스템과의 연계.
  • URL 가져오기 : 모든 URL에서 패키지 가져오기, 직접 모듈 설치가 필요 없음.
  • React Server Components : 컴포넌트 레벨에서 서버 사이드 단 로직까지 처리할 수 있다는 내용.

✔️ Rust Compiler

Rust 컴파일러로 대체하면서

  • 빌드속도 3개 빨라지고
  • 코드 변경으로 인한 실시간 새로고침 속도는 5배 증가
  • 아직은 검증 단계이므로 옵션 형식으로 사용 가능함
// next.config.js

module.exports = {
  swcMinify: true
}


✔️ Middleware (beta)

미들웨어 처리가 가능한 기능 추가 됨.

미들웨어를 사용하기 위한 파일 생성

// pages/_middleware.js

export function middleware(req, ev) {
  return new Response('Hello, world!')
}


✔️ React 18 Support

React 18를 적용하면서 Suspense, startTransition의 기능을 사용할 수 있다

npm install next@latest react@rc react-dom@rc

✅ 서버사이드 스트리밍

  • 서버사이드 Suspense 및 SSR 스트리밍 지원에 대한 기본 기능 제공
    • HTTP 스트리밍을 사용해서 서버 렌더링 구현 가능
  • 해당 기능 활성화하려면 아래 설정 추가
// next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true
  }
}
  • 활성화되면, 모든 페이지에서 SuspenseSSR 스트리밍을 사용할 수 있다.
import dynamic from 'next/dynamic'
import { lazy, Suspense } from 'react'

import Content from '../components/content'

// These two ways are identical:
const Profile = dynamic(() => import('./profile'), { suspense: true })
const Footer = lazy(() => import('./footer'))

export default function Home() {
  return (
    <div>
      <Suspense fallback={<Spinner />}>
        {/* A component that uses Suspense-based */}
        <Content />
      </Suspense>
      <Suspense fallback={<Spinner />}>
        <Profile />
      </Suspense>
      <Suspense fallback={<Spinner />}>
        <Footer />
      </Suspense>
    </div>
  )
}

✅ React Server Components

  • Component 레벨에서 동작하는 모든 것을 서버 단에서 처리할 수 있다.
    • 기존 SSR을 위한 getServerSideProps 또는 getStaticProps 등의 코드도 더 이상 필요하지 않게 된다고 한다
  • 해당 기능 활성화하려면 아래 설정 추가
// next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
    serverComponents: true
  }
}
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
  • 모든 Next.js 페이지의 이름을 .server.js로 변경하여 서버용 컴포넌트를 만들고, 서버용 컴포넌트 내부에서 직접 클라이언트 컴포넌트를 가져올 수 있다.
    • 서버에서 구성 요소를 실행하려면 .server.js을 파일 이름 끝에 추가
      • 에시) ./pages/home.server.js
    • 클라이언트 구성 요소의 경우 .client.js를 추가
      • 예시) ./components/avatar.client.js
    • 이러한 방식은 브라우저 단에서 Hydration 처리가 된다
  • 예시) <Home>은 항상 SSR, <Profile>은 클라이언트로 스트리밍되며, 클라이언트 런타임에 포함되지 않는다. <Content>은 클라이언트 측에서 Hydration 됨.
// pages/home.server.js

import { Suspense } from 'react'

import Profile from '../components/profile.server'
import Content from '../components/content.client'

export default function Home() {
  return (
    <div>
      <h1>Welcome to React Server Components</h1>
      <Suspense fallback={'Loading...'}>
        <Profile />
      </Suspense>
      <Content />
    </div>
  )
}

✔️ URL Imports

URL 자체로 외부 모듈을 Import를 할 수 있는 기능

module.exports = {
  experimental: {
    urlImports: ['https://cdn.skypack.dev']
  }
}

// 또는
import confetti from 'https://cdn.skypack.dev/canvas-confetti'

✔️ Bot-Aware ISR Fallback

Next.js가 페이지를 렌더랑 하는 방법에는 static generation과 server-side rendering 방식이 있다.

ISR(Incremental Static Generation): getStaticProps 함수를 활용한 static generation 방식은 언제나 빌드 시점 에 페이지를 생성하지만, ISR 방식은 일정 주기마다 데이터의 최신 여부를 검사하고 업데이트된 데이터로 페이지를 다시 생성한다

ISR로 작성된 페이지에서 fallback : true로 설정되게 되면

  • 새롭게 보여주기 전의 정보로 작성된 정적 페이지를 보고있게 되는데
  • 이 과정에서 크롤러 봇이 해당 페이지에 방문해서 크롤링하다가 페이지가 변경되면 의도하지 않은 크롤링 수집이 되어버리는 문제가 발생

Next.js 12에서

  • 일반 유저에선 ISR의 동작 그대로 수행하고,
  • 크롤러라면 server-render ISR 페이지를 받아보게 된다

✔️ Smaller images using AVIF

이미지 압축 포맷 AVIF라는 형식을 <Image> 태그에서 옵션으로 사용할 수 있다.

module.exports = {
  images: {
    formats: ['image/avif', 'image/webp']
  }
}

브라우저가 AVIF를 지원할 때만 정상적으로 제공이 되고, 그렇지 않으면 WebP를 지원하는지 판단 후 WebP를 제공하는 방식이다. 모두 제공되지 않으면 원본 이미지 형식이 제공된다.

profile
🚀 내가 보려고 쓰는 기술블로그

0개의 댓글