服务端渲染nextjs项目接入经验总结分析

 更新时间:2023年11月09日 10:00:50   作者:路边县  
这篇文章主要为大家介绍了服务端渲染nextjs项目接入经验总结分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

背景介绍

服务端渲染 nextjs@13 项目接入经验总结,本文重点介绍基本知识点/常用的知识点/关键知识点

为提高首屏渲染速度减少白屏时间提高用户体验及丰富技术面,开始调研和接入nextjs框架

nextjs是一套成熟的同构框架(一套代码能运行在服务端也能运行在浏览器)对比传统的客户端渲染的优势是首屏是带数据的。其它后续操作是一样的。理论上能比客户端渲染看到数据能快个100-200ms具体看实际统计,

服务端渲染大概流程图(图片来源于网络)

客户端渲染大概流程图

对比流程图服务端渲染更加简洁。

使用

环境

Node.js >= 18.17 nextjs13

安装

npx create-next-app@13

选择 src/ 目录 和 使用 App Router

大致目录结构

...
package.json
public
node_modules
src
|- app
  |- page.tsx
  |- layout.tsx
  |- blog
    |- page.tsx
    |- layout.tsx
  |- docs
    |- page.tsx
    |- layout.tsx
| -services
| -utils
...

路由

大致路由为

注意这是约定路由 需要用page.tsx layout.tsx文件命名

内置API

head标签  import Head from 'next/head'

图片标签 import Image from 'next/image'

跳转标签 import Link from 'next/link'

script
import Script from 'next/script'

路由相关
import { useRouter, useSearchParams, useParams, redirect } from 'next/navigation'

请求头 import { headers } from 'next/headers'

服务器组件和客户端组件

服务器组件需要运行在服务器
主要特点有请求数据,服务端环境等

客户端组件运行在浏览器 标识 文件第一行增加 'use client'主要特点有事件,浏览器环境,react hooks

比较

操作服务器组件客户端组件
请求数据
访问后端资源(直接)
在服务器上保留敏感信息(访问令牌、API密钥等)
保持对服务器的大量依赖性/减少客户端JavaScript
添加交互性和事件侦听器(onClick、onChange等)
使用状态和生命周期(useState、useReducer、useEffect等)
浏览器API
自定义hooks
使用React Class组件

开始填充业务代码

修改html页面

文件位置在/src/app/layout.tsx,可以进行标题修改等一系操作

import Head from "next/head";
export default async function RootLayout(props: any) {
  return (
 <html lang="en">
   <Head>
     <title>页面标题</title>
   </Head>
   <body>{props.children}</body>
 </html>
  );
}

获取数据

async function getData() {
  const res = await fetch('https://xxxxx.com/', { cache: 'no-store' })
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
  return res.json()
}
export default async function Page() {
  const data = await getData()
  return <main>{JSON.stringify(data, null, 2)}</main>
}

把浏览器的信息转发到服务端
这个例子是cookie有需求可以用放其它的

import { headers } from 'next/headers'
const getData = async () => {
  const headersList = headers();
  const cookie = headersList.get('Cookie');
  const res = await fetch('https://xxx.com', {
 cache: 'no-store',
 headers: { cookie }
  });
  return res.json()
};

处理全局通讯和数据

在/src/app 目录下增加 context.tsx/src/app/context.tsx

'use client';
import { createContext, useMemo } from 'react';
import { useImmer } from 'use-immer';
export const PropsContext = createContext({});
export function Context({ children, ...other }: any) {
  const [GlobalState, setGlobalState] = useImmer<any>({
    ...other
  });
  const providerValue = useMemo(
    () => ({ GlobalState, setGlobalState }),
    [GlobalState]
  );
  return (
    <PropsContext.Provider value={providerValue}>
      {children}
    </PropsContext.Provider>
  );
}

 /src/app/layout.tsx

import React from 'react';
import { headers } from 'next/headers'
import { Context } from './context';
const getData = async () => {
  const headersList = headers();
  const cookie = headersList.get('Cookie');
  const res = await fetch('https://xxx.com', {headers: {
      cookie
    }});
  return res.json()
};
export default async function RootLayout(props: any) {
  const useInfo = await getData();
  return (
    <html lang="en">
      <body>
        <div>header</div>
        <Context useInfo={useInfo}>{props.children}</Context>
        <div>footer</div>
      </body>
    </html>
  );
}

使用/src/app/blog/page.tsx

