最近我偶然得知 GitHub 的用户名是不能占着茅坑不拉屎的,详见 Name Squatting Policy(Squatting 也很精髓了),所以我就发邮件拿到了这个 2011 年就曾经注册了的用户名。再加上机缘巧合在去年一系列的事情导致我学到不少 Web 的知识,我准备慢慢改一下这个网页,所以就干脆整理下当时怎么折腾 GitHub Pages 的。

简单介绍:Github Pages 是一个托管静态网页的平台,静态网页就是没有后台数据库,仅加载一些 Html、CSS、JS 文件,很多对象存储服务和代码托管平台都自带这一功能,比如阿里云 OSS、腾讯云 COS、Amazon S3、Coding 等,还有一些专门提供这种服务的网站如 netlify 等。Hexo 就是用 markdown 文件生成这些静态网页的工具,除此之外还有 jekyll 等。

写作需要学习一个 markdown 语法,再学一个 Git 就更好不过,花不了多少时间。

以 Windows 10 (1809) 为例,在多台电脑之间同步的部分,另一台电脑同样为 Windows 10。在 macOS Catalina (10.15.2) 也这样用过,没什么问题。

Table of Contents

  1. 安装 Hexo
  2. 配置 GitHub
  3. 配置 Hexo 以及部分命令
    1. 一些可选插件
  4. Amazon S3 + CloudFront 图床
    1. OneDrive 图床
  5. 多台电脑之间同步
  6. 更新 Hexo 的版本
  7. Terminal 配置代理,及 Homebrew 的安装(Mac)

安装 Hexo

  1. 下载安装 Node.js: nodejs.org,目前 10.15.3 LTS 一路 Next 即可。成功的话 cmd 输入 node -vnpm -v 应返回版本号。mac 用 homebrew 安装也可以。

  2. 下载安装 Git: git-scm.com,目前 2.21.0 也可以一路 Next。default editor 可以换一个,PATH environment 可以改成 Git Bash Only。成功的话任意位置右键菜单应该出现 Git Bash Here

  3. 创建一个文件夹,在 cmd 中 cd 进入,然后 npm install hexo -g,完成后 hexo init 初始化这个文件夹,完成后会显示 INFO Start blogging with Hexo!

    • -g 是全局安装参数,不会安装到当前文件夹中,init 会初始化这个文件夹,初始化后在当前目录可以使用 hexo -v 看到版本号,没有初始化的目录只有 hexo-cli 版本
    • hexo-cli (command-line interface) 集成了 hexo 的一些命令用来生成和部署等,会自动附带装上
Install HexoInstall Hexo
  1. 输入 hexo g 完成后 hexo s(提示端口占用加上参数 -p <port>),浏览器访问 http://localhost:4000 可以看到 Hexo 生成的 Hello World 页面。会多出一个 public 文件夹,里面就是生成的网页。之后就用不到 cmd 了,所有命令都在 Git Bash 中进行即可。

配置 GitHub

  1. 注册一个 GitHub 账号。

  2. 在 GitHub 中建立一个 repository,输入 Repository name,必须为 <username>.github.io

  3. 在刚才的文件夹上右键 Git Bash Here,然后输入 git config --global user.email "<github-email>" 以及 git config --global user.name "<your-name>",邮箱必须是 Github 账户里的邮箱之一或者 GitHub 提供的 no-reply 邮箱,不然,倒也没啥问题,只是 commit 不会关联到自己的账户了。名字随意, GitHub 只靠邮箱关联用户名和用户: About commit email addresses, Setting your commit email address in Git

  4. 输入 ssh-keygen -t rsa -C "<github-email>",出现的几个提示都直接按回车,生成 SSH 连接的密钥。然后输入 eval "$(ssh-agent -s)",添加密钥到 ssh-agent,成功后显示 Agent pid。最后再输入 ssh-add ~/.ssh/id_rsa,添加生成的 SSH key 到 ssh-agent,成功后显示 Identity added。

  5. 在 GitHub 的 Settings -> SSH and GPG keys 界面,点击 New SSH key,把 id_rsa.pub 文件里(一般在 C:\Users\<User Name>\.ssh)内容复制进去。

  6. 输入 ssh -T git@github.com 测试添加是否成功,成功会显示你的 GitHub Username。第一次使用 SSH 时会显示:
    The authenticity of host 'github.com (13.229.188.59)' can't be established. RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. Are you sure you want to continue connecting (yes/no)? 输入 yes 后会加入到 known host 中。

