首页
关于
Search
1
解决 Next.js 部署后 API 缓存不刷新的问题
68 阅读
2
测试
57 阅读
3
Next.js 渲染模式深度解析与SEO优化
50 阅读
4
从零开始搭建typecho
49 阅读
5
Next.js 应用性能优化实战:从 CSR 到 SSG 的演进过程
48 阅读
默认分类
登录
Search
Typecho
累计撰写
5
篇文章
累计收到
5
条评论
首页
栏目
默认分类
页面
关于
搜索到
5
篇与
的结果
2025-07-18
Next.js 应用性能优化实战:从 CSR 到 SSG 的演进过程
在最近的项目实践中,我遇到了一个首页性能优化的问题。首页包含一个较为复杂的 AnimatedBanner 组件,具有大量的图片和鼠标跟随动画。最初的实现方式为客户端渲染(CSR),带来了较大的首屏加载压力。本文将详细记录我如何逐步优化 AnimatedBanner,从客户端渲染 (CSR) 到静态站点生成 (SSG),并解决了在过程中遇到的各种问题。一、初始问题分析最开始,我的 AnimatedBanner 组件采用 use client,通过 useEffect 直接加载动画逻辑。虽然功能完整,但带来了几个问题:首屏加载 JS 量大,影响渲染速度。组件树使用 use client 后,无法利用 Next.js 的静态生成优势(SSG)。二、渐进式优化策略我采用了一步一步的优化策略:动态加载动画逻辑将组件拆分为 Server 和 Client Component使用 IntersectionObserver 懒加载动画引入 `` 组件懒加载使用 `` 提升图片加载体验三、优化实施过程1. 动态加载动画逻辑原本动画逻辑通过 useEffect 直接导入,我将其修改为动态导入方式,减小初始加载体积:useEffect(() => { import("@/utils/bannerMouseEffect").then(({ initBannerMouseEffect }) => { initBannerMouseEffect(); }); }, []);2. 拆分 Server 和 Client Component为了充分利用 Next.js 的静态生成,我将 AnimatedBanner 拆分为纯 Server Component 和 Client Component Wrapper。Server Component(AnimatedBanner):只负责静态 HTML 和图片渲染。Client Component(AnimatedBannerClient):负责加载和执行动画逻辑。Server Component示例:const AnimatedBanner = forwardRef(({ style }, ref) => ( <div ref={ref} className="animated-banner"> {/* 图片渲染 */} </div> )); AnimatedBanner.displayName = "AnimatedBanner";Client Component示例:"use client"; const AnimatedBannerClient = ({ style }) => { const bannerRef = useRef(null); useEffect(() => { if ("IntersectionObserver" in window) { const observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { import("@/utils/bannerMouseEffect").then(({ initBannerMouseEffect }) => { initBannerMouseEffect(); }); observer.disconnect(); } }); observer.observe(bannerRef.current); } }, []); return <AnimatedBanner ref={bannerRef} style={style} />; };3. 使用 IntersectionObserver 懒加载动画使用 IntersectionObserver 实现只有当用户滚动到组件时才加载动画逻辑,有效提升性能。4. 使用 next/dynamic 组件懒加载通过 Next.js 内置的动态导入进一步优化:const AnimatedBannerClient = dynamic(() => import("@/components/AnimatedBannerClient"), { ssr: false, loading: () => <div>加载中...</div>, });5. 提升图片加载体验:blurDataURL为图片添加低分辨率占位图,改善加载体验:<Image src={item.src} blurDataURL={item.blurDataURL} placeholder="blur" />四、遇到的问题与解决方案优化过程中,遇到以下问题:父组件使用 "use client" 后,子组件无法静态渲染问题:解决方案:拆分组件,确保 Banner 部分为纯 Server Component,通过 Client Wrapper 加载动画。forwardRef 组件 ESLint 警告问题:添加 displayName 解决警告:AnimatedBanner.displayName = "AnimatedBanner";图片未显示问题:确保 ref 正确透传,并去除不必要的 ssr: false 配置即可。五、最终效果及结论通过以上优化措施,首页性能大幅提升:首屏秒开:静态 HTML 直接加载,图片显示平滑。动态动画延迟加载:动画逻辑按需加载,减少用户初次访问的等待时间。维护性提升:组件结构清晰,后续维护更加方便。此次优化实践证明了 Next.js 应用合理使用 Server 和 Client Components 的重要性。通过精细化控制渲染模式,完全可以实现更好的用户体验和性能。希望本次实践能够为遇到类似问题的开发者提供一些参考和思路。
2025年07月18日
48 阅读
0 评论
0 点赞
2025-07-18
Next.js 渲染模式深度解析与SEO优化
Next.js 渲染模式深度解析与SEO优化Next.js 是一个强大的 React 框架,支持多种渲染方式:客户端渲染(CSR/BSR)、静态站点生成(SSG)、服务端渲染(SSR)、增量静态再生(ISR)。本文将通过示例、代码、Mermaid图表以及优化策略,帮助你深入理解这些渲染方式,并掌握如何针对 SEO 进行优化。一、渲染方式概述1. 客户端渲染 (CSR / BSR)定义: 在浏览器端通过 JavaScript 动态生成页面内容。React、Vue 的 SPA 项目默认采用 CSR。特点:优点:交互性强,用户体验流畅。缺点:初始 HTML 几乎为空,需等待 JS 执行完成,导致首屏白屏和 SEO 不佳。Next.js 示例:"use client"; import { useEffect, useState } from "react"; import axios from "axios"; export default function Posts() { const [posts, setPosts] = useState([]); useEffect(() => { axios.get('/api/posts').then(res => setPosts(res.data)); }, []); return posts.length ? posts.map(p => <div key={p.id}>{p.title}</div>) : <p>加载中...</p>; }Mermaid 图:flowchart LR A[请求页面] --> B[服务器返回空HTML + JS] B --> C[浏览器执行JS] C --> D[AJAX拉取数据] D --> E[填充DOM并渲染页面]2. 静态站点生成 (SSG)定义: 构建时将页面预先生成静态 HTML 文件,每个用户访问时直接返回该文件。特点:优点:首屏极快、SEO 优秀。缺点:需要重新构建才能更新数据。Next.js 示例:export async function getStaticProps() { const posts = await getAllPosts(); return { props: { posts } }; } export default function PostsPage({ posts }) { return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>; }Mermaid 图:flowchart TD A[构建阶段] -->|生成静态HTML| B[部署CDN/服务器] B -->|用户访问| C[直接返回HTML]3. 服务端渲染 (SSR)定义: 每次请求时由服务器动态生成 HTML,并返回给浏览器。特点:优点:动态数据实时更新,SEO 友好。缺点:每个请求都需要服务器计算,性能略逊于 SSG。Next.js 示例:export async function getServerSideProps() { const data = await fetchData(); return { props: { data } }; }Mermaid 图:flowchart TD A[用户请求] --> B[服务器获取数据并渲染HTML] B --> C[返回完整HTML给浏览器]4. 增量静态再生 (ISR)定义: 基于 SSG 的优化机制,可定期重新生成页面,无需每次重新构建整个站点。特点:优点:兼顾性能与内容实时性。缺点:内容更新存在短暂延迟。Next.js 示例:export async function getStaticProps() { const posts = await getAllPosts(); return { props: { posts }, revalidate: 60 }; }Mermaid 图:flowchart TD A[首次构建生成静态HTML] --> B[缓存到CDN] B --> C[用户访问] C -->|超过60秒触发再生| D[后台再生成HTML]二、“use client” 与渲染模式在 Next.js 13+ 的 App Router 中:未加 "use client" 的组件 → Server Components,可参与 SSG/SSR/ISR。页面级 "use client" → 整个页面以 CSR(BSR)模式运行。优化策略: 将 "use client" 仅应用于需要交互的子组件,让页面主体继续享受服务端预渲染的优势。示例结构:graph TD A[Server Component] --> B[SEO内容] A --> C[Client Component - WeatherBanner] A --> D[Client Component - Carousel]三、Next.js 框架渲染方式对比渲染方式首屏速度SEO动态性适用场景CSR/BSR中等差高富交互SPASSG极快优低文档/博客SSR快优高电商、动态数据ISR快优中新闻、电商四、如何提升 SEO核心内容服务端渲染:拆分组件,确保主要文本通过 SSG/SSR 输出。合理使用 `:添加 、` 和 Open Graph 标签。语义化 HTML:使用 <header>、<main>、<article>、<footer>。图片优化:使用 next/image 并加上 alt 描述。内容预取和缓存:使用 ISR 或服务端缓存策略提高内容更新与抓取效果。五、页面改造案例假设一个首页,当前使用:"use client"; import WeatherBanner from "@/components/WeatherBanner"; import Carousel from "@/components/Carousel";优化策略: 移除页面级 "use client",仅在交互组件中声明。并配合 getStaticProps 或 getServerSideProps 预渲染关键内容:// app/page.tsx import WeatherBanner from "@/components/WeatherBanner"; // 客户端组件 import Carousel from "@/components/Carousel"; import { fetchQuotes } from "@/lib/api"; export default async function HomePage() { const quotes = await fetchQuotes(); return ( <> <Head> <title>我的主页 - SEO优化</title> <meta name="description" content="这是一个SEO优化后的Next.js主页" /> </Head> <main> <h1>欢迎来到我的主页</h1> <article>{quotes.map(q => <p key={q.id}>{q.content}</p>)}</article> <WeatherBanner /> <Carousel /> </main> </> ); }六、总结正确理解 BSR/CSR 与 SSG/SSR/ISR 的差别,选择合适的渲染模式。合理使用 "use client",尽量保持核心内容在服务端渲染。SEO 优化要点:元数据、语义化结构、资源优化和性能提升。通过上述策略,你可以在 Next.js 中同时兼顾 SEO 效果 和 优秀的用户交互体验。
2025年07月18日
50 阅读
0 评论
0 点赞
2025-07-17
解决 Next.js 部署后 API 缓存不刷新的问题
解决Next.js部署后API缓存不刷新的问题
2025年07月17日
68 阅读
0 评论
0 点赞
2025-07-11
从零开始搭建typecho
系统:Rocky Linux 9.5 (Blue Onyx)在 Rocky Linux 上,安装 PHP‑FPM 与扩展,以及配置 Nginx 和 SELinux,大致步骤如下。1. 启用 EPEL 和 Remi 源默认 Rocky 源里的 PHP 版本可能偏旧,推荐使用 Remi 源来安装 PHP 7.4+。# 安装 EPEL sudo dnf install -y epel-release # 安装 Remi 源仓库 sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm # 启用 Remi PHP 8.3 槽(也可改成 remi-8.0、remi-8.1) sudo dnf module reset -y php sudo dnf module enable -y php:remi-7.32. 安装 PHP-FPM 及必要扩展sudo dnf install -y php-fpm php-mysqlnd php-gd php-mbstring php-xml php-curl # 启动并设为开机自启 sudo systemctl enable --now php-fpm检查服务状态:systemctl status php-fpm3. 下载并部署 Typechocd /var/www/html wget https://github.com/typecho/typecho/releases/latest/download/typecho.zip dnf install unzip -y unzip typecho.zip chown -R www-data:www-data /var/www/typecho/ chmod -R 755 /var/www/typecho/ chmod -R 777 /var/www/typecho/usr/uploads这里因为云服务网络问题,所以使用我的Windows电脑从typecho官网地址下载安装包上传到云服务器里。4. 设置 SELinux 上下文Rocky Linux 默认启用 SELinux,需要给 Typecho 的上传目录打标签,否则会被阻止写入。# 给 uploads 目录及其子目录设置可写权限类型 sudo semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/typecho/usr/uploads(/.*)?' sudo restorecon -Rv /var/www/typecho/usr/uploads如果你还未安装 policycoreutils-python-utils,请先:sudo dnf install -y policycoreutils-python-utils5. 创建数据库假设使用 MariaDB/MySQL:sudo dnf install -y mariadb-server sudo systemctl enable --now mariadb # 安全配置(可交互) sudo mysql_secure_installation # 登录并创建库 mysql -u root -p <<SQL CREATE DATABASE typecho_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'typecho_user'@'localhost' IDENTIFIED BY 'StrongPassword'; GRANT ALL ON typecho_db.* TO 'typecho_user'@'localhost'; FLUSH PRIVILEGES; SQL6. 修改 Nginx 配置因为我的域名已经使用,所以我采用新增一个local块,在原来 server 块里(处理 seekersferry.com 的部分),添加 /blog/ 段:# 处理 /blog/ 下的静态和 try_files location /blog/ { root /var/www/typecho; index index.php index.html; # 有文件就直接给文件,没文件才转给 index.php try_files $uri $uri/ /blog/index.php?$args; } # 专门处理 /blog/ 下的 PHP location ~ ^/blog/.*\.php$ { root /var/www/typecho; include fastcgi.conf; # 推荐比 fastcgi_params 完整 fastcgi_pass unix:/run/php-fpm/www.sock; fastcgi_index index.php; # 告诉 PHP-FPM 真正的脚本位置 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }注意root /var/www/typecho; 与 URL 前缀 /blog/ 一起,会把 /blog/index.php 映射到 /var/www/typecho/index.php。PHP-FPM 的 socket 在 Rocky Linux 通常是 /run/php-fpm/www.sock。测试并重载 Nginx:sudo nginx -t && sudo systemctl reload nginx7. 运行安装向导浏览器访问:https://www.seekersferry.com/blog/install.php按页面提示填写数据库信息、管理员账号等。完成后删除或重命名 install.php。8. 最后检查后台登录:https://www.seekersferry.com/blog/admin确保 usr/uploads 可写,上面 SELinux 标签正确。SSL、防火墙(firewalld)等根据需要打开/关闭端口。最后效果如下:补充: 安装插件官网上插件列表:http://docs.typecho.org/plugins/downloadgithub上的插件:https://github.com/typecho-fans/plugins
2025年07月11日
49 阅读
2 评论
2 点赞
2025-07-11
测试
1111
2025年07月11日
57 阅读
2 评论
2 点赞