CarefreeCMS 文档CarefreeCMS 文档
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
  • 功能特性

    • 内容管理
    • 多站点管理
    • AI 文章生成
    • AI 内容生成
    • SEO 优化
    • 静态化生成
    • 评论系统
    • 用户系统

静态化生成

CarefreeCMS 的静态化功能可以将动态页面生成为纯静态 HTML 文件,大幅提升访问速度和 SEO 效果。

为什么要静态化?

优势

⚡ 极速访问

  • 无需 PHP 解析
  • 无需数据库查询
  • 直接读取 HTML 文件
  • 响应时间 < 10ms

📈 SEO 友好

  • 搜索引擎更容易抓取
  • 页面加载速度快
  • 降低跳出率
  • 提高排名

💰 降低成本

  • 减少服务器负载
  • 降低带宽消耗
  • 可使用廉价 CDN
  • 节省服务器资源

🔒 安全性高

  • 无 SQL 注入风险
  • 无 PHP 代码执行风险
  • 防止恶意攻击
  • 数据更安全

📱 易于分发

  • 可部署到任何 Web 服务器
  • 支持 CDN 加速
  • 方便备份和迁移
  • 离线也能访问

劣势

🔄 实时性差

  • 内容更新需要重新生成
  • 动态功能受限
  • 评论等交互功能需特殊处理

💾 存储空间

  • 需要额外存储空间
  • 大型网站文件数量多

⏰ 生成时间

  • 首次生成耗时较长
  • 批量更新需要时间

静态化流程

工作原理

1. 读取数据库数据
   ↓
2. 加载模板文件
   ↓
3. 渲染模板(填充数据)
   ↓
4. 生成 HTML 文件
   ↓
5. 保存到指定目录

目录结构

backend/html/              # 静态文件根目录
├── index.html            # 首页
├── article/              # 文章目录
│   ├── 1.html
│   ├── 2.html
│   └── ...
├── category/             # 分类目录
│   ├── tech.html
│   ├── tech_2.html      # 分页
│   └── ...
├── tag/                  # 标签目录
│   ├── 1.html
│   └── ...
├── page/                 # 单页目录
│   ├── about.html
│   └── ...
├── assets/               # 静态资源
│   ├── css/
│   ├── js/
│   └── images/
└── sitemap.xml          # 网站地图

模板系统

模板文件

模板位于 backend/templates/ 目录:

backend/templates/
└── default/              # 默认主题
    ├── index.html       # 首页模板
    ├── article.html     # 文章详情模板
    ├── category.html    # 分类列表模板
    ├── tag.html         # 标签列表模板
    ├── page.html        # 单页模板
    ├── search.html      # 搜索结果模板
    └── 404.html         # 404 页面模板

模板语法

CarefreeCMS 使用 Twig 模板引擎:

变量输出