'use client';
import { PropsContext } from '@/app/context';
import { useContext } from 'react';
export default function A2() {
  const { GlobalState, setGlobalState } = useContext<any>(PropsContext);
  return (
    <main>
      {JSON.stringify(GlobalState, null, 2)}
      <div
        onClick={() => {
          setGlobalState((s: any) => {
            s.useInfo.name = '修改之后的名称';
          });
        }}
      >
        修改名称
      </div>
    </main>
  );
}

跳转

如果没有用户信息需要跳转到登录页

import { redirect } from 'next/navigation'
async function fetchTeam(id) {
  const res = await fetch('https://...')
  // 具体逻辑根据实际的来
  if (!res.ok) return undefined
  return res.json()
}
export default async function Profile({ params }) {
  const team = await fetchTeam(params.id)
  if (!team) {
 redirect('/login')
  }
  // ...
}

部署

如果不在根域名下需要在 next.config.js添加

路由名称根据实际来

{
  basePath: '/router'
}

然后在流水线nginx配置路由 /router* 转发到这个应用

如果 basePath 配置的 /router/' 对应nginx配置 /router/*

编写 Dockerfile

由于 FROM nodejs@xx 过不了镜像扫描 镜像里面又没有Node.js >= 18.17的只能使用提供最基础的镜像了

Dockerfile

FROM hub.xxx.com/basics/alpine:3.18.2
RUN apk add nodejs=18.18.2-r0 npm=9.6.6-r0
WORKDIR /app
ADD . .
RUN npm i
RUN npm run build
EXPOSE 3000
CMD ["sh", "-c", "NODE_ENV=$NODE_ENV npm run start"]

参考文档

https://nextjs.org/docs

https://vercel.com/guides/react-context-state-management-nextjs

以上就是服务端渲染nextjs项目接入经验总结分析的详细内容,更多关于服务端渲染nextjs项目接入的资料请关注脚本之家其它相关文章!

相关文章

  • 一文带你掌握JavaScript异步编程的五种方式

    一文带你掌握JavaScript异步编程的五种方式

    异步可以理解为把一个任务分成了两段,先执行第一段,转而去执行其它任务,等准备完毕后,再回过头来执行第二段, 本文主要来和大家聊聊JavaScript异步编程的五种方式,感兴趣的可以了解下
    2025-07-07
  • es6中let和const的使用方法详解

    es6中let和const的使用方法详解

    这篇文章主要介绍了es6中let和const的使用方法,结合实例形式详细分析了es6中let和const的基本功能、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2020-02-02
  • Openlayers实现地图全屏显示

    Openlayers实现地图全屏显示

    这篇文章主要为大家详细介绍了Openlayers实现地图全屏显示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例

    JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例

    这篇文章主要介绍了JavaScript求一个数组中重复出现次数最多的元素及其下标位置,涉及javascript数组元素遍历、判断、正则过滤、追加等相关操作技巧,需要的朋友可以参考下
    2018-07-07
  • JavaScript判断数组是否存在key的简单实例

    JavaScript判断数组是否存在key的简单实例

    下面小编就为大家带来一篇JavaScript判断数组是否存在key的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • JavaScript 数组常见操作技巧

    JavaScript 数组常见操作技巧

    这篇文章主要给大家分享的是JavaScript 数组常见操作技巧,数组是 JavaScript 中常见数据类型之一,关于它的一些操作方法,我在这里做一下简单记录和总结,需要的小伙伴可以参考一下
    2022-02-02
  • JavaScript indexOf忽略大小写

    JavaScript indexOf忽略大小写

    javascript中indexOf函数是严格区分大小写的,也就是当我们使用javascript的indexOf函数的时候, 是无法进行大小写同时进行的。为我们的一些字符串操作造成了困难。
    2009-03-03
  • JavaScript中DOM核心操作的实战指南

    JavaScript中DOM核心操作的实战指南

    本文详细介绍了JavaScript中DOM元素操作的实战指南,从查找、创建、修改、插入、删除、属性操作、事件绑定及遍历等节点等常见操作入手,对比了各种方法的优缺点,希望对大家有所帮助
    2026-04-04
  • 跨浏览器开发经验总结(三)   警惕“IE依赖综合症”

    跨浏览器开发经验总结(三) 警惕“IE依赖综合症”

    跨浏览器开发经验总结(三) 警惕“IE依赖综合症”
    2010-05-05
  • JavaScript中工厂函数与构造函数示例详解

    JavaScript中工厂函数与构造函数示例详解

    这篇文章主要给大家介绍了关于JavaScript中工厂函数与构造函数的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用JavaScript具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05

最新评论