Next.js是一个非常流行的React框架,它提供了开箱即用的服务器端渲染(Server-SideRendering,SSR)能力,我们可以轻松地使用Next.js轻松实施SSR并将其部署在Vercel上。但是Vercel在国内没有服务节点,SSR时通过Vercel服务器请求国内服务接口有一定比例失败,影响页面渲染。因此,我们需要加入Client-SideRendering(CSR)的逻辑作为掩护,以提高渲染的成功率。在Next.js中,我们可以通过在页面组件中添加getServerSideProps方法来触发SSR。比如我们调用接口根据页面URL上的路径参数id获取详细信息,并将数据提供给页面组件方法进行渲染。代码如下:interfaceProps{detail:Detail;}asyncfunctiongetServerSideProps(context:GetServerSidePropsContext):Promise<{props:Props}>{const{id}=context.params;constdetail=awaitgetDetail(id);return{props:{detail,},};}Next.js会将上下文传递给getServerSideProps方法,其中包含路由和请求参数信息;我们返回一个包含props的对象,在服务端渲染中通过props将获取到的数据提供给页面组件。constPage:React.FC (props);const路由器=useRouter();constisPropsEmpty=Object.keys(props).length===0;useEffect(()=>{if(isPropsEmpty){constcontext:GetServerSidePropsContext={locale:router.locale,locales:router.locales,defaultLocale:router.defaultLocale,params:router.query,query:router.query,resolvedUrl:router.asPath,req:{}未知,res:{}未知,};getServerSideProps(context).then(setNewProps);}},[]);if(newProps){returnReact.createElement(component,newProps);}返回空值;};HoC.displayName=`Hoc(${component.name})`;returnHoC;}逻辑和前面的实现基本一样,在高层组件中,如果SSR失败,我们在浏览器端再次调用getServerSideProps发起请求。这时候我们就需要构造一个和Next.js一致的context。这里我们选择从next/router获取相关信息并构建。最后,我们将页面组件传给高阶组件,返回一个新的页面组件并导出。导出默认withCSR(Page,getServerSidePropsOrigin);页面组件访问的两步抽象完成后,我们页面组件降级的实现就变得非常简单了。在不需要修改页面组件和getServerSideProps的基础上,我们只需要添加如下一行:import{withCSR,getServerSideProps}from'../ssr-fallback';exportconstgetServerSideProps=createGetServerSidePropsFunction(getServerSidePropsOrigin);导出默认withCSR(Page,getServerSidePropsOrigin);到目前为止,我们已经实现了从SSR到CSR的优雅降级。进一步抽象成一个npm包我们将上述逻辑抽象成一个npm包next-ssr-fallback,并进一步抽象出SSRFallback类,简化getServerSideProps的传递。用法如下:importFallbackSSRfrom'next-ssr-fallback';constfallbackSSR=newFallbackSSR({getServerSideProps:getServerSidePropsOrigin,});exportconstgetServerSideProps=fallbackSSR.createGetServerSidePropsFunction();exportdefaultfallbackextSSR.withCSR-Page);ssr-fallback的GitHub仓库:https://github.com/crazyurus/next-ssr-fallback还有一个连接next-ssr-fallback的Next.js项目recruit-pc供参考,项目部署在Vercelhttps://recruit-pc.vercel.app总结当我们在Next.js中遇到SSR渲染失败的问题时,我们选择降级为CSR来提高渲染成功率,并将这部分实现逻辑抽象为next-ssr-fallback可以在其他项目中复用,实现更优雅的降级。如果大家有其他SSR降级相关的做法,欢迎分享
