• nextjs13如何进行服务端渲染?


    目录

    一、创建一个新项目

    二、动态获取后端数据进行服务端渲染出现的问题

    三、nextjs13如何进行服务端渲染


    nextjs13是nextjs的一个重大升级,一些原本在next12当中使用的API在nextjs13上使用十分不便。本文将着重介绍在nextjs13及以上版本当中进行服务端渲染的方法。

    一、创建一个新项目

    npx create-next-app@latest

    项目安装成功后,不可避免的要安装其他依赖进行项目开发。但是,在新项目下安装其他依赖的话,终端会爆出以下错误:

     以上错误可能会导致依赖安装不成功,解决的办法是删除node_modules,然后进行pnpm install(本人是用pnpm进行安装包的管理),然后在进行依赖的安装即可。

    二、动态获取后端数据进行服务端渲染出现的问题

    Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

    在我做的很多项目当中都使用axios进行前后端数据交互,几乎都已经形成习惯了。因此,在进行nextjs13项目当中,我也引入了axios安装包进行前后端数据交互,在客户端数据请求的时候没问题。在开发环境当中,进行服务端数据渲染没有问题。但是,在生产环境中,后端数据变化后,页面上进行服务端请求的数据,并没有发生变化。

    问题在于使用axios进行服务端数据请求,在生产打包后,nextjs会将请求到的数据打包进去,生成一个静态的页面。因此,在后端数据发生变化后,静态页面的数据并不会跟着发生变化。

    页面上的280000000000000000就是在build的时候,从后端请求回来的数据,生成了一个静态的页面,以后无论后端数据如何变化这个值都不会发生变化,除非重新部署。但是,这种效果很显然不是需求所想要的。既然是从后端拿数据,目的就是当时后端数据发生变化,页面的内容也跟着一起变化,而不是一直不变。写到这里,可能有人提出封装一个组件,进行客户端渲染。这就是个笑话了,使用nextjs的目的就是要进行服务端渲染,以利于SEO。如果什么事情都要客户端去做,那还不如用react构建一个单页面应用,还用nextjs干嘛呢。

    三、nextjs13如何进行服务端渲染

    遇到问题,凡事儿第一步就是先看官方文档。在官方文档的Fetching Data on the Server with fetch

    其实已经给出了答案:

    nextjs扩展了本地获取Web API,允许您为服务器上的每个获取请求配置缓存和重新验证行为。React扩展了fetch,以便在呈现React组件树时自动记住fetch请求。你可以在服务器组件、路由处理程序和服务器操作中使用带有async/await的fetch。

    也就是说使用fetch进行数据请求,可以进行服务端组件数据渲染。

    home.tsx

    1. import fetch from '@/plugins/request/fetch';
    2. import Image from 'next/image';
    3. import HomeEarn from '@/compontent/HomeEarn';
    4. import axios from '@/plugins/request/http';
    5. export default async function Home() {
    6. const data = await fetch.get('earn_info/liquidity_earn_amount');
    7. console.log('🚀 ~ file: page.tsx:18 ~ Home ~ data:', data);
    8. /* const res = await fetch(
    9. 'https://node3.ibax.io:8880/api/v1/earn_info/liquidity_earn_amount',
    10. { next: { revalidate: 0 } }
    11. );
    12. const data = await res.json();
    13. console.log('🚀 ~ file: page.tsx:22 ~ Home ~ data:', data); */
    14. return (
    15. <main className="flex min-h-screen flex-col items-center justify-between p-24">
    16. <div>
    17. {/* {data.data.amount} */}
    18. <HomeEarn>HomeEarn>
    19. <span>{data.amount}span>
    20. <span className="ml-1">{data.tokenSymbol}span>
    21. div>
    22. main>
    23. );
    24. }

     fetch封装:

    1. import local from '@/network/local';
    2. export type env = 'test' | 'production' | 'development';
    3. const http = {
    4. Api() {
    5. console.log(process.env.BUILD_ENV);
    6. const currNetwork = local[process.env.BUILD_ENV as env];
    7. console.log('🚀 ~ file: fetch.ts:7 ~ Api ~ currNetwork:', currNetwork);
    8. // console.log('🚀 ~ file: fetch.ts:5 ~ Api ~ currNetwork:', currNetwork);
    9. return currNetwork.api;
    10. },
    11. async get(url: string, params?: any) {
    12. const api = this.Api();
    13. const paramsUrl = params
    14. ? `?${new URLSearchParams(params).toString()}`
    15. : '';
    16. const res = await fetch(`${api}/api/v1/${url}${paramsUrl}`, {
    17. headers: {
    18. method: 'GET',
    19. 'Content-Type': 'application/json; charset=utf-8',
    20. mode: 'cors'
    21. // 'Content-Type': 'application/x-www-form-urlencoded',
    22. },
    23. // cache: 'force-cache'
    24. cache: 'no-cache'
    25. });
    26. if (!res.ok) {
    27. // This will activate the closest `error.js` Error Boundary
    28. throw new Error('Failed to fetch data');
    29. }
    30. try {
    31. const data = await res.json();
    32. if (data.code === 0) {
    33. return data.data;
    34. } else {
    35. return null;
    36. }
    37. } catch (error) {
    38. return null;
    39. }
    40. },
    41. async post(url: string, data?: any) {
    42. const api = this.Api();
    43. const res = await fetch(`${api}/api/v1/${url}`, {
    44. headers: {
    45. method: 'POST', // *GET, POST, PUT, DELETE, etc.
    46. 'Content-Type': 'application/json'
    47. // 'Content-Type': 'application/x-www-form-urlencoded',
    48. },
    49. // cache: 'force-cache',
    50. cache: 'no-cache',
    51. body: data ? JSON.stringify(data) : ''
    52. });
    53. if (!res.ok) {
    54. // This will activate the closest `error.js` Error Boundary
    55. throw new Error('Failed to fetch data');
    56. }
    57. try {
    58. const data = await res.json();
    59. if (data.code === 0) {
    60. return data.data;
    61. } else {
    62. return null;
    63. }
    64. } catch (error) {
    65. return null;
    66. }
    67. }
    68. };
    69. export default fetch;

  • 相关阅读:
    leetcode数组必刷题——二分查找、移除元素、有序数组的平方、长度最小的子数组、螺旋矩阵、螺旋矩阵 II
    mybatis-plus 分页插件配置
    vim常用命令
    输入输出系统
    2024.6.17 作业 xyt
    Tomcat使用教程(超详细)
    GeoServer入坑(一)--DEM地形图发布
    STM32 cubemx hal库huart串口接收不到第一帧数据或数据全为0的问题
    记录小白第一次EDUsrc:任意密码漏洞
    机器学习方法之k近邻方法的综述
  • 原文地址:https://blog.csdn.net/sinat_36728518/article/details/136376647