verify SSH key & install Hexo plug-inverify SSH key & install Hexo plug-in

配置 Hexo 以及部分命令

  1. npm install hexo-deployer-git --save。一个部署到 GitHub 的插件,必须要装。

    • --save 会把包安装到当前文件夹的 node_modules 中,并在 package.json 里添加相关 dependencies 内容:"hexo-deployer-git": "^1.0.0"
  2. _config.yml 里填写

    • Site 部分看着填,里面的 language 会影响多语言的主题,我习惯用 en,这样页面的导航内容就是英文。
    • url 一定要填,否则一些链接会出错;permalink 我改成了 :title/,这样链接会比较短,而且没有数字看上去和谐点。这个属性可以在 markdown post 的 front-matter 部分写上新的覆盖掉这个设置
    • post_asset_folder 有人可能需要这个功能,详见 Hexo Docs - asset-folders,我不需要在首页显示完整全文就没开启
    • theme 填主题的文件夹的名称
    • deploy 部分,type: git;repository 为 GitHub 的 SSH;branch: mastermessage 可选,如果没有这一项的话,每次 git commit 的信息为 Site updated: YYYY-MM-DD HH:mm:ss
  3. 【不同 theme 会有区别】修改 theme 的 _config.yml,以及 /language/zh-cn.yml 底部的内容。

    • 如果是源码,在 theme 文件夹上 Git Bash Here 运行 npm install ,会新建 theme/node_modules 并将相关依赖安装在内。然后 npm install -g grunt-cli 全局安装 grunt,最后 grunt buildProd(这会构建 theme,比如把 sass 编译成 css 等等,在 theme/source/assets 下)。
    • 在大局域网内,npm install 经常有问题,如果看见一堆 ERR! 多半是需要梯子。一般问题出在 sass-node,它通过 github release 下载,可以在 theme 下放一个 .npmrc 文件给它指定成淘宝源,内容如下
      1
      2
      3
      4
      sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
      phantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/
      electron_mirror=https://npm.taobao.org/mirrors/electron/
      registry=https://registry.npm.taobao.org
install grunt and build themeinstall grunt and build theme
  1. 启用分类/归档/标签功能,其实就是生成三个文件夹在 hexo/public 下,回到 Hexo 的 Git Bash 中输入 hexo new page "all-categories"hexo new page "all-archives"hexo new page "all-tags",然后修改三个 markdown 文件的内容为如下形式

    1
    2
    3
    4
    5
    ---
    title: all-archives
    layout: all-archives
    comments: false
    ---
  2. Git bash 中的一些 hexo 命令

    • hexo g 为在本地新生成页面,生成完之后可以 hexo s 在本地看看效果
    • hexo d 为把 public 文件夹中的内容推送到 github,可以加上参数 -- message "<>" 指定 git commit 的信息。执行第一次之后会多出 .deploy_git 文件夹,里面就是带版本控制的 public 文件夹(真正推送到 GitHub)
    • hexo clean 清除 public 文件夹中历史生成的文件,不常用
  3. 至此,只需要把新的 markdown 文件放入 hexo/source/_posts ,图片可以放入 hexo/source/images/theme/source/assets/images/ 中以相对方式引用。然后运行上述命令生成推送。

一些可选插件

使用 npm install <plug-in name> --save 安装。

  1. hexo-filter-auto-spacing

自动在中英文间加上空格的插件(我喜欢手动)。

  1. hexo-image-lazyload

图片懒加载的插件。

  1. hexo-generator-sitemap

部署时自动创建 sitemap,方便 Google 抓取。

  1. hexo-math

重点说说这个,一个可以插入 MathJax 的插件,这样可以在文内优雅地使用 LaTex 公式。

