“前端养成记”博客上线历程

2016 年 1 月 28 日更新:

平台选择

本博客从计划到上线,前前后后应该有快一个月吧。一开始就决定托管在 Github Pages 上,自然会从静态博客入手遴选。一开始选定的是 Jekyll 静态博客,后来又喜欢上 Hexo 的简洁;最后的最后,看到了 Ghost 的默认主题 Casper,很是喜欢。无奈 Ghost 不是静态博客,感觉像是没戏了,遂开始想要找 Casper 的 Jekyll 或 Hexo 的移植主题,也确实找到了。

Casper for Jekyll: https://github.com/rosario/kasper

Casper for Hexo:

https://github.com/MIKAGMR/hexo-theme-ghost-casper

https://github.com/kywk/hexo-theme-casper

跟静态博客不同的是,Ghost 这种轻量级的动态博客,有一个管理后台,可以直接写作和管理博客。本质上,跟 WordPress 是相通的,只是 Ghost 搭建在 Node.js 环境上,轻量,快速,简洁。

不可否认的是,Ghost 的颜值是我相当看重的一点,也确实打动我了。

所以我最终选择了 Ghost(确实一点都不 geek)。当然,前提是我找到了一套解决方案,我要做的是测试方案的可行性。

Ghost 技术栈简要解析

把 Ghost 的结构厘清,其实蛮简单,特别是使用官方已经编译好的 Ghost 压缩包解压后进行二次开发的话:

Ghost 的页面使用的是 Handlebars.js 前端模板引擎,页面总数在 10 个左右。页面采用引入/调用方式,就是把常规的 HTML 结构,譬如 meta 头信息、headerfooter 等常用且可以复用的 HTML 页面结构,给独立成一个个模板文件,而在其他诸如单篇博文页博主个人主页等页面模板文件内,引用上面的独立模板文件。譬如在单篇博文页内引入 meta 头信息模板文件,就可以达到一处编写,N 处调用的类似变量调用/引入的概念。前端模板引擎的出现,给前端开发人员缩短开发周期起到了不可或缺的作用。

不了解前端模板引擎工作原理的童鞋,请移步 Handlebars.js 官方文档。快速上手中文教程戳 这里

动态→静态,how?

所谓动态博客,需要服务器来支持数据输出。而静态页面,就是用诸如 HTMLXML 等标记语言写好结构,用 CSS 描述好表现样式,用 JavaScript 写好了交互逻辑的,理论上不再接受后端服务器数据输出而动态修改的页面。

简而言之,静态页面是死的,动态页面是活的。对于 Github Pages 这样仅支持静态网站/页面的托管服务而言,怎么搞定 Ghost 的托管呢?

这就不得不提到一个开源项目 Buster 了!

Buster 是救命稻草

Buster 的原理其实蛮简单:用 Python 语言写的一个文件路径遍历器。通过调用 Wget 把 Ghost 中用到的图片、字体、CSS、JavaScript 等静态资源统一复制到一个新的文件夹(同时此文件夹可以作为 Github Pages 的 repo),然后相应地修改 HTML 文件内引用的静态文件的路径,使之最终生效。

Buster 也是个大坑

然而,很不幸的是,Buster 这玩意最初始的项目贡献者已不再维护该项目。旧版的 Buster 对于新版的 Ghost 博客,有很多不如人意的地方(或者说,更多的是由于 Wget 的特性带来的问题),譬如:RSS 订阅功能失效博文题图无法成功获取并复制到新目录导致图片引用失效等等……

支持新版 Ghost 的 Buster 是由 Misiur 提供的:

Misiur's Buster Github Repo:https://github.com/Misiur/buster

光是选择 Buster 的 fork 版本,折腾 Buster 的用法,给 Buster 找 bug,就耗了我将近 4 天的闲暇时间,估计将近 10 个小时。

Don't BB, show the code

软件/工具准备:

  1. Node.js:前端开发人员必备。建议使用版本 v0.12.7。
  2. git / Github Desktop:用于克隆项目到本地,部署、提交项目到 Github。建议都安装,前者用于命令行操作,方便其他前端工具和工作流调用;后者用于手动图形化操作,更简便。
  3. Python:用于运行 Buster.py 脚本文件。建议使用版本 v2.7.10.
  4. Chocolatey:Windows 平台软件包管理工具。本项目主要用它来安装最新版的 Wget。

项目源码准备

Ghost 中文版:由点云网提供的中文版 Ghost。

Buster:由 Misiur 提供支持。

由于本人使用 Windows 平台,还不熟悉 Linux 和 OS X。以下代码均基于 Windows 平台,望见谅。然而我坚信,Windows 这么奇葩的平台都能搞定,Linux 和 OS X 一点问题都木有。

