📢 系统公告

apistatic V1.0 正式发布,静筑 Apistatic 开源 CLI 工具,对接 api工厂开放 API,一键生成整套纯静态 HTML 站点

静筑 Apistatic

开源 CLI 工具,对接 api工厂开放 API,一键生成整套纯静态 HTML 站点。

产物可直接部署至 GitHub Pages、OSS、CDN 等任意静态空间,天然 SEO 友好,支持全量 / 增量构建、自定义 Nunjucks 主题模板、文章图片自动本地化。


目录

  • 特性
  • 快速开始
  • 配置项详解
  • CLI 命令
  • 自定义模板教程
  • 二次开发指南
  • 常见问题 FAQ
  • 开源协议

特性

  • 零服务器:产物全部为纯 HTML,可部署至任意静态空间
  • 增量构建:只重新渲染有变化的文章,海量内容场景高效构建
  • 自动 SEO:生成 sitemap.xmlrobots.txt、RSS 订阅文件
  • 图片本地化:文章内远程图片自动下载到本地,告别图片失效
  • 响应式主题:内置大气博客主题,PC / Pad / 手机完美自适应
  • 多主题支持:基于 Nunjucks 模板引擎,可自由替换主题
  • Markdown / HTML 双格式:自动识别文章内容格式,无需额外配置
  • 富内容支持:Banner 轮播、文章分类、标签云、评论、友情链接、公告栏

快速开始

1. 安装

npm install -g apistatic

或在项目内本地使用:

git clone https://github.com/apistatic/apistatic.git
cd apistatic
npm install

2. 初始化配置

apistatic init

在当前目录生成 config.yaml,按注释填写参数即可。

3. 填写商户信息

打开 config.yaml,找到 api 配置块,分别填写 subDomain(专属域名)和 merchantId(商户ID):

api:
  subDomain: "你的专属域名"   # 在后台「工厂设置 → 专属域名」查看
  merchantId: "你的商户ID"    # 在后台「工厂设置 → 商户ID」查看(通常为纯数字)

注意subDomain 和 merchantId 是两个不同的值,请分别查看后台对应配置项填写,不一定相同。

快速测试:两个字段均可填写 180,再在「api工厂」后台 → 工厂设置 → 数据克隆 → 将别人的数据克隆给我 → 对方商户ID 填写 180,将测试数据导入自己账号。

4. 构建站点

# 增量构建(默认,只更新变化页面)
apistatic build

# 全量重建
apistatic build --full

# 指定配置文件
apistatic build -c ./my-config.yaml

构建完成后,dist/ 目录即为完整的静态站点,直接上传部署即可。


配置项详解

config.yaml 完整说明:

# 站点基本信息
site:
  title: "我的博客"            # 站点标题
  description: "站点简介"      # 用于 meta description
  url: "https://your-domain.com"   # 站点根域名(不含末尾斜杠)
  author: "作者昵称"
  keywords: "博客,技术"        # 全局关键词
  footer: "© 2024 我的博客"   # 页脚版权文字
  language: "zh-CN"
  postsPerPage: 10             # 每页文章数
  logo: ""                     # 站点 logo 图片 URL(留空则只显示文字)
  icp: ""                      # ICP 备案号
  customPages:                 # 导航栏显示的单页面 key(在后台「单页面」中配置)
    - "about"

# api工厂接口配置
api:
  subDomain: "myblog"          # 【必填】专属域名(用于 common.apifm.com 接口)
  merchantId: "180"            # 【必填】商户ID(用于 cms.apifm.com 接口,与 subDomain 不一定相同)
  baseUrl: "https://api.it120.cc"  # 一般无需修改
  token: ""                    # 用户 token(公开内容无需填写)
  timeout: 15000               # 请求超时(毫秒)
  retries: 3                   # 失败自动重试次数
  retryDelay: 1000             # 重试间隔(毫秒)

# 构建配置
build:
  outputDir: "./dist"          # 静态网站输出目录
  cacheDir: "./cache"          # 构建缓存目录
  template: "default"          # 主题模板(对应 templates/ 下的文件夹名)
  incremental: true            # 默认使用增量构建
  cleanOutput: true            # 全量构建时先清空输出目录
  articlesPageSize: 50         # 每次拉取文章数(最大 50)

# 资源处理
assets:
  downloadImages: true         # 是否下载远程图片到本地
  imageDir: "images"           # 本地图片存储目录名(在 dist/ 下)
  compressImages: false        # 图片压缩(需额外安装 sharp)

# SEO 配置
seo:
  generateSitemap: true        # 生成 sitemap.xml
  generateRobots: true         # 生成 robots.txt
  generateRss: true            # 生成 rss.xml

CLI 命令

# 查看版本
apistatic -v
apistatic --version

# 查看帮助
apistatic -h
apistatic --help

# 初始化配置文件
apistatic init

# 增量构建(默认)
apistatic build

# 全量重建,忽略缓存
apistatic build --full

# 指定配置文件路径
apistatic build -c ./custom-config.yaml

# 清空构建缓存与 dist 目录
apistatic clean

自定义模板教程

目录结构

每套主题放在 templates/<主题名>/ 目录下:

templates/
└── default/          # 默认主题
    ├── base.html     # 公共布局(header / footer)
    ├── index.html    # 首页
    ├── article.html  # 文章详情页
    ├── list.html     # 文章列表页(分类 / 标签)
    ├── archive.html  # 归档页
    ├── page.html     # 单页面
    ├── 404.html      # 404 页面
    └── sidebar.html  # 侧边栏(被其他模板 include)