安装完了在 _config.yml 配置一下,加上下面的内容:

1
2
3
4
math:
engine: mathjax
mathjax:
src: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

主要是将 source 换成 jsdelivr,默认的 cloudflare 经实践在局域网很多地方加载有问题。

还要干一件事是,这个插件显然是在 markdown 渲染到 html 以后才在页面中插入 MathJax 的脚本,然后加载 html 之后才完成替换。所以公式中大量的 _ 很可能被渲染成了 <em></em>,毕竟 markdown 语法中也有 _(和 * 是一样的作用),用于标注斜体或粗体。所以我们要去掉对 _ 的渲染,只保留 * 的用法。

hexo 默认的引擎是 marked,在 node_modules/marked 中,需要打开 marked.min.js (ilb/marked.js),搜索 em:,应该会找到两处,删除掉正则表达式里面所有 _ 的部分,例如 0.7.0 版是:

1
2
3
4
5
6
7
var inline = {
em: /^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/
};

inline.pedantic = merge({}, inline.normal, {
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
});

替换为下面的保存即可。

1
2
3
4
5
6
7
var inline = {
em: /^\*([^\s*<\[])\*(?!\*)|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/
};

inline.pedantic = merge({}, inline.normal, {
em: /^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
});

使用的时候行内公式使用 \\( equation \\),行间公式使用 $$ equation $$。注意换行要用四个斜杆了 \\\\,如果有中括号也要注意。

Amazon S3 + CloudFront 图床

总得需要一个放图片和视频等东西的地方,比较小的可以直接放到 GitHub 上,但是 repository 目前有 1GB 的限制,所以比较大的照片和视频和其它文件就放到了 Amazon S3,费用基本是看流量,目前大概 1GB = ¥1。

  1. 注册一个账号,国际的

  2. 创建一个 S3 储存桶,名称随意,填域名就好,<username>.github.io 或者 image.<custom-domain> 这样。

  3. 在「设置 -> 权限 -> 存储桶策略」里面复制粘贴下面的内容,把 <bucket-name> 替换成刚才的,<username> 也要替换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<bucket-name>/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://<username>.github.io/*",
"http://localhost:4000/*"
]
}
}
}
]
}

