前端 SSG:别让你的网站加载速度慢得像蜗牛

前端 SSG:别让你的网站加载速度慢得像蜗牛

毒舌时刻

这网站加载速度慢得能让我泡杯咖啡回来还没好。

各位前端同行,咱们今天聊聊前端 SSG(静态站点生成)。别告诉我你还在使用纯客户端渲染,那感觉就像在没有预加载的情况下开车——能开,但起步慢得要命。

为什么你需要 SSG

最近看到一个项目,每次加载都要重新获取数据,用户体验差。我就想问:你是在做网站还是在做实时应用?

反面教材

// 反面教材:纯客户端渲染 // App.jsx import React, { useState, useEffect } from 'react'; function App() { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchPosts() { setLoading(true); try { const response = await fetch('https://api.example.com/posts'); const data = await response.json(); setPosts(data); } catch (error) { console.error('Error fetching posts:', error); } finally { setLoading(false); } } fetchPosts(); }, []); return ( <div> <h1>我的博客</h1> {loading ? <div>加载中...</div> : ( <div> {posts.map(post => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> </div> ))} </div> )} </div> ); } export default App; 

毒舌点评:这代码,就像在每次启动时都要重新启动发动机,慢得要命。

正确姿势

1. Next.js SSG

// 正确姿势:Next.js SSG // 1. 安装依赖 // npx create-next-app@latest // 2. 页面组件 // pages/index.js import React from 'react'; export async function getStaticProps() { // 构建时获取数据 const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); return { props: { posts }, revalidate: 60 // 每 60 秒重新生成 }; } export default function Home({ posts }) { return ( <div> <h1>我的博客</h1> <div> {posts.map(post => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> </div> ))} </div> </div> ); } // 3. 动态路由 // pages/posts/[id].js import React from 'react'; export async function getStaticPaths() { // 构建时生成所有可能的路径 const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); const paths = posts.map(post => ({ params: { id: post.id.toString() } })); return { paths, fallback: false }; } export async function getStaticProps({ params }) { // 构建时获取数据 const res = await fetch(`https://api.example.com/posts/${params.id}`); const post = await res.json(); return { props: { post } }; } export default function Post({ post }) { return ( <div> <h1>{post.title}</h1> <p>{post.content}</p> </div> ); } 

2. Astro SSG

// 正确姿势:Astro SSG // 1. 安装依赖 // npm create astro@latest // 2. 页面组件 // src/pages/index.astro --- // 构建时获取数据 const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); --- <html> <head> <title>我的博客</title> </head> <body> <h1>我的博客</h1> <div> {posts.map(post => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> </div> ))} </div> </body> </html> // 3. 动态路由 // src/pages/posts/[id].astro --- // 构建时获取数据 const { id } = Astro.params; const res = await fetch(`https://api.example.com/posts/${id}`); const post = await res.json(); --- <html> <head> <title>{post.title}</title> </head> <body> <h1>{post.title}</h1> <p>{post.content}</p> </body> </html> 

3. Gatsby SSG

// 正确姿势:Gatsby SSG // 1. 安装依赖 // npm install -g gatsby-cli // gatsby new my-site // 2. 配置数据源 // gatsby-config.js module.exports = { plugins: [ { resolve: 'gatsby-source-rest-api', options: { endpoints: ['https://api.example.com/posts'] } } ] }; // 3. 页面组件 // src/pages/index.js import React from 'react'; import { graphql } from 'gatsby'; export const query = graphql` query { allRestApiPosts { edges { node { id title content } } } } `; export default function Home({ data }) { const posts = data.allRestApiPosts.edges.map(edge => edge.node); return ( <div> <h1>我的博客</h1> <div> {posts.map(post => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> </div> ))} </div> </div> ); } // 4. 动态页面 // src/templates/post.js import React from 'react'; import { graphql } from 'gatsby'; export const query = graphql` query($id: String!) { restApiPosts(id: { eq: $id }) { title content } } `; export default function Post({ data }) { const post = data.restApiPosts; return ( <div> <h1>{post.title}</h1> <p>{post.content}</p> </div> ); } // 5. 创建动态页面 // gatsby-node.js exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; const result = await graphql(` query { allRestApiPosts { edges { node { id } } } } `); result.data.allRestApiPosts.edges.forEach(edge => { createPage({ path: `/posts/${edge.node.id}`, component: path.resolve('./src/templates/post.js'), context: { id: edge.node.id } }); }); }; 

