1. 使用RSC

RSC 减少了客户端处理的需求,使站点响应速度更快。发送到浏览器的 JavaScript 减少,从而加快了页面交互和查看的速度。例如,React 树是有选择性的,不会为所有 DOM 元素创建 React Client 组件。

2. SVG、Image优化

使用内置 next/images 组件,用于加载和渲染各种图像格式(包括 SVG),并进行效率和性能优化。它扩展了 HTML 图像元素,提供无缝集成和自动优化等优势。

3. 通过包装组件为RSC添加交互

image.png

如果一个组件需要有交互,又不想让组件改为客户端组件时,可以使用包装组件,在服务端组件之外包装一层客户端组件,通过 chidren 将服务端组件嵌入到客户端组件内。交互逻辑放在客户端组件中处理。例如

"use client";
 
import { usePathname } from "@/navigation";
import { useEffect, useState } from "react";
 
const ToggleHover = ({ children }: { children: React.ReactNode }) => {
  const pathname = usePathname();
  const [key, setKey] = useState(0);
 
  useEffect(() => {
    setKey((prevKey) => prevKey + 1);
  }, [pathname]);
  useEffect(() => {
    const element = document.getElementById("headerMenu") as HTMLElement | null;
    const handleScroll = () => {
      if (element && window?.scrollY > 870) {
        // Change to the desired scroll height
        element.style.display = "block";
      } else {
        if (element) element.style.display = "none";
      }
    };
    if (pathname === "/") {
      if (element && window?.scrollY < 870) element.style.display = "none";
 
      const addScrollListener = () => {
        window.addEventListener("scroll", handleScroll);
      };
      addScrollListener();
    } else {
      if (element) {
        element.style.display = "block";
      }
    }
    return () => {
      if (pathname === "/") {
        const removeScrollListener = () => {
          window.removeEventListener("scroll", handleScroll);
        };
        removeScrollListener();
      }
    };
  }, [key, pathname]);
 
  return <div key={key}>{children}</div>;
};
 
export default ToggleHover;

使用

import DeskTopMenu from "@/components/common/Header/DesktopMenu"
import ToggleHover from "./ToggleHover"
 
const Header = () => {
  return (
    <>
      <ToggleHover>
        <DeskTopMenu />
      </ToggleHover>
    </>
  )
}
export default Header

4. 不同的设备不同输出

服务器组件针对不同的设备做判断,客户端、Web、移动端等,例如移动端和Web端的布局不同,存在两套菜单栏布局代码,我们希望移动端访问时,服务器只会返回移动端使用的菜单栏布局代码,反之 Web端亦然。

使用 middleware 来获取用户访问设备,并设置到 header 中,在 Layout 中判断用户设备

import createMiddleware from 'next-intl/middleware';
import { NextRequest, userAgent } from 'next/server';
 
 
export default async function middleware(request: NextRequest) {
  const { device } = userAgent(request);
  const viewport = device.type === 'mobile' ? 'mobile' : 'desktop';
  request.headers.set('viewport', viewport);
}
import Footer from "../[locale]/sections/Footer";
import Header from "../[locale]/sections/Header";
import { headers } from "next/headers";
 
export default async function RootLayout({
  children,
  params: { locale }
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
 
  const headersList = headers();
  const viewport = headersList.get("viewport") || "";
 
  return (
    <html >
 
      <body>
        <Header viewport={viewport} />
        {children}
        <Footer/>
      </body>
    </html>
  );
}

5. 动态导入组件

对于比较大、或者使用频次不高的的组件,可以使用NextJS 提供的动态导入特性来加载组件:NextJs dynamic 动态加载,它可以将代码分割成小块并按需加载,这可以带来性能上的巨大提升。尤其在移动设备上,同时也将减少应用程序的初始加载时间和整体的抱大小

import dynamic from "next/dynamic"
 
const Component = dynamic(() => import("./Component.tsx"))