有些日子沒寫項目了,正好學了點Nodejs,就說拿koa2+react搭一個博客練練手。javascript
在找博文存儲方案的時候瞭解到目前大多數博文都已markdown或相似的標記化語言文檔存儲,因此就找了較爲新穎的hexo博客框架試用一下,順帶研究下源碼。html
起初以爲挺舒服,由於配置和主題切換起來足夠簡單,官網的文檔也是但願用戶不須要了解太多,只有最簡單的教程,因此沒幾個小時就以爲不夠用了。java
個人需求是經過Node實現博文的數據維護和接口,因此接下來我經過 hexo-admin 和 hexo-generator-restful 兩個hexo插件來實驗,前者構建了一個管理界面,有帳號管理、博文編寫和管理等功能,後者提供了hexo中全部內容的輸出接口,巧的是經過查看源碼發現hexo-admin還提供了不少可用來維護博文的輸入接口。node
後來我把hexo項目部署到了服務器上,前臺後臺預期功能也實現了,卻索然無味了……react
hexo博客在本地搭建起來很簡單,全命令行操做便可,官網也有不怎麼清楚的教程->點此進入。nginx
node環境搭建git
npm install -g hexo-cli
hexo init <blog-site-name>
命令行進入項目目錄,輸入命令運行。hexo server
或者 hexo s
github
INFO Start processing INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.
這裏沒什麼說的,以後便可經過訪問 http://localhost:4000 進入博客。npm
npm install --save hexo-admin hexo-generator-restful
json
若是你願意的話能夠看它們的文檔查看詳細使用方法:
https://github.com/jaredly/he...
https://github.com/yscoder/he...
入口文件index.js片斷
這裏經過hexo的api方法在服務請求中間件中加入了登錄模塊和路由模塊。
其中路由模塊分後臺管理頁面 admin/
和 後臺管理接口 admin/api/
hexo.extend.filter.register('server_middleware', function(app) { // 若是配置文件中要求用密碼登錄 if (passwordProtected) { require('./auth')(app, hexo); // setup authentication, login page, etc. } // Main routes app.use(hexo.config.root + 'admin/', serveStatic(path.join(__dirname, 'www'))); app.use(hexo.config.root + 'admin/api/', bodyParser.json({limit: '50mb'})); // setup the json api endpoints api(app, hexo); });
剖析api.jsapi.js
中就是全部接口代碼。
這是接口封裝函數:
var use = function (path, fn) { app.use(hexo.config.root + 'admin/api/' + path, function (req, res) { var done = function (val) { if (!val) { res.statusCode = 204 return res.end(''); } res.setHeader('Content-type', 'application/json') res.end(JSON.stringify(val, function(k, v) { // tags and cats have posts reference resulting in circular json.. if ( k == 'tags' || k == 'categories' ) { // convert object to simple array return v.toArray ? v.toArray().map(function(obj) { return obj.name }) : v } return v; })) } res.done = done res.send = function (num, data) { res.statusCode = num res.end(data) } fn(req, res) }) }
類型太多,這裏以博文接口爲例,能夠看到經過下級路由publish
、unpublish
、remove
、rename
實現了對博文的發佈,撤回草稿,移除,更名操做,而且根據GET
、POST
請求類型對/post
功能進行了區分。
use('posts/', function (req, res, next) { var url = req.url if (url[url.length - 1] === '/') { url = url.slice(0, -1) } var parts = url.split('/') var last = parts[parts.length-1] if (last === 'publish') { return publish(parts[parts.length-2], req.body, res) } if (last === 'unpublish') { return unpublish(parts[parts.length-2], req.body, res) } if (last === 'remove') { return remove(parts[parts.length-2], req.body, res) } if (last === 'rename') { return rename(parts[parts.length-2], req.body, res) } var id = last if (id === 'posts' || !id) return next() if (req.method === 'GET') { var post = hexo.model('Post').get(id) if (!post) return next() return res.done(addIsDraft(post)) } if (!req.body) { return res.send(400, 'No post body given'); } update(id, req.body, function (err, post) { if (err) { return res.send(400, err); } res.done({ post: addIsDraft(post), tagsCategoriesAndMetadata: tagsCategoriesAndMetadata() }) }, hexo); });
其餘細節就不贅述,能夠直接看其源碼,但有一點要說明一下,就是hexo建立博文的方式:經過/new
咱們可見一斑。hexo經過new建立實體markdown文件,再經過update方法更新其內容。
use('pages/new', function (req, res, next) { if (req.method !== 'POST') return next() if (!req.body) { return res.send(400, 'No page body given'); } if (!req.body.title) { return res.send(400, 'No title given'); } hexo.post.create({title: req.body.title, layout: 'page', date: new Date()}) .error(function(err) { console.error(err, err.stack) return res.send(500, 'Failed to create page') }) .then(function (file) { var source = file.path.slice(hexo.source_dir.length) hexo.source.process([source]).then(function () { var page = hexo.model('Page').findOne({source: source}) res.done(addIsDraft(page)); }); }); });
hexo官方推薦使用 hexo-deployer-git
作靜態部署,也就是說,經過下面的配置,hexo會將工程文件轉譯成一個.deploy文件夾,並將該文件夾force push到所配置的git目錄中,你能夠經過github將該目錄下文件進行渲染,也能夠將該靜態目錄clone到本身服務器上進行渲染。
deploy: type: git repo: <repository url> #https://bitbucket.org/JohnSmith/johnsmith.bitbucket.io branch: [branch] #published message: [message]
這意味着每次同步服務器上的博客都須要先將博文push到gihub上,再從服務器端手動pull相應的更新,是否是很麻煩,雖然靜態部署不管是從安全性仍是穩定性上都比較可靠,並且也有了hexo插件可以自動實現這些操做,可是這不是我想要的。
靜態資源文件目錄:
我心中最理想的架構是將博文、圖片等靜態資源存放在github中,服務端經過定時更新或監聽更新的方式同步github上的資源文件,而後在github上編寫markdown文件便可自動同步博客網站的內容。這樣作內容管理優點有幾點:
服務端也能夠選擇使用 hexo theme 模板 或先後端分離的方式進行開發,我這裏選擇只提供接口作數據服務。固然hexo theme模板來的簡單,也好看。
以centos7爲例,下面是部署方式:
npm install -g forever
建立一個index.js文件,內容以下:
const Hexo = require('hexo'); const hexo = new Hexo(process.cwd(),{ debug: true }); hexo.init().then(function(){ hexo.call('server', {}).then(function(){ console.log('server started'); }) })
forever start index.js
netstat -ntpl
查看4000端口是否是被啓用了。到這裏咱們就完成了博客的內容管理,實現了IO接口,但這時候我放棄了。
我開始思考我爲何要作用這麼一個須要長期維護的東西來練手,要寫東西的話有簡書、segementfault等網站支持,爲何不從那邊寫完再爬數據。並且接下來要作服務器與github同步的工做還挺複雜,功能簡單,但很消耗個人服務器性能,實在是得不償失……
這裏分享一個我很喜歡的風格:
https://clovertuan.github.io/