具体步骤:

  1. 软件/工具准备中安装的软件和工具添加到 Windows 的系统环境变量,并重启电脑;
  2. 在 Github Desktop 中创建一个名为 username.github.io 的项目,并提交到 Github(username 替换成自己的 Github 账户名,例如我的是:loyalsoldier.github.io);
  3. 下载 Ghost 中文版:https://github.com/diancloud/Ghost/releases
  4. 解压 Ghost 中文版压缩包到步骤 1 创建的项目的根目录下的 Ghost 文件夹(文件夹命名非必须 Ghost,只是方便分辨文件和之后操作而已);
  5. 把 Buster 克隆到项目根目录:在命令行提示符中输入git clone https://github.com/Misiur/buster.git,并回车;
  6. 进入 Ghost 文件夹并启动 Ghost:

    启动 Ghost 服务器

  7. 熟悉 Ghost 博客操作,包括新建博文修改博文修改个人主页等等……

  8. 熟悉操作后,可以在生产环境下进行操作了:

    配置生产环境 URL

  9. 保持 Ghost 服务器开启状态下,用 Markdown 写好你的博文

  10. 最重要的一步,用 Buster 把 Ghost 博文静态化处理:

    用 Buster 将 Ghost 博客静态化处理

  11. .gitignore 文件添加以下内容即可在向 Github 提交项目更改时,忽略掉该文件/文件夹:

    给项目添加 .gitignore 列表

  12. 如果自己有一个域名,并希望访客输入 username.github.io 时,自动跳转到个性化域名上去,可在项目根目录新建一个 CNAME 文件:

    给项目增加 CNAME 跳转

  13. 将项目提交到 Github。一两分钟后,访问 http://username.github.io 或 CNAME 文件中设置的个性域名,就可以访问自己的 Ghost 博客啦!

Ghost 进阶使用教程

添加“多说”评论

  1. 注册多说账号:http://duoshuo.com ,并填写相关设置;
  2. Ghost/content/themes/casper/post.hbs 模板文件的 {{#post}}{{/post}} 标签之间加入以下多说评论通用代码(建议放在 </footer> 标签前):

    多说评论框

  3. 配合 Ghost 蓝色的主题色,我定制了一套多说评论框的样式,供参考:

/* 评论区块基本样式 */
#ds-thread {
    margin-top: 7rem;
    padding-top: 6rem;
    border-top: 1px solid #ebf2f6;
}

/* 更改社交账号登陆 样式 */
#ds-thread #ds-reset .ds-login-buttons .ds-more-services,
#ds-thread #ds-reset .ds-login-buttons .ds-more-services:hover{
    color: #90bad3 !important;
}

/* 链接悬停样式 */
#ds-thread #ds-reset a:hover {
    color: #90bad3 !important;
}

/* 分类悬停样式 */
#ds-thread #ds-reset .ds-sort a.ds-current,
#ds-thread #ds-reset .ds-sort a:active {
    color: #90bad3 !important;
}

/* 高亮悬停样式 */
#ds-thread #ds-reset .ds-highlight {
    color: #90bad3 !important;
}

/* 评论区块底部 border 样式 */
#ds-thread #ds-reset .ds-comments {
    border-bottom-color: #ebf2f6 !important;
}

/* 评论列表顶部 border 样式*/
#ds-thread #ds-reset li.ds-post {
    border-top-color: #ebf2f6 !important;
}

/* 评论 body 文字的样式*/
#ds-thread #ds-reset .ds-comment-body p {
    color: #3a4145;
}

/* 新浪微博浮沉的链接样式*/
#ds-thread #ds-reset #ds-bubble a,
#ds-thread #ds-reset #ds-bubble a:hover {
    color: #90bad3 !important;
}

/* Power By 字体颜色 */
#ds-thread #ds-reset .ds-powered-by a,
#ds-thread #ds-reset .ds-powered-by a:hover {
    color: #ddd;
}

/* 工具条的样式 */
#ds-thread #ds-reset .ds-post-toolbar {
    border-bottom-left-radius: 0.8rem !important;
    border-bottom-right-radius: 0.8rem !important;
}

/* 发布按钮的样式 */
#ds-thread #ds-reset .ds-post-button {
    border-bottom-right-radius: 0.8rem !important;
}

#ds-thread #ds-reset .ds-post-button {
    background: #90bad3 !important;
}

#ds-thread #ds-reset .ds-post-button:hover {
    background: #7381FE !important;
}

/* 头像的样式 */
#ds-thread #ds-reset .ds-replybox .ds-avatar img,
#ds-reset .ds-avatar img {
    border-radius: 50% !important;
}

