渲染 = 把动态数据转换成静态HTML文件的过程
VanBlog使用Next.js的 ISR(Incremental Static Regeneration 增量静态再生成) 技术:
graph TB
    subgraph "数据层"
        DB[("MongoDB<br/>2k文章+4w标签")]
        Cache["内存缓存<br/>Tag Provider"]
    end
    
    subgraph "渲染层"
        ISR["ISR Provider<br/>增量静态再生成"]
        WEB["Next.js Website<br/>静态文件生成"]
    end
    
    subgraph "静态文件"
        HTML["HTML页面<br/>• 首页 /<br/>• 文章页 /post/[id]<br/>• 标签页 /tag/[name]<br/>• 分类页 /category/[name]<br/>• 列表页 /page/[p]"]
    end
    
    subgraph "用户访问"
        USER["用户浏览器"]
        CDN["CDN/Nginx<br/>静态文件服务"]
    end
    
    DB --> Cache
    Cache --> ISR
    ISR --> WEB
    WEB --> HTML
    HTML --> CDN
    CDN --> USER
    
    classDef database fill:#ff9999
    classDef render fill:#99ccff  
    classDef static fill:#99ff99
    classDef user fill:#ffcc99
    
    class DB,Cache database
    class ISR,WEB render
    class HTML static
    class USER,CDN user
graph TB
    subgraph "需要全量渲染的操作"
        CRON["定时任务每天2AM"]
        INIT["系统初始化"]
        SITE["站点配置变更"]
        MENU["导航菜单变更"]  
        MOMENT["动态管理"]
        CATEGORY["分类管理"]
        LAYOUT["布局设置"]
    end
    
    subgraph "使用增量渲染的操作"
        ARTICLE["文章CRUD-activeArticleById"]
        TAG["标签操作-精确渲染"]
        ABOUT["关于页面-activeAbout"]
        LINK["友链管理-activeLink"]
    end
    
    subgraph "渲染结果"
        FAST["快速更新10-60秒"]
        SLOW["全站重建原10-30分钟"]
    end
    
    CRON --> SLOW
    INIT --> SLOW  
    SITE --> SLOW
    MENU --> SLOW
    MOMENT --> SLOW
    CATEGORY --> SLOW
    LAYOUT --> SLOW
    
    ARTICLE --> FAST
    TAG --> FAST
    ABOUT --> FAST
    LINK --> FAST
typescript展开代码// packages/server/src/controller/admin/article/article.controller.ts
// ✅ 文章操作使用精确的增量渲染
this.isrProvider.activeArticleById(id, 'update', beforeObj);  // 更新
this.isrProvider.activeArticleById(data.id, 'create');       // 创建  
this.isrProvider.activeArticleById(id, 'delete', beforeObj); // 删除
activeArticleById方法会精确渲染:
/post/${id}/tag/${tagName}/category/${categoryName}/、/timeline、/tag、/category/page/[p]页面typescript展开代码// packages/server/src/controller/admin/tag/tag.controller.ts  
// ✅ 标签操作使用精确的增量渲染
this.isrProvider.activeUrl('/tag', false);                           // 标签列表页
this.isrProvider.activePath('tag');                                  // 所有标签页面  
this.isrProvider.activeUrl(`/tag/${encodeURIComponent(name)}`, false); // 特定标签页
activeArticleById 方法的完整覆盖当文章发生变化时,会精确渲染以下页面:
文章相关页面:
/post/${id}/post/${pre.id}/post/${next.id}标签相关页面:
/tag/${newTag}(更新后的标签)/tag/${oldTag}(更新前的标签)分类相关页面:
/category/${newCategory}/category/${oldCategory}聚合页面:
/(文章列表)/timeline(按时间排序)/tag(所有标签)/category(所有分类)分页页面:
/page/1, /page/2, ...(通过activePath('page'))标签同步、重命名、删除操作都只渲染必要的页面:
/tag/tag/${tagName}activePath('tag')渲染所有标签页优化前(全量渲染):
优化后(增量渲染):
增量渲染不仅性能好,还能保证数据一致性:
text展开代码📈 高频操作(已优化为增量渲染): ✅ 文章 CRUD → activeArticleById → 5-20页面 ✅ 标签操作 → 精确渲染 → 1-5页面 ✅ 关于页面 → activeAbout → 1页面 ✅ 友链管理 → activeLink → 1页面 ⚡ 低频操作(保持全量渲染): 📅 定时任务 → 每天1次 → 全站 🔧 站点配置 → 偶尔修改 → 全站 📝 布局设置 → 很少修改 → 全站


本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!