美文网首页前端面试工程师大前端从入门到跑路
React笔记五:使用Next.js实现React SSR的优雅

React笔记五:使用Next.js实现React SSR的优雅

作者: brandonxiang | 来源:发表于2021-05-09 16:25 被阅读0次

    前言

    React SSR最成熟的开源框架是Next.js,这么多年保持着强劲的生命力,它的创始团队vercel(曾用名zeit),如今更关注于SSR和serverless的结合。随着服务端的容器化技术以及serverless技术不断完善,在国外可能SSR的降级已经不是一个必要命题。但是,考虑到国内的服务环境,今天我们还是有必要从前端的技术点讨论一下如何去实现SSR的优雅降级。

    旧版本的Next.js是利用getInitProps实现服务端渲染以及静态站点生成。在Next.js 9.3版本后,getInitProps这个api被替换成为三个不同的api,分别是:

    • getStaticProps (静态页面生成SSG): 构建的时候生成页面
    • getStaticPaths (静态页面生成SSG): 根据构建内容去生成动态路由
    • getServerSideProps (服务端渲染SSR): 在每个请求中在服务端获取数据渲染页面

    这三个api的使用是对一个项目中不同页面的更细程度的划分,它可以有效区分哪些页面走SSR、哪些页面走CSR和SSG。高效的划分了这三种不同的渲染模式。

    What is JAMstack ?

    静态页面生成SSG这种模式更加符合JAMstack的标准,所有的页面都是提前预渲染的,静态的页面可以直接托管在CDN上,有效降低运维成本,有助于你“高效下班”。Next.js官方建议你优先使用静态页面生成,不得已才使用服务端渲染。但是静态页面不能满足你的所有case。只有以下情况才比较适合静态页面生成:

    • 数据能通过CMS接口有效渲染
    • 数据能够公开缓存,并且不能用户特有的
    • 页面必须预渲染,并且SEO敏感

    Next.js已经能够在一个项目不同路由支持不同的渲染模式。

    源码参考 brandonxiang/example-nextjs ,页面的逻辑放在modules文件夹里面,用一个自定义的函数getPrerenderProps来保证页面的预渲染逻辑。这个预渲染逻辑如下,即获取数据传递到组件当中与Next.js的预渲染api类似。

    // modules/Home.tsx
    export const getPrerenderProps =  async (ctx) => {
      // SSG读取环境变量,并作为兜底参数
      const defaultLimits =  process.env.limits || 0;
      // SSR和CSR动态渲染从URL上获取参数
      const _limits =  (ctx?.query?._limits) || defaultLimits;
      // 获取远程动态数据
      const res = await axios.get(
       'https://jsonplaceholder.typicode.com/photos?_limit=' + _limits
      )
      // 传递给各种渲染模式
      return { props: { photos: res.data } }
    }
    

    自定义页面渲染函数Page来保证页面dom的渲染,这里的目标是“一份核心代码,多种渲染模式”。数据photos则会在页面中渲染。

    // modules/Home.tsx
    function Home({ photos }) {
      let _photos =  photos || []
      return (
        <div className="photos">
          {
            _photos.map((photo, index) => (
              <figure key={index}>
                <img src={photo.thumbnailUrl} alt={photo.title} />
                <figcaption>{photo.title}</figcaption>
              </figure>
            ))
          }
        </div>
      )
    }
    
    export const Page = Home;
    

    然后将它渲染到三种不同的模式当中。由于 Next.js 的文件路由设定,页面需要被设置成为三种:

    • index.js SSR模式
    • index_ssg.js SSG模式
    • index_csr.js CSR模式

    Next.js如何实现SSR

    SSR模式需要将自定义的getPrerenderProps 输出到页面级别Next.js API的getServerSideProps当中,获取数据的逻辑将会提前在服务端完成。此时,服务端可以实现页面的动态渲染。Page则返回给整个页面的渲染函数。

    // index.js
    export { 
      Page as default, 
      getPrerenderProps as getServerSideProps 
    } from '../modules/Home';
    

    Next.js如何实现CSR

    CSR模式则是自定义的getPrerenderProps 在useEffect中渲染,在页面加载之后,重新对页面进行渲染,达到一个客户端渲染的效果。路由参数发生变化,页面会重新进行渲染,保证的页面的动态可用。这种模式页面的渲染会比较慢,时长主要是请求时长。

    // index_csr.js
    export default () => {
        const router = useRouter();
        const [extraProps, setExtraProps] = useState({});
    
        useEffect(() => {
            getPrerenderProps(router).then(({props}) => {
                setExtraProps(props);
            }) 
        }, [router]);
    
        return <Page {...extraProps}/>
    }
    

    Next.js如何实现SSG

    SSG则是静态预渲染,参数不能动态从路由传入,只能构建的时候以环境变量的形式传入,所以页面渲染需要采用特殊的兼容读取方式。

    将自定义的getPrerenderProps 输出到页面级别Next.js API的getStaticProps当中,实现静态渲染。

    // index_ssg.js
    export { 
      Page as default, 
      getPrerenderProps as getStaticProps 
    } from '../modules/Home';
    

    如何将SSR降级成为CSR

    SSR服务端渲染由于是依赖服务器资源,在流量过大的情况下,有可能会出现服务不可用的情况,返回特殊的错误码例如500等。这时候我们可以实现优雅降级,利用 nginx 做对应的流量分发,当SSR页面返回异常错误的时候,nginx会将流量导入到CSR页面当中。

    SSR页面和CSR页面基于Next.js采用同样的业务逻辑编写方式,有效保证页面逻辑的一致性,一份代码两端复用。

    SSR优雅的降级

    总结

    Next.js是非常成熟高效的服务端渲染框架,本文通过一些取巧的方式来实现“一份代码,多种渲染方式”,既能提高页面的性能,也能够保证页面的优雅降级。多种渲染模式采用同一份代码,保证了逻辑的一致性,有效地为QA节省了回归人力。在“质量”和“性能”上找到了一个很好的平衡点。

    相关文章

      网友评论

        本文标题:React笔记五:使用Next.js实现React SSR的优雅

        本文链接:https://www.haomeiwen.com/subject/yhlmoktx.html