有些日子没写项目了,正好学了点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/