從零打造一款輕量且天然支持SSR的CMS系統-SimpleCMS
2年前筆者開發了一款基于 nodejs 的全棧開源 cms 系統 XPCMS, 主要是為了解決技術開發者搭建自身內容平臺的局限以及降低使用成本, 雖然1.0版本已經完成, 但是從整體部署和二次開發的便捷度上還是存在很多缺點, 更加適合有一定技術能力的開發者來使用.
為了解決 XPCMS 的不足, 去年筆者和朋友特地開發了一款輕量便捷的內容管理系統——simpleCMS, 目前已在 github 上開源, 且能同時適配PC端和移動端.
目前市面上已經有很多成熟的 cms 系統, 比如 worldPress, 博客系統 hexo, 對于技術開發者來說使用和部署很簡單, 但是定制和自定義擴展方面, 卻需要一定的技術門檻和開發成本.
基于以上一些痛點和局限, 我們開發了一款簡單易用, 且天然支持服務端渲染(SSR)的全棧 cms 系統, 方便大家輕松定制自己的博客網站. 筆者接下來就來帶大家一起分析 simpleCMS 的功能和技術實現.
技術架構和實現方案
為了降低大家的使用和部署成本, 我們采用了如下技術實現:
- 服務層: koa2 + nodejs + jsonSchema(當然其中還使用了很多nodejs中間件)
- 前臺頁面: pug(結合nodejs實現前后端同構, 且天然的SSR)
- 后臺管理: umi3.0 + react + antd + axios + typescript(當然還用了很多前端插件, 比如富文本, md編輯器)
- 系統/服務器相關: linux / pm2 / nginx
基本架構模式如下圖所示:

系統頁面架構圖:

功能分析
接下來筆者就來介紹 simpleCMS 的功能點. 我們先來分析一下后臺管理系統.
后臺管理系統功能分析
后臺管理系統是動態博客系統必備的模塊, 它能很方便的管理我們的網站數據. 這里筆者先來帶大家看一下后臺管理系統的基本模塊:
- 登錄頁面
- 數據大盤
- 內容管理
- 頁面配置
- 廣告配置
- 用戶信息管理
- 多語言支持
以上是 cms 管理系統必備的模塊, 這里我們基本上采用react hooks 來寫, 具體頁面如下:
1 登錄頁面

2 數據大盤

3 文章管理

4 內容編輯

5 多語言支持

其他頁面就不一一展示了, 感興趣的朋友可以體驗一下. 主要技術采用 umi + antd + react + typescript 實現, 感興趣可以在 github 上參考學習.
前臺基本功能分析
前臺主要是我們的博客網站, 這里采用 pug 這個模版引擎來實現, 交互功能使用大家最熟悉的jquery.前臺基本模塊有:
- 博客首頁
- 文章列表頁
- 文章詳情頁
對應的交互功能有點贊, 評論, 文章搜索功能等, 基本頁面如下:
1 首頁

2 列表頁

3 詳情頁
4 評論和點贊
由于pug模版引擎適合做一些展示型的網站, 所以非常適合用在cms系統中, 我們也可以使用ejs等模版引擎.
技術實現細節
由于整個cms 系統是一個完整的技術閉環, 數據流轉都是相關的, 這里筆者主要總結一下實現一個cms的技術細節.
- 數據統計功能實現 —— 采用nodejs定時任務(node-schedule)
- 富文本和md編輯器實現
- 后臺多語言實現方案
- 內容管理流程設計
- pug 模版和數據交互
- jsonSchema 數據結構設計
- 手寫簡單加密解密算法
- 跨域解決方案以及用戶權限設計
- pm2管理node進程以及做負載均衡
- 多進程場景下的并發鎖設計
數據統計功能實現
數據統計主要是統計網站的pv, 單篇文章閱讀量和點贊量, 為了更好的進行分析我們需要對單日的數據進行統計和存庫, 具體實現就是利用定時任務在一天結束前進行數據的統計, 這里我們用 node-schedule來實現, 具體使用方式筆者也在之前的文章中做了介紹, 感興趣可以參考一下.

基本使用如下:
- let schedule = require('node-schedule');
- let testJob = schedule.scheduleJob('42 * * * *', function(){
- console.log('將在未來的每個時刻的42分時執行此代碼, 比如22:42, 23:42');
- });
富文本和md編輯器方案實現
這里我們用的富文本組件是braft, 功能和可擴展性基本滿足業務需求, md編輯器是程序員寫博客的基本方式, 這里主要采用了for-editor, 其次就是對其進行了二次封裝來實現支持剪切板功能.
國際化方案
多語言主要使用的react-intl, 由于umi 對其有很好的集成, 所以說我們只需要搭建基本的多語言規則即可. 比如在項目目錄里建立locales文件夾, 然后存放zh(中文)/en(英文)文件即可, 基本的代碼如下:
- // locales/en/user
- export default {
- simpleCMS_DESC: 'Easy to use CMS system, help everyone to have their own website blog.',
- CopyrightText: 'SimpleCMS r&d team',
- }
- // locales/zh/user
- export default {
- simpleCMS_DESC: '簡單易用的cms系統, 助力每個人都能擁有自己的網站博客。',
- CopyrightText: 'SimpleCMS 研發團隊'
- }
如果對多語言實現方案感興趣的, 可以參考simpleCMS源碼.