"Condition" 用来防盗链,这样只有通过之内的域名(HTTP Head)才能访问这个储存桶的文件。只适用于以 https://s3-ap-northeast-1.amazonaws.com/<bucket-name>/<filename> 访问的情况。

  1. 在「属性」页面,选择静态网站托管,索引文件填 index.html,错误文档填 error.html,不必真的有这两个页面。这一步也可以不需要。

  2. 这时候往这个存储桶里上传文件,就可以有一个链接了。当然,这个链接在大型局域网下访问会很缓慢,有的还打不开。下面加上一个 CDN 就会好不少,而且在大型局域网外也会改善。

  3. 打开 CloudFront Distribution 选择 Create

    • Origin Domain Name 选择刚才 S3 Bucket 的名称
    • Alternate Domain Names (CNAMEs) 有自定义域名就填,没有就空着
    • Price Class 选择 Use Only US, Canada, Europe and Asia
    • 限制存储桶访问,创建新身份,并更新存储桶策略(授予读取权限),这样会自动在存储桶策略中的 "Statement" 中加入允许 CloudFront 访问的以下内容
      1
      2
      3
      4
      5
      6
      7
      8
      9
      {
      "Sid": "2",
      "Effect": "Allow",
      "Principal": {
      "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXX"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::<bucket-name>/*"
      }
  4. 过一会 就会部署好,使用 cloudfront.net 的域名(或自定义的)访问即可。这样有个问题是使用这个域名速度非常快但是是没有防盗链的,需要配合 AWS WAF 解决。

OneDrive 图床

不得不说 CloudFront 的速度还是相当之快,即使是 HK 上线之前局域网内也是秒开。唯一的缺点就是费用还是需要一点的,尤其是图片很多的话。目前 AWS 还没有免费额度(一年试用之后)。

后来还是希望使用完全免费的平台,也不上域名之类的。所以我现在使用的是 OneDrive,被墙了,但是同 Flickr 一样,嵌入的图片是可以打开的。使用方法很简单,想办法上传之后,然后点击嵌入,复制链接即可使用(最好删掉链接 ? 及之后的内容,否则比如 GIF 会不动)。

如果说缺点,大概就是:

  • 大局域网内不如 AWS 快
  • 每张图片都需要手动点击嵌入,复制链接(AWS 的链接前面都是相同的,链接中只需改文件名,而 OneDrive 的链接都是乱的)

多台电脑之间同步

我大多数时间使用一台 Windows 的台式机,出门旅游过年回家等用 Mac。这部分得学习 Git,感觉这也是用 GitHub Pages 的好处,廖雪峰的 Git 教程我看就很不错且够用。

  1. 前提知识:./.deploy_git/ 如前所述,这个是真正推送到 <username.github.io> 这个 repository 的文件夹,而且,每次 hexo deploy 执行的都是 force push,意味着如果这个文件夹丢失,那么之前的 commit 也都会消失。

  2. 把 theme 文件夹里可能有的 .git 文件夹删了,目录里不能同时有两个(.deploy_git 下也有一个,但是这个在 .gitignore 中被忽略了)。

  3. 新建一个 repository,称它为 backup repo(有人说用分支,但是现在 private repo 也免费了,而且还不会占一个 repo 1GB 的空间限制)。

  4. 针对 tranquilpeak 这个 theme:删掉 theme/.gitignore 里面的 assets

  5. 在 Hexo 文件夹的 Git Bash 中 git init -> git add . -> git commit -m "<info>" -> git remote add origin git@github.com:<username>/<reponame>.git -> git push -u origin master

  6. 现在,除了 public 和 node_modules 之外的所有文件都备份到了 GitHub。前者通过 Hexo g 生成,后者 npm install 安装,都是无需备份的。

  7. 在新的电脑上,首先安装 Git、Node.js、Hexo,然后配置好 SSH Key,然后把刚才的 backup repo clone 下来,再把 <username.github.io> 这个 repo clone 到 hexo 文件夹内,文件夹名称改为 .deploy_git。最后在 hexo 和 theme 上分别 npm install

    在 Windows 上有个很蠢的问题就是它可能不让用 . 开头作为文件(夹)名,需要 cmd 命令 ren <dir_path> .deploy_git 【更新:Windows10 1903 已经解决了这个问题】

  8. 之后需要在两台电脑切换时,只需在做了最新修改的一台电脑 push backup repo;然后在另一台 pull backup repo,如果执行过 hexo d 的话还要在 .deploy_git 上也 pull。就完成了多台电脑的同步,且这样不会丢失 commit history。

更新 Hexo 的版本

更新升级意义不大,大版本再折腾吧。theme 直接下载新的 release,把 _config-theme.ymlassets 文件夹复制过去覆盖就好,当然前提是看下 _config-theme.yml 有没有大变化。

Hexo 可以修改 package.json 里面的版本,最新版本号可以 npm outdated 查看,然后 npm install

Terminal 配置代理,及 Homebrew 的安装(Mac)

~/.zshrc 中添加以下两行

1
2
alias proxy="export all_proxy=socks5://127.0.0.1:1080"
alias unproxy="unset all_proxy"

之后只要在 Terminal 中输入 proxy 即可走 Shadowsocks 代理,注意端口不一定是 1080,看下 SS 的设置。配置好之后 Homebrew 以及后面的 sass-node 等的安装应该都不需要额外配置了。

如果需要使用镜像安装 Homebrew,那么先将 https://raw.githubusercontent.com/Homebrew/install/master/install 保存为 install.rb,然后修改其中的 BREW_REPO = "https://mirrors.ustc.edu.cn/brew.git".freeze,再使用 /usr/bin/ruby ~/Desktop/install.rb 安装。应该会卡在

1
2
==> Tapping homebrew/core
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core'...

这时只需 git clone git://mirrors.ustc.edu.cn/homebrew-core.git/ /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core --depth=1 即可完成安装。最后可以按照 https://mirror.tuna.tsinghua.edu.cn/help/homebrew/ 的说明都换成清华源。