切换主题

  1. 复制 templates/default/ 为 templates/my-theme/
  2. 修改 config.yaml 中 build.template: "my-theme"
  3. 编辑模板文件,重新构建

模板变量

所有页面均可访问的全局变量:

变量 说明
site 站点配置(title / description / url / logo 等)
categories 所有文章分类(含 articleCount
tags 标签云数据(含 name / number
banners Banner 轮播图列表
links 友情链接列表
recentArticles 最新 5 篇文章(侧边栏用)
notices 系统公告列表
pages 自定义单页面列表(导航栏)
year 当前年份(页脚版权年份)

文章详情页额外变量:

变量 说明
article 文章对象(id / title / content / pic / dateAdd / tags 等)
comments 评论列表
prevNext { pre, next } 上一篇 / 下一篇

内置过滤器

{# 日期格式化 yyyy-MM-dd #}
{{ article.dateAdd | date }}

{# 中文日期 yyyy年M月d日 #}
{{ article.dateAdd | dateCn }}

{# 截取摘要(默认 150 字符) #}
{{ article.content | excerpt(120) }}

{# 自动渲染 Markdown 或 HTML #}
{{ article.content | renderContent | safe }}

二次开发指南

项目结构

apistatic/
├── bin/apistatic.js      # CLI 入口(commander)
├── src/
│   ├── cli/              # init / build / clean 命令实现
│   ├── config/           # 配置加载与校验
│   ├── api-fetcher/      # api工厂接口封装(分页拉取、重试)
│   ├── data-cache/       # 增量构建缓存(JSON 快照 + hash 对比)
│   ├── renderer/         # Nunjucks 渲染引擎封装
│   ├── site-generator/   # 全流程构建调度器
│   ├── seo/              # sitemap / robots / RSS 生成
│   ├── asset-handler/    # 图片下载与路径替换
│   └── utils/            # logger / file / date / content 工具
├── templates/default/    # 默认博客主题(Nunjucks)
├── public/               # 全局静态资源(css / js)
├── dist/                 # 构建产物(部署此目录)
└── cache/                # 增量构建缓存(JSON)

接口说明

ApiFetcher 封装了 api工厂三个服务域的接口:

服务 基础域名 用途
API api.it120.cc/{subDomain} Banner、公告、友链等
Common common.apifm.com/{subDomain} 分类、配置、评论、标签等
CMS cms.apifm.com/{merchantId} 文章列表、文章详情

扩展新接口只需在 src/api-fetcher/index.js 中添加方法:

// 示例:拉取广告位数据
async fetchAdPositions(keys) {
  const res = await this.commonGet('/site/adPosition/batch', { keys });
  if (!res || res.code !== 0) return [];
  return res.data || [];
}

构建流程扩展点

src/site-generator/index.js 的 build() 方法即为完整流程,每个步骤均为独立方法,可按需重写:

build()
  ├── _fetchAllData()       // 数据拉取
  ├── _buildGlobalContext() // 全局上下文组装
  ├── _renderHome()         // 首页 + 列表分页
  ├── _renderCategoryPages() // 分类页
  ├── _renderTagPages()     // 标签页
  ├── _renderArchive()      // 归档页
  ├── _renderArticle()      // 文章详情(含图片本地化)
  └── seoGen.generate*()    // SEO 文件

常见问题 FAQ

Q: 执行 apistatic build 提示"配置文件不存在"?

先执行 apistatic init 生成 config.yaml,编辑后再执行构建。

Q: 接口返回 code: 700 暂无数据,没有内容?

检查 api.subDomain 是否填写正确。可先在「api工厂」后台发布一篇测试文章,或使用数据克隆功能导入商户 180 的测试数据。

Q: 图片没有下载到本地?

确认 assets.downloadImages: true,且网络可以访问远程图片地址。构建日志中若有 ⚠ 图片下载失败 提示,说明该图片地址不可访问,会保留原始远程 URL。

Q: 如何部署到 GitHub Pages?

  1. 将 dist/ 目录内容推送到 GitHub 仓库的 gh-pages 分支
  2. 或配置 GitHub Actions,在每次 push 时自动执行 apistatic build 并部署 dist/
# .github/workflows/deploy.yml 示例
name: Build & Deploy
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm install
      - run: node bin/apistatic.js build --full
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

Q: 如何部署到阿里云 / 腾讯云 OSS?

构建完成后,将 dist/ 目录整体同步到对应 OSS Bucket,配置静态网站托管即可。推荐使用 ossutil 或对应云厂商 CLI 工具。

Q: 增量构建没有生效,每次都是全量?

查看 cache/snapshot.json 是否存在。首次构建或执行 apistatic clean 后,缓存会被清空,下次构建自动变为全量构建。后续构建才会走增量逻辑。

Q: 文章内容乱码或格式异常?

api工厂文章内容支持 Markdown 和 HTML 两种格式,Apistatic 会自动识别。如仍有异常,可检查后台文章内容是否包含特殊字符,或在模板中使用 | safe 过滤器输出原始 HTML。

Q: 自定义主题模板找不到变量?

在开发主题时,可临时在模板中加入 {{ dump() }} 查看所有可用变量(Nunjucks 调试用)。详细变量列表参见模板变量章节。


开源协议

本项目使用 木兰宽松许可证 MulanPSL-2.0 开源。

Copyright (c) 2024 Apistatic Contributors

依据木兰宽松许可证,第2版("本许可证")获得许可;
除非符合本许可证,否则您不得使用本文件。
您可以在以下网址获取本许可证的副本:
http://license.coscl.org.cn/MulanPSL2