纯前端零框架实现 34 万首古诗词阅读器:诗海 The Poetry Ocean 开源项目分享

当代码遇见诗歌,当数据承载文明,那些被吟诵千年的文字依然可以在今天闪耀。

一、项目背景

在信息快速流动的今天,我们每天接触大量文字,却越来越少停下来读一读跨越千年的诗句。杜甫的沉吟、李白的豪情、苏轼的旷达——它们躺在数据库里,与现代读者之间隔着一层。

诗海(The Poetry Ocean) 是一个开源的古诗词数字化展示项目:

  • 收录 344,240 首 古诗词
  • 纯前端静态网站,无服务器、无后端、无框架、无构建
  • 单文件 index.html 包含全部 CSS/JS
  • 同步提供 微信小程序 版本,功能完全对等

🔗 在线体验:https://ethanthr-dotcom.github.io/poetry-site/
📦 源码仓库:https://github.com/ethanthr-dotcom/shihai-the_poetry_ocean
在这里插入图片描述

二、技术架构

整体设计

网页端 浏览器 ──► 单文件 index.html ──► data/*.json(jsDelivr CDN) 小程序端 页面 ──► wx.cloud.callFunction ──► poemData(gzip 打包)

核心思路:按需加载 + 两级索引。34 万首诗切分为 345 个分块(每块 1000 首,约 90MB),配合两级索引实现懒加载。

两级索引设计

文件 大小 内容
index.json 18KB file / count / dynasties
index-full.json 324KB + authors / types
001.json ~ 345.json ~260KB/块 1000 首/块

首次访问只加载 18KB,后续按需加载分块。这种设计的关键在于:

  • 精简索引首屏必需,包含朝代信息(朝代搜索可用)
  • 全索引懒加载,额外包含作者和体裁(作者/体裁筛选时才加载)
  • 字符摘要索引 search-index.json:每块标题的字符集,标题模糊检索先收窄数据块

网页端:单文件架构

整个网站就是一个 HTML 文件,所有 CSS、JS 全部内联:

  • 零框架:原生 HTML/CSS/JS
  • 零构建:无 Webpack / Vite / Babel
  • 零依赖:不引入任何 npm 包
  • 本地调试:python3 -m http.server 8080 即可

站点会自动识别本地环境(IS_LOCAL),从相对路径 data/ 加载;部署到 GitHub Pages 等静态托管时自动切换 jsDelivr CDN,无需改代码

小程序端:微信云开发

小程序与网页端功能完全对等,数据经微信云开发云函数分发:

// 数据云函数路由:分块号 > 140 走第二个函数 function fnForFile(file) { const m = /^(\d{3}).json$/.exec(file); return m && parseInt(m[1], 10) > 140 ? "poemData2" : "poemData"; }

先按诗词数量加权随机选一个数据块,再块内随机抽一首。带关键词/体裁约束时,先用全索引收窄候选块,再流式扫描。

2. 智能搜索

单一搜索框 + 方式切换(按作者 / 按朝代 / 按标题):

  • 作者 / 朝代:精确匹配,先用全索引 authors / dynasties 字段收窄数据块
  • 标题:模糊匹配(包含),先用 search-index.json 字符摘要收窄
  • 体裁:支持多选,1479 项体裁全量内嵌代码
  • 与体裁任意组合

搜索过程实时显示进度(已扫描数据块 / 命中数量),命中关键词加粗高亮,数据块并行加载提速。

3. 分页加载策略

首次加载 20 首,滚动触底自动续载 20 首:

// 单次严格上限 20 条,命中先进缓冲,再按剩余额度上屏 const TARGET = 20; while (added < TARGET && (pendingHits.length || cursor < chunks.length)) { // 先上屏缓冲 → 再并行拉取 6 块 → 溢出进缓冲 }

并行拉取 6 个数据块,命中先进 pendingHits 缓冲,按剩余额度上屏,避免单次超载。

4. Canvas 手绘分享卡片

纯 Canvas 2D 逐字手绘排版:

  • 支持 1:1 / 3:4 / 9:16 / 自动比例
  • 横排 / 竖排双布局
  • 高分辨率输出
  • 同一套绘制逻辑网页端和小程序端共用

5. 主题系统

CSS 自定义属性(变量)动态注入:

  • 16 种主题配色 × 3 种排版(居中 / 宽屏 / 紧凑)
  • 即时切换,无需刷新
  • 设置面板分组可折叠

6. 字体加载

思源宋体(Noto Serif SC) 双端生效:

  • 网页端:@fontsource/noto-serif-sc + SerifFallback 本地回退
  • 小程序端:wx.loadFontFace 全局加载,scopes: ["native", "webview"] 让页面和分享图都能用
  • jsDelivr → unpkg 双 CDN 降级

四、数据管线

诗词数据来源于开源项目 chinese-poetry/chinese-poetry (MIT License),涵盖全唐诗、全宋诗、宋词、元曲、五代诗词、楚辞、诗经等。

用 Python 重新整理:

pip3 install zhconv python3 tools/convert_chinese_poetry.py

处理步骤:

  1. 繁体统一转简体(zhconv)
  2. 清理 PUA 码位与乱码字符
  3. 切分为 345 个分块(每块 1000 首)
  4. 生成两级索引

每个分块的诗词对象使用短键名节省体积:

含义 含义
t 标题 d 朝代
a 作者 y 体裁
c 正文

五、项目数据

  • 344,240 首诗词
  • 345 个数据分块
  • 1,479 种体裁
  • 18KB 首次加载(网页端)
  • 16 主题 × 3 排版
  • 1 个 HTML 文件 = 整个网站

六、本地部署

网页版(30 秒)

git clone https://github.com/ethanthr-dotcom/shihai-the_poetry_ocean.git cd shihai-the_poetry_ocean python3 -m http.server 8080

浏览器打开 http://localhost:8080/ 即可。

微信小程序

  1. 微信开发者工具导入仓库根目录
  2. 填入自己的 AppID
  3. 开通云开发,记下环境 ID 填入 config.js
  4. 右键 poemData / poemData2 → 上传并部署
  5. 编译运行

七、技术栈总结

部分 技术
网页端 单文件 HTML(原生 HTML/CSS/JS)
主题系统 CSS 变量动态注入
分享图 Canvas 2D 手绘排版
字体 Noto Serif SC + 双 CDN 降级
数据分发 jsDelivr CDN / 微信云函数
小程序 原生小程序 + 云开发
数据管线 Python(zhconv + 切片 + 索引)

八、开源协议

  • 源代码:MIT License
  • 诗词数据:来自 chinese-poetry/chinese-poetry(MIT License)
  • 非营利项目,仅供阅读、学习与研究参考

掬古人之诗,养今时之心。

如果这个项目对你有帮助,欢迎 Star ⭐ 支持!
🔗 仓库:https://github.com/ethanthr-dotcom/shihai-the_poetry_ocean
🌐 在线:https://ethanthr-dotcom.github.io/poetry-site/

更多推荐