使用github pages + issues + api建立个人博客
Closed this issue · 19 comments
[2018-09-27] 此文已经outdated,我使用angular 6重写了这个blog system. 现在只需fork并简单操作即可使用。see instructions.
不过原理仍是类似的,此文可作为参考.
以下为旧文
前言
最近写了一个简单的博客并放在github上,在此详述一下细节,以为分享。
方法并不高端,但是:
- 简单易行不要钱。
不需要数据库,不需要服务器,不需要域名
,因为github都帮我们做了,壮哉我大github! - 完全自定义的纯HTML/JS/CSS代码。不需要学各种static site generator的玩法,又能实现独一无二的个人博客
�
好了,废话稍止,进入正文。
原理就一句话
写前端代码
并host在github pages, 利用github issues做为后台, 通过github API完成前后端交互
基本介绍
-
- Github 提供的托管
静态网页
的服务,基本使用方法是建立一个名为YOUR_USER_NAME.github.io
的repo, 并把代码push到master
branch。 - 注意其只支持
静态内容
。 - 另外,如果你有自己的域名,也可以将域名指向github pages
- Github 提供的托管
-
每个github repo自带的tracking系统,支持markdown, 代码高亮,图片,表格,emoji表情
-
Github提供的API, 可以拿到你的issues内容,可以render markdown... 更多请看文档
为何不直接使用issues作为博客
事实上,直接使用issues作为博客也是可行的,从这个角度,就是把github issues当成博客平台。
这个方案的缺陷是:
- Github issues并不是为作为博客而设计的,博客平台的很多功能,比如推荐、SEO等都是没有的
- 你将受限于github的UI和用户(需要注册才能评论),无法自由的定义你想要的UI和交互
而使用github API来构建no backend app, 即可以合理利用github提供的强大功能,又能随心所欲的定义自己的网站,还能集成任意的第三方服务(评论、分享等),十分潇洒
我的玩法
本博客基于m-angular-boilerplate开发,这是我写的一个前端快速开发框架
,主要技术为angularJS + bootstrap + grunt + coffeeScript
,有兴趣的朋友可以看看。 😄
这个框架的scope不同于博客系统,在此先不多说。本文会主讲博客涉及到的内容。
上酸菜和代码
首先要在Github上建立repo,名字为YOUR_USER_NAME.github.io
, 比如我的martin-liu.github.io
。
拉到本地后开始coding。 以下为coffee编译出来的js代码,主要使用angularJS,如用其它框架实现,按同样的原理来就是
-
注册routing。就是把url和页面逻辑对应,比如
http://martin-liu.github.io/#!/
这个url就找partials/home.html
这个html,并执行HomeCtrl
这个function。如果找不到,就去404页面angular.forEach(Config.routes, function(route) { if (route.params && !route.params.controller) { route.params.controller = 'BaseCtrl'; } $routeProvider.when(route.url, route.params); }); $routeProvider.otherwise({ templateUrl: 'partials/404.html' });
Config.routes内容为:
[ { "url": "/", "params": { "name": "home", "label": "Home", "templateUrl": "partials/home.html", "controller": "HomeCtrl" } }, { "url": "/article/:id", "params": { "name": "article", "hide": true, "templateUrl": "partials/article.html", "controller": "ArticleCtrl" } }, { "url": "/about", "params": { "name": "about", "label": "About", "templateUrl": "partials/about.html" } } ]
-
Home页面的实现
- 拿issues内容
我的api link为
https://api.github.com/repos/martin-liu/martin-liu.github.io/issues?labels=blog&page=1&per_page=10&state=open
code如下,
BlogRemoteService.getBlogs()
就是ajax call刚刚那个url,拿issues数据BlogRemoteService.getBlogs().then((function(_this) { return function(blogs) { return _this.data.blogs = _this.processBlogs(blogs); }; })(this)); processBlogs = function(blogs) { return _.map(blogs, BlogService.decorateBlog); };
BlogService.decorateBlog就是下面的取summary
可以看到,文章内容有一段注释,里面是json代码。注释不会显示,但可被获取,做为metadata
<!-- { "summary":"渺小如我们,是风吹动水面,是蝴蝶一次振翅。在正确的位置,也能掀起远方的风暴;找到那个支点,也能撬动地球。" } -->
BlogService.decorateBlog的内容如下,用来解析注释内容,赋值给
blog.meta
decorateBlog: function(blog) { var e, meta, metaStr; if (!blog.body) { return blog; } metaStr = blog.body.substring(0, blog.body.indexOf('-->')); metaStr = metaStr.replace(/\n|\r|<!-{2,}/gm, ' '); try { meta = JSON.parse(metaStr); } catch (_error) { e = _error; console.log(e); } blog.meta = meta; if (blog.meta.summary) { BlogRemoteService.renderMarkdown(blog.meta.summary).then(function(data) { return blog.meta.summary = data; }); } return blog; }
- html页面, 展示blog list, 带summary。如果不用angularJS, 用handlebars或mustache也可轻松实现
<m-loading ng-if="!vm.data.blogs"></m-loading> <div ng-if="vm.data.blogs" ng-repeat="blog in vm.data.blogs"> <div style="cursor:pointer" ng-click="Util.redirect('/article/' + blog.number)"> <h3 ng-bind="blog.title"></h3> <p class="summary" ng-bind-html="blog.meta.summary"></p> <span ng-bind="blog.created_at | date:'yyyy-MM-dd'"</span>> </div> <hr/> </div>
- 拿issues内容
-
文章页面的实现
- 拿文章内容
我的api link为https://api.github.com/repos/martin-liu/martin-liu.github.io/issues/3?labels=blog&page=1&per_page=10&state=open
javascript BlogRemoteService.getBlog(id).then((function(_this) { return function(blog) { if (blog.body) { _this.data.blog = BlogService.decorateBlog(blog); BlogRemoteService.renderMarkdown(blog.body).then(function(ret) { return _this.data.content = ret; }); return $rootScope.blog = _this.data.blog; } }; })(this));
- render markdown
post
blog.content到https://api.github.com/markdown - html
<m-loading ng-if="!vm.data.content"></m-loading> <div ng-if="vm.data.content"> <h2 class="align-center" ng-bind="vm.data.blog.title"></h2> <p ng-bind="vm.data.blog.created_at | date:'yyyy-MM-dd hh:mm:ss'" class="created-at"></p> <br/> <div ng-bind-html="vm.data.content"></div> </div> <br/> <br/> <hr/> <p>欢迎扫码订阅公众号:</p> <img width="120" src="/image/qrcode_wechat.jpg"/> <div ng-if="vm.data.blog.number" duoshuo data-thread-key="{{vm.data.blog.number}}"></div>
- 拿文章内容
-
关于css
css主要是用的bootstrap, 但是代码高亮是copy from github, 代码在这里 -
使用多说评论,百度统计,jiathis社会化分享
需要到各自的网站上注册,得到相应代码以下为异步加载多说和百度统计的代码
function addScript(src){ var el = document.createElement("script"); el.src = src; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(el, s); } // duoshuo var duoshuoQuery = { short_name: 'martin-liu' } // baidu statistics var _hmt = _hmt || []; _hmt.push(['_setAutoPageview', false]); var scriptSrcs = [ 'http://static.duoshuo.com/embed.unstable.js', // duoshuo '//hm.baidu.com/hm.js?a67e974dea316e70836c07c3e3576a29' // baidu statistics ] for(var i = 0; i < scriptSrcs.length; i++){ addScript(scriptSrcs[i]); }
另外,对于多说使用angular-duoshuo来支持angularJS
<div ng-if="vm.data.blog.number" duoshuo data-thread-key="{{vm.data.blog.number}}"></div>
百度统计, url变化时触发
$rootScope.$on('$routeChangeSuccess', function($event, current) { if (_hmt) { return _hmt.push(['_trackPageview', $location.url()]); } });
-
fork me on github
见https://github.com/blog/273-github-ribbons -
使用locache做本地cache, 减少request数量,提高用户体验。我设置为5分钟失效
this.getWithCache = function(key, isSession, getFunc, timeout) { var cache, data, defer, promise; cache = Cache; if (isSession) { cache = Cache.session; } defer = $q.defer(); data = cache.get(key); if (data) { defer.resolve(data); return defer.promise; } else { promise = getFunc(); promise.then(function(data) { return cache.set(key, data, timeout); }); return promise; } };
-
push到github,等几分钟,一个新鲜的热乎乎的博客就出现了!
以下是我的部署script,因为有build过程(concat, uglify之类)#!/bin/bash grunt build ( cd dist git init git add . git commit -m "Deployed to Github Pages" git push --force --quiet "https://github.com/martin-liu/martin-liu.github.io.git" master )
Next
还有一些问题没有解决,如
- RSS
- SEO
最后
可以看到,这是个非常简单的blog,并不完善,但是workable,可以在此基础上迭代开发。这一点相当重要,因为
Done is better than perfect.(完成更胜完美)
-- facebook标语
您好,请问这个博客的内容编写必须在线上编写嘛? 就说打开issue开始写作?我有个需求就是在本地写好,然后push到issues中,可以实现吗?
@JimmyLv 可以call github的API,https://developer.github.com/v3/issues/#create-an-issue, edit也可以 😃
像你这个需求,需要自己写点代码,比如你用的编辑器的插件,或者简单点写个shell script来post/update issues
@martin-liu 我找了一下sublime的插件,并没有,啊呜。
我把sublime配成了这样,太适合写作了~
@martin-liu 又找了。。。。https://packagecontrol.io/packages/TicketMaster 所以有个问题就是,任何人都可以在你这个blog里面写内容吗?issues是大家都可以提的呀。
@JimmyLv 所以你要判断issues的owner,只有owner是自己,并且符合某种条件(比如tag)才认为是一篇博文。
这个插件如果好用的话应该就解决所有问题了,如果不好用,你可以改改code或者自己写一个
大神,你这个教程有点复杂啊。
你能给封装成gist的Embed类似的方式吗? 一行js插入 issue
大佬,你这个博客fork过来了 怎么用啊 写自己的文档。。。
@syavingc readme里有介绍: https://github.com/martin-liu/martin-liu.github.io , 你需要install nodejs, 然后npm install -g grunt
, 再follow README就可以了。
不过好几年过去了,可能会有其它问题 😅
@JimmyLv @xu-song @syavingc
鉴于录续有人问到这个project,且这个project的code已经严重落后时代了,所以我这两天抽时间用angular 6 + ng-zero 重写了一遍.
Follow instruction 即可直接使用
顶楼主一波
按照楼主的教程,用vue搭建了自己的个人博客https://pma934.github.io
基本功能算是有了,不过ui还没弄好。
还有就是感觉github的markdown api的效果不太好,想直接下载个解析效果好的markdown模块,不知道有没有推荐
@pma934 如果是觉得style不好,你可以自己改css的。你也可以试试https://github.com/markdown-it/markdown-it , 支持highlight, emoji等等
@martin-liu 谢谢大佬,之前忘了使用gfm模式,导致p标签里面没有br标签。不过,github那个api有访问限制,访问过于频繁ip会被限制,所以我换成了https://github.com/markedjs/marked
这个😁。大佬说那个我也去试试,看看哪个性能好点。顺便问一下大佬知不知道怎么实现留言板之类的。
@pma934 API访问限制,可以通过本地cache (session storage)来减少call number。
留言板我现在的实现是通过github API拿issue下的comments,然后render在文章下边,比如http://martin-liu.github.io/#/article/4 , code在这里
@martin-liu
session storage没用过,我下午看看。感觉我现在那个博客有时候加载挺慢的,说不定能用上
大佬那个方法我看了的,我的意思是如果可以不用render,而是直接在本页面放对话框就好了
@pma934 你可以考虑用Disqus(可能被�墙了)。
不过我觉得github comment是比较好的方案,不用再考虑存储问题,直接在issue里讨论也比较geek一点。
如果你想用github comment, 但又想本页面提交,也不是不行,但是访问者需要登录github才能写comment, 你可以做个check, 如果登录了github就给个框框写,没有就提示要登录github
@martin-liu 我按照https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/ 的流程来实现登录功能,在开发环境下成功了,但是在build后出现了问题。
我明明在Network收到了access_token的值,但是在console里却报错了,大佬你知道是怎么回事么
@pma934 这个是cross domain issue, 需要CORS support. 本质上来说就是github禁止你从其它domain通过ajax来访问这个url
你需要用api.github.com
而不是github.com
, 前者enable了CORS. see https://developer.github.com/v3/oauth_authorizations/ or https://developer.github.com/v3/auth/
@martin-liu 仔细又看了https://developer.github.com/v3/oauth_authorizations/ 和 https://developer.github.com/v3/auth/页面的api ,还是没找到 api.github.com
里可以替代https://github.com/login/oauth/authorize
的api。最后看到https://segmentfault.com/a/1190000011100934?utm_medium=referral&utm_source=tuicool 这篇文章,用cors-anywhere的反向代理api解决了跨域问题。
不过还是谢谢大佬的帮助
您好,请问这个博客的内容编写必须在线上编写嘛? 就说打开issue开始写作?我有个需求就是在本地写好,然后push到issues中,可以实现吗?
可以啊