/* 评论计算器的样式 */
#ds-thread #ds-reset li.ds-tab a.ds-current {
    border-radius: 5px !important;
}

/* 评论框的样式 */
#ds-thread #ds-reset .ds-textarea-wrapper {
    border-top-left-radius: 0.8rem !important;
    border-top-right-radius: 0.8rem !important;
}


#ds-thread #ds-reset .ds-post-options {
    border-bottom-left-radius: 0.8rem;
    border-bottom-right-radius: 0.8rem;
}

/* 媒体查询 */
@media only screen and (max-width: 500px) {

    /* base */
    #ds-thread {
        margin-top: 3rem;
    }
    /* 头像 margin */
    #ds-thread #ds-reset .ds-replybox .ds-avatar {
        margin: 0 !important;
    }
    /* 工具条的样式 */
    #ds-thread #ds-reset .ds-post-options,
    #ds-thread #ds-reset .ds-post-toolbar {
        border-bottom-right-radius: 0;
        border-right-width: 0;
    }
    /* 取消 评论数的背景和边框样式 */
    #ds-thread #ds-reset li.ds-tab a.ds-current {
        border: none !important;
        background-color: initial !important;
    }
    /* 增加评论数的边距 */
    #ds-thread #ds-reset li.ds-tab a.ds-current span {
        padding-left: 4px !important;
    }
    /* 工具条工具的边距 */
    #ds-thread #ds-reset .ds-post-options .ds-sync {
        left: 1.4rem !important;
    }
    /* 隐藏 PowerBy */
    #ds-thread #ds-reset .ds-powered-by a,
    #ds-thread #ds-reset .ds-powered-by a:hover {
        display: none !important;
    }
    /* 增加评论区的底部边距 */
    #ds-thread {
        margin-bottom: 4rem !important;
    }
}

添加 CNZZ 统计

  1. 注册 CNZZ:http://www.cnzz.com
  2. 命令行输入 npm start --production 开启服务器预览;
  3. 浏览器输入 http://127.0.0.1:2368/ghost 进入生产环境下的 Ghost 后台管理系统;
  4. 点击博客设置 - 自定义代码,在网页尾部输入框中输入 CNZZ 提供的统计代码;
  5. 为了让统计代码按钮不在页面内显示,可以在 CNZZ 提供的代码外套一层 div,例如这个站点的统计代码如下:

    CNZZ 统计代码

修复 RSS 订阅

Ghost/content/themes/casper/partials/navigation.hbs 模板文件的 href="{{@blog.url}}/rss 修改为 href="{{@blog.url}}/rss/index.rss

绑定个性化域名

托管在 Github Pages 上的静态页面,都是以 username.github.io 为域名进行访问的。然而很多人肯定希望能使用自己的域名。具体步骤如下:

  1. 先完成上面的所有步骤,包括将博客静态化后,上传部署到 Github,然后使用命令行提示符,输入 ping username.github.io 获取你的 Github Pages 页面的 IP 地址(username 请替换为自己的 Github 账号名),如图:

    Ping IP

    其中 103.245.222.133 就是我的 Github Pages 个人页面的 IP 地址。

  2. 打开你注册的个人域名的域名注册商网站,比方说国内的万网新网,国外的 GoDaddy,进入管理控制台,添加域名解析。在解析记录中加入一个 A记录(必须)、一个 CNAME 记录(非必须),大体如下:

    添加域名解析记录

A 记录填写步骤 1 中 Ping 出来的 IP 地址,主机记录是 @;CNAME 记录填写你注册的个性化域名,主机记录是 www 或任何你能想到的前缀

CNAME 里添加 www 的作用是,你输入 www.loyalsoldier.me,浏览器会自动跳转到 loyalsoldier.me。你也可以添加一条叫 blog 的 CNAME 记录,那么访问 blog.loyalsoldier.me 的时候,就会自动跳转到 loyalsoldier.me。·

这里的 CNAME 跟提交到 Github 项目里的 CNAME 文件是相互跳转的功能:

这里的 CNAME 的作用是:输入 loyalsoldier.me,浏览器会跳转到 loyalsoldier.github.io。

Github 项目中 CNAME 文件的作用是:输入 loyalsoldier.github.io,浏览器跳转到 loyalsoldier.me。

注意事项

  1. 每次撰写博文,都要通过 npm start --production 开启 Ghost 服务器进入 Ghost 后台;
  2. 博文撰写完毕后,都需要重新 python buster.py generate
  3. generate 完成后,都需要提交项目更改到 Github,博文才能生效。

共同进步

有疑问,可评论、留言,将尽力解答。

如果博文存在错误,欢迎指出。我们共同进步!

Loyalsoldier

死飞,设计,编码,音乐……美物都值得善待。