hexo博客框架从入门到弃坑

引言

有些日子没写项目了,正好学了点Nodejs,就说拿koa2+react搭一个博客练练手。

在找博文存储方案的时候了解到目前大多数博文都已markdown或类似的标记化语言文档存储,所以就找了较为新颖的hexo博客框架试用一下,顺带研究下源码。

起初觉得挺舒服,因为配置和主题切换起来足够简单,官网的文档也是希望用户不需要了解太多,只有最简单的教程,所以没几个小时就觉得不够用了。

我的需求是通过Node实现博文的数据维护和接口,所以接下来我通过 hexo-adminhexo-generator-restful 两个hexo插件来实验,前者构建了一个管理界面,有账号管理、博文编写和管理等功能,后者提供了hexo中所有内容的输出接口,巧的是通过查看源码发现hexo-admin还提供了很多可用来维护博文的输入接口。

后来我把hexo项目部署到了服务器上,前台后台预期功能也实现了,却索然无味了……

hexo博客搭建

hexo博客在本地搭建起来很简单,全命令行操作即可,官网也有不怎么清楚的教程->点此进入

  1. node环境搭建

  2. 安装hexo-cli
    npm install -g hexo-cli
  3. 通过hexo-cli初始化博客项目,将blog-site-name替换成你的项目名
    hexo init <blog-site-name>
  4. 搭建结束,开箱即用,目录结构如图
    hexo博客框架从入门到弃坑
  5. 命令行进入项目目录,输入命令运行。
    hexo server 或者 hexo s

    INFO  Start processing
    INFO  Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

这里没什么说的,之后即可通过访问 http://localhost:4000 进入博客。

构建接口服务

  1. 首先安装 hexo-adminhexo-generator-restful 两个插件

    npm install --save hexo-admin hexo-generator-restful

  2. 如果你愿意的话可以看它们的文档查看详细使用方法:

    https://github.com/jaredly/he...
    https://github.com/yscoder/he...
  3. 我们来看hexo-admin插件的源码,目录结构如下:

    hexo博客框架从入门到弃坑

  4. 入口文件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);
    });
  5. 剖析api.js
    api.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)
    })
     }

    类型太多,这里以博文接口为例,可以看到通过下级路由publishunpublishremoverename实现了对博文的发布,撤回草稿,移除,改名操作,并且根据GETPOST请求类型对/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));
          });
        });
      });
  6. hexo-generator-restful
    官方文档已经介绍的很详细了,他能提供站点配置site.json,博文post.json等等等等。

目前为止,接口搭建工作就基本完成了

hexo部署

静态部署

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插件能够自动实现这些操作,但是这不是我想要的。

静态资源文件目录:
hexo博客框架从入门到弃坑

动态部署

我心中最理想的架构是将博文、图片等静态资源存放在github中,服务端通过定时更新或监听更新的方式同步github上的资源文件,然后在github上编写markdown文件即可自动同步博客网站的内容。这样做内容管理优势有几点:

  1. github充当备份,万一哪天你忘了你服务器上还有这个博客服务,你还有github帮你记着。
  2. 免去了markdown编辑器的开发工作,github上可以新增和编辑markdown文件,当然你可以使用印象笔记等软件编写然后复制过来。自己写的编辑器还要做大量的优化工作,大概率没别人写的好,所以就不造轮子了。
  3. 免去繁杂的同步工作。

服务端也可以选择使用 hexo theme 模板 或前后端分离的方式进行开发,我这里选择只提供接口做数据服务。当然hexo theme模板来的简单,也好看。

以centos7为例,下面是部署方式:

  1. node环境、hexo环境、接口搭建
  2. npm install -g forever
  3. cd <your-blog-site>
  4. 创建一个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');
        })
    })
  5. forever start index.js
  6. netstat -ntpl查看4000端口是不是被启用了。
  7. 用nginx把这个端口代理了,然后就可以访问了。

到这里我们就完成了博客的内容管理,实现了IO接口,但这时候我放弃了。
我开始思考我为什么要做用这么一个需要长期维护的东西来练手,要写东西的话有简书、segementfault等网站支持,为什么不从那边写完再爬数据。而且接下来要做服务器与github同步的工作还挺复杂,功能简单,但很消耗我的服务器性能,实在是得不偿失……

Hexo博客框架适合人群

  1. 学生,用于找工作,搭建真的很傻瓜,但效果还蛮好的,上手操作也简单。
  2. 设计工作者,hexo是偏向内容管理的,我在theme库中看到了好多比较好看的博客模板,到目前为止还在使用的那些博主几乎都是做设计的。

这里分享一个我很喜欢的风格:

https://clovertuan.github.io/

相关推荐