서두에
React 생태계에서, SSR 서포트가 가장 우수한 것은 아마도 Next.js 일 것입니다. 하지만 SSR 은 Next.js 의 전부가 아니며, 그 가 제공하는프리렌더링서포트 중 하나일 뿐입니다:
-
SSG(Static Site Generation/Static Generation): 정적 생성. 컴파일 시에 정적 HTML 을 생성
-
SSR(Server-Side Rendering): 서버사이드 렌더링. 사용자 리퀘스트 도래 시 동적으로 HTML 을 생성
CSR 시작 전에 다양한 방식으로 페이지 콘텐츠를 미리 렌더링하여, 퍼스트 스크린 성능을 향상시키는 동시에 SEO 의 요구를 충족시키는 것. 이것이 바로 Next.js 의 가장 핵심적인 특성입니다
不仅如此,Next.js 는 혼용 서포트도 제공하며, 서로 다른 렌더링 모드를 결합하여 사용하고, 상호 보완적으로 융합시킬 수 있습니다. 예를 들어:
-
ISR(Incremental Static Regeneration): 증분 정적 재생성. 런타임에 정기적으로 정적 HTML 을 재생성
-
SSG 에서 SSR 로 다운그레이드: 미리 생성된 정적 HTML 에 히트하지 않을 경우, 즉시 SSR 을 실행
-
정적 캐시付き SSR: SSR 완료 후, 결과를 캐시.次回 정적 캐시에 히트하면 직접 반환 (SSG 와 동등)
-
SSG 와 CSR 의 결합: 컴파일 시에 정적 부분 (페이지 외곽) 을 생성.CSR 로 동적 부분 (페이지 콘텐츠) 을 채움
-
SSR 과 CSR 의 연동:URL 직접 액세스는 더 빠른 SSR.SPA 전환은 체험이 더 우수한 CSR
이러한 섬세한 혼합 렌더링 서포트로 인해, 각종 렌더링 모드가 그 우위성을 충분히 발휘할 수 있으며, Next.js 도 한층 더 빛을 발합니다
SSG + SSR
SSG 는 SSR 의 렌더링 프로세스를 컴파일 시로 앞당기는 것에 해당하며, 이로 인해这部分의耗时를 최적화하고, 극히 우수한 페이지 로드 성능을 달성합니다. 그러나 명백한 결함도 존재합니다——정적 콘텐츠의 렌더링에만 사용 가능. 이로 인해 본래 매우 뛰어난 방안이 활약의 장을 찾기 어려워집니다. 그렇다면, 그 적용 시나리오를 확대할 방법이 있을까요?
있습니다. 핵심은「정적」을 어떻게 이해하는가입니다. 정적, 동적은 실제로 콘텐츠의 변화 빈도를 기술하는 것입니다. 거의 (영원히) 변화하지 않거나, 변화 빈도가 매우 낮은 콘텐츠를, 우리는 정적 콘텐츠라고 부릅니다. 따라서콘텐츠의 변화에 대처하는 방법을 생각하면, SSG 의 적용 시나리오를 빈번히 변화하지 않는「정적 콘텐츠」에서 빈번히 변화하지 않는「동적 콘텐츠」로 확대할 가능성이 있습니다
極限情况下,「빈번히 변화하지 않는」은「매번 변화하는 것은 아니다」와 동치입니다. 즉, 실시간/퍼스널라이즈 등 매순간 동적으로 변화하는 콘텐츠를 제외하고, 나머지 시나리오는 모두 SSG 를 사용 가능합니다. 물론, 전제는 콘텐츠가 필요한 빈도로 업데이트되어生效하는 것을 보증하는 것입니다. 콘텐츠 업데이트는 실제로는 재 SSG 이므로, 업데이트 타이밍이 부족할 뿐입니다……
또 하나의それほど 명확하지 않은 제한은 정적 콘텐츠의 수량입니다. 렌더링 작업은 컴파일 시에 모두 완료되어야 하므로, 정적 데이터가 100 만 건 있으면, 100 만 부의 HTML 을 컴파일 생성해야 합니다. 1 회의 컴파일에 며칠이 걸릴 수 있습니다……컴파일 비용 (시간/머신 불문) 은 콘텐츠 수량에 따라 不断增加합니다. 이는 SSG 렌더링 모드에 생래備わった 문제입니다. 無解のように 보입니다. 除非, 컴파일 시에 전량 페이지를 생성하지 않는다면……
사용자 리퀘스트面向의 SSR 은 恰好한 업데이트 타이밍을 제공할 수 있으며, 동시에 컴파일의 하류로서, SSR 은 누락을 막을 기회가 있습니다. 그래서, SSG 와 SSR 은 一拍即合.SSG 는 小部分의 핫페이지만을 컴파일 생성하고, 나머지는 런타임에 SSR 로 생성합니다. 사용자 리퀘스트 도래 시, 콘텐츠의 업데이트가 필요한지에 따라 SSR 로 재생성할지 前回의 생성물을 사용할지를 결정합니다:
Instead, you may statically generate a small subset of pages and use fallback: true for the rest. When someone requests a page that's not generated yet, the user will see the page with a loading indicator. Shortly after, getStaticProps finishes and the page will be rendered with the requested data. From now on, everyone who requests the same page will get the statically pre-rendered page.
Inspired by stale-while-revalidate, background regeneration ensures traffic is served uninterruptedly, always from static storage, and the newly built page is pushed only after it's done generating.
이와 같이, SSG 는 적용 시나리오를 확대하고 (고빈도 변화의 콘텐츠, 編みきれない 海量 콘텐츠), SSR 은 성능 우위성을 획득합니다 (정적 캐시):
This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.
P.S. SSG 와 SSR 의 결합에 대한 상세 정보는, When is fallback: true useful?, Incremental Static Regeneration 참조
SSG + CSR
SSR 과 비교하여, SSG 의 비용은 더 낮고, 로컬에서 정적 HTML 을 컴파일 생성하여, Web 서버 또는 CDN 에 호스트하기만 하면 프리렌더링에 의한 로드 성능 향상을 누릴 수 있습니다. 애플리케이션 서버의 고액 머신 비용도 없고, SSR 온라인 서비스의 가용성이나 운용 보수 작업을 걱정할 필요도 없습니다
SSR 을借助하여 SSG 의 적용 시나리오를 확대하려면, 그에 따른 비용 문제를 고려해야 합니다. 그렇다면, 더 비용이 낮은 방법이 있을까요?
있습니다. 그러나 체험 면에서 약간의 타협이 필요합니다.SSG 가 정적 콘텐츠의 렌더링을 得意로 하고 있는既然, 페이지 콘텐츠를 动静 분리하고, 페이지 상의 정적 부분을 SSG 에 컴파일 생성시키고, 나머지 동적 부분은 계속 CSR 로 채우는것이 가능합니다:
First, immediately show the page without data. Parts of the page can be pre-rendered using Static Generation. You can show loading states for missing data.
Then, fetch the data on the client side and display it when ready.
SSG 와 CSR 을 결합하면, 페이지 로드의 백스크린 시간을 단축함과 동시에, SSR 의 추가 비용도 회피할 수 있습니다. 그러나, 美中不足한 것은 로드 체험이 순수한 SSG 보다 떨어진다는 것입니다.畢竟 (사용자가 더 관심 가질 가능성이 있는) 동적 콘텐츠는 클라이언트 사이드에서 이차 렌더링되어初めて呈現되며, SSG 와 같이 한 번에 완전한 콘텐츠를 呈現하는 것은 아닙니다. 따라서, 이 방식이 가져오는 것은 더 많은 체험 향상입니다. 사용자 지각 상 페이지 로드가 빨라졌다고 느낍니다. 일종의 점진식 렌더링 모드라고 할 수 있습니다
P.S. SSG 와 CSR 의 결합에 대한 상세 정보는, Fetching data on the client side 참조
SSR + CSR
SSG, SSR, CSR 의 3 개가 둘씩 결합하는 중에서, 가장 耐人尋味한 것은 아마도 이 셋째의 조합——SSR 과 CSR 의 결합입니다
hydrate 는 제외하고, SSR 과 CSR 에게는 아직 결합점이 있을까요?
물론 있습니다. SSR 은 페이지 로드 프로세스 중의 백스크린 시간을 효과적으로 단축할 수 있으며, 동시에 페이지 콘텐츠를 한 번에 완전히 呈現하는 상쾌한 체험을 제공할 수 있습니다. 이와 비교하여, CSR 의 렌더링 성능은 클라이언트 환경에 의존, 데이터 리퀘스트의 지체 등의 결점이 무한대 로 커져, CSR 의 高光 우위성을 덮어隠을 정도가 됩니다:
-
무새로고침으로 콘텐츠를 로드
-
사용자 행동에 따라 프리로드 가능
이러한 우위성은 퍼스트 스크린 로드 프로세스 중에서는 확실히 體現되지 않습니다. 따라서 페이지 로드 성능만을 본다면, SSR 이 CSR 에 완승하며, 둘 중에서 1 개를 선택하면 되고, 결합의 필요는 없습니다. 그러나, 시점을 사용자 조작의 전체 플로우로 提升到げ면, CSR 과 SSR 이 매우 融和한 방식으로 완벽하게 결합할 수 있음을 알 수 있습니다:
-
퍼스트 스크린 로드는 SSR 로: 사용자가 URL 을 통해 직접 액세스하는 것이 홈 페이지라도 二級, 三級 페이지라도, SSR 은 페이지를 최속으로 呈現할 수 있습니다
-
站内 전환은 CSR 로: 그後の交互操作中의 페이지 전환은, CSR 로 시ーム리스하게 새 콘텐츠를 로드. 더욱이 사용자 행동을 예측하여 목표 페이지의 콘텐츠를 미리 로드하는 것도 가능합니다
즉, 퍼스트 스크린 로드 작업은 더 빠른 SSR 에게 맡기고, 交互 프로세스 중에는 CSR 에게 大展身手시키는것입니다:
When you request this page directly, getServerSideProps runs at the request time, and this page will be pre-rendered with the returned props.
When you request this page on client-side page transitions through next/link or next/router, Next.js sends an API request to the server, which runs getServerSideProps. It'll return JSON that contains the result of running getServerSideProps, and the JSON will be used to render the page. All this work will be handled automatically by Next.js, so you don't need to do anything extra as long as you have getServerSideProps defined.
Next.js 는 이 결합 방식에 내장 서포트를 제공할 뿐만 아니라, 가시 영역 중의 站内 링크를 자동으로 프리로드하는 것도 가능합니다:
prefetch - Prefetch the page in the background. Defaults to true. Any <Link /> that is in the viewport (initially or through scroll) will be preloaded. Prefetch can be disabled by passing prefetch={false}.
P.S. SSR 과 CSR 의 결합에 대한 상세 정보는, Only runs on server-side 참조
아직 댓글이 없습니다