毒舌点评:这才叫前端 SSG,构建时生成静态页面,加载速度快,用户体验好,再也不用担心页面加载慢的问题了。

Read more

Zotero 8.0.1 生产力全开:2026 英文文献批量下载、自动化脚本与 AI 深度分析全攻略

Zotero 8.0.1 生产力全开:2026 英文文献批量下载、自动化脚本与 AI 深度分析全攻略

注意:全平台付费的文献,需要你有下载权限,不能免费下载。 文章目录 * 一、Zotero简介 * 二、文献检索和导出 * 三、文献批量下载 * 3.1 理论:Zotero如何下载文献? * 3.2 操作 * 3.21 导入文献 * 3.22 获取全文 * 3.4 处理没有获取到的文献 * 3.5 附:整理zotero下载的文献 * 四、zotero 的AI 插件 一、Zotero简介 Zotero是一个免费的开源文献管理软件。 支持:win、mac、linux;包含桌面端软件和浏览器插件;开源:就有很多插件可供增强软件的功能;免费:但是别人开发的插件可能是付费的,以及云同步的空间扩展也是付费的。 🟢官网:https:

【源力觉醒 创作者计划】文心大模型 4.5 开源了,和你一起解锁 AI 从封闭到开放的澎湃势能

【源力觉醒 创作者计划】文心大模型 4.5 开源了,和你一起解锁 AI 从封闭到开放的澎湃势能

「源力觉醒 创作者计划」文心大模型 4.5 开源了,和你一起解锁 AI 从封闭到开放的澎湃势能 文章目录 * 「源力觉醒 创作者计划」文心大模型 4.5 开源了,和你一起解锁 AI 从封闭到开放的澎湃势能 * 一、开篇引入 * 二、文心大模型 4.5 系列开源情况介绍 * 1. 开源的来龙去脉:从博弈到共建 * 2. 开源模型亮点:技术突破与场景适配 * 三、文心大模型 4.5 系列开源给开发者带来的改变 * 1. 降低开发的门槛和花费 * 2. 带来更多创新的机会 * 四、文心大模型 4.5 系列开源对行业生态的作用 * 1. 推动技术交流和进步 * 2. 促进产业协同发展

告别截图!Antigravity 集成 Figma MCP 打造像素级还原的 AI 编程体验

告别截图!Antigravity 集成 Figma MCP 打造像素级还原的 AI 编程体验

🚀 告别截图!Antigravity 集成 Figma MCP 打造像素级还原的 AI 编程体验 作为开发者,你是不是经常截图发给 AI 让它写 CSS,结果写出来的效果总是“差强人意”?👀 间距不对、颜色有色差、字体搞错…… 今天我们要玩点高端的!利用 MCP (Model Context Protocol) 协议,将 Figma 的底层设计数据直接“喂”给 Antigravity。让 AI 不再是“看图说话”,而是直接读取设计原稿!🎨➡️💻 🌟 什么是 Figma Context MCP? 这是一个由 Framelink 开发的 MCP 服务。它能让你的 AI 编辑器(如 Antigravity,

基于LangGraph实现模块化Skills型AI Agent

基于LangGraph+DeepSeek+Serper 实现模块化Skills型AI Agent 在AI Agent的落地实践中,模块化Skills设计是提升Agent可扩展性、可维护性的核心方案——将搜索、计算、文件处理等能力封装为独立Skills,Agent可根据需求自主调用,无需修改核心流程。本文将基于LangGraph、DeepSeek大模型和Serper搜索工具,手把手带你实现一个具备工具调用能力的Skills型AI Agent,同时解决开发中常见的MRO冲突、Pydantic验证等问题,代码可直接复制运行。 一、前言:为什么选择Skills型Agent? 传统AI Agent多采用「硬编码工具调用」的方式,新增能力需修改核心逻辑,耦合度高且难以维护。而Skills型Agent将能力拆分为独立的Skill模块,每个Skill遵循统一接口,具备以下优势: 1. 模块化解耦:新增/修改Skill无需改动Agent核心流程,即插即用; 2. 智能决策:大模型自主判断是否调用Skill、调用哪个Skill,无需人工干预; 3. 可扩展性强:支持搜索、计算、代码解释、数