{# 输出文章标题 #}
{{ article.title }}

{# 输出带默认值 #}
{{ article.author|default('匿名') }}

{# 转义 HTML #}
{{ article.content|raw }}

条件判断

{% if article.is_top %}
    <span class="badge">置顶</span>
{% endif %}

{% if article.view_count > 1000 %}
    <span class="hot">热门</span>
{% else %}
    <span class="normal">普通</span>
{% endif %}

循环遍历

{# 遍历文章列表 #}
{% for article in articles %}
    <div class="article-item">
        <h2>{{ article.title }}</h2>
        <p>{{ article.summary }}</p>
    </div>
{% endfor %}

{# 空列表处理 #}
{% for article in articles %}
    ...
{% else %}
    <p>暂无文章</p>
{% endfor %}

包含其他模板

{# 包含头部 #}
{% include 'header.html' %}

{# 包含侧边栏并传递参数 #}
{% include 'sidebar.html' with {'type': 'hot'} %}

模板继承

{# 基础模板 base.html #}
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

{# 子模板 article.html #}
{% extends 'base.html' %}

{% block title %}{{ article.title }}{% endblock %}

{% block content %}
    <article>
        <h1>{{ article.title }}</h1>
        <div>{{ article.content|raw }}</div>
    </article>
{% endblock %}

常用变量

全局变量

{{ site.name }}          # 网站名称
{{ site.url }}           # 网站URL
{{ site.keywords }}      # 网站关键词
{{ site.description }}   # 网站描述
{{ site.logo }}          # 网站Logo

文章变量

{{ article.id }}         # 文章ID
{{ article.title }}      # 标题
{{ article.content }}    # 内容
{{ article.summary }}    # 摘要
{{ article.cover }}      # 封面图
{{ article.author }}     # 作者
{{ article.create_time}} # 发布时间
{{ article.view_count }} # 浏览次数
{{ article.category }}   # 分类
{{ article.tags }}       # 标签数组

分类变量

{{ category.name }}      # 分类名称
{{ category.alias }}     # 分类别名
{{ category.description}}# 分类描述
{{ category.articles }}  # 文章列表

生成方式

单个生成

生成文章

  1. 在文章列表点击 生成静态页
  2. 或编辑文章后点击 发布并生成
  3. 生成完成显示文件路径

生成分类

  1. 在分类管理点击 生成静态页
  2. 生成该分类的列表页和分页

生成标签

  1. 在标签管理点击 生成静态页
  2. 生成该标签的文章列表页

批量生成

进入 系统管理 → 静态化管理

生成首页

操作: 生成首页
耗时: 约 1-2 秒
生成文件: html/index.html

生成所有文章

操作: 生成所有文章
数量: 显示文章总数
耗时: 约 N 秒(N = 文章数 / 10)
进度: 显示实时进度条

生成所有分类

操作: 生成所有分类
包含: 分类列表页 + 分页
生成文件: category/*.html

生成所有标签

操作: 生成所有标签
包含: 标签文章列表
生成文件: tag/*.html

生成全站

操作: 一键生成全站
包含:
- 首页
- 所有文章
- 所有分类
- 所有标签
- 所有单页
- Sitemap

定时生成

设置定时任务

进入 系统管理 → 定时任务

每日凌晨生成

任务名称: 每日静态化
Cron表达式: 0 2 * * *
执行方法: app\task\StaticTask@generateAll
状态: 启用

每小时生成新文章

任务名称: 增量静态化
Cron表达式: 0 * * * *
执行方法: app\task\StaticTask@generateNew
参数: {"hours": 1}
状态: 启用

自动生成

发布时自动生成

在文章发布时自动生成静态页:

编辑 backend/app/controller/api/Article.php:

public function save()
{
    // 保存文章
    $article = Article::create($data);

    // 自动生成静态页
    if ($article->status == 1) {
        $this->generateStatic($article->id);
    }

    return Response::success('发布成功');
}

更新时自动生成

文章更新时重新生成:

public function update($id)
{
    $article = Article::find($id);
    $article->save($data);

    // 重新生成静态页
    $this->generateStatic($id);

    return Response::success('更新成功');
}

访问配置

Nginx 配置

server {
    listen 80;
    server_name www.example.com;

    # 静态文件目录
    root /var/www/cms/backend/html;
    index index.html;

    # 优先访问静态文件
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
    gzip_min_length 1000;
}

Apache 配置

<VirtualHost *:80>
    ServerName www.example.com
    DocumentRoot /var/www/cms/backend/html

    <Directory /var/www/cms/backend/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

        # URL 重写
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)$ index.html [L]
    </Directory>

    # 开启压缩
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
        AddOutputFilterByType DEFLATE application/javascript application/json
    </IfModule>

    # 缓存设置
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresByType image/jpeg "access plus 1 month"
        ExpiresByType text/css "access plus 1 week"
        ExpiresByType application/javascript "access plus 1 week"
    </IfModule>
</VirtualHost>

高级功能

增量生成

只生成新增或修改的内容:

// 获取最近1小时更新的文章
$articles = Article::where('update_time', '>', date('Y-m-d H:i:s', time() - 3600))
    ->select();

// 逐个生成
foreach ($articles as $article) {
    $this->generateArticle($article);
}

多模板支持

为不同分类使用不同模板:

$category = Category::find($id);

// 根据分类选择模板
$template = $category->template ?: 'default/category.html';

// 生成静态页
$html = $this->render($template, $data);

URL 自定义

自定义静态文件的 URL 结构:

'url_rules' => [
    // 文章: /article/年/月/ID.html
    'article' => '/article/{year}/{month}/{id}.html',

    // 分类: /分类别名/页码.html
    'category' => '/{alias}/{page}.html',

    // 标签: /tag/标签ID.html
    'tag' => '/tag/{id}.html',
],

条件生成

根据条件决定是否生成:

// 只生成已发布且未过期的文章
if ($article->status == 1 && $article->expire_time > time()) {
    $this->generateArticle($article);
}

// 只生成浏览量超过100的文章
if ($article->view_count >= 100) {
    $this->generateArticle($article);
}

性能优化

生成优化

分批生成

// 每次生成100篇
$articles = Article::limit(100)->select();
foreach ($articles as $article) {
    $this->generateArticle($article);

    // 避免内存溢出
    unset($article);
}

异步生成

// 使用队列异步生成
Queue::push('StaticJob', [
    'type' => 'article',
    'id' => $articleId,
]);

缓存模板

// 缓存编译后的模板
$twig = new \Twig\Environment($loader, [
    'cache' => '/path/to/cache',
]);

访问优化

CDN 加速

# 使用 CDN 域名
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
    proxy_pass https://cdn.example.com;
}

浏览器缓存

# 设置缓存时间
location ~* \.(html)$ {
    expires 1h;
    add_header Cache-Control "public";
}

HTTP/2

listen 443 ssl http2;

常见问题

生成的页面没有样式?

原因:资源路径不对

解决:

  1. 检查模板中的资源路径是否正确
  2. 使用绝对路径或相对于根目录的路径
  3. 同步模板资源到静态目录

生成速度太慢?

优化方案:

  1. 使用分批生成
  2. 启用异步队列
  3. 优化数据库查询
  4. 增加服务器配置

如何实现动态功能?

方案一:Ajax 加载

<!-- 静态页面中加载评论 -->
<div id="comments"></div>
<script>
$.get('/api/comments?article_id=1', function(data) {
    $('#comments').html(renderComments(data));
});
</script>

方案二:使用 SSI

<!--#include virtual="/dynamic/comments.php?id=1" -->

方案三:使用 ESI

<esi:include src="/api/comments?id=1" />

如何更新已生成的页面?

方式一:重新生成 编辑内容后点击"生成静态页"

方式二:定时更新 设置定时任务定期重新生成

方式三:按需更新 内容修改时自动触发生成

最佳实践

  1. 合理规划

    • 确定哪些页面需要静态化
    • 动态内容用 Ajax 加载
    • 合理设置更新频率
  2. 优化模板

    • 简洁高效的模板代码
    • 减少不必要的查询
    • 使用模板缓存
  3. 定时任务

    • 设置在访问低峰期生成
    • 增量更新优于全量更新
    • 监控生成状态
  4. 混合部署

    • 静态页面 + 动态接口
    • 充分利用两者优势
    • 提供最佳用户体验

相关资源

  • 模板开发
  • 系统配置
  • SEO优化
  • 性能优化
在 GitHub 上编辑此页
Prev
SEO 优化
Next
评论系统