blob: ad472b7a9df52782133cea2ca9f4026168892a69 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>又一个新的博客 — Hello World</title>
<link rel="stylesheet" href="../../../_static/alagitpull.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/flexboxgrid.min.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/git-pull.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../../',
VERSION: '0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="../../../_static/jquery.js"></script>
<script type="text/javascript" src="../../../_static/underscore.js"></script>
<script type="text/javascript" src="../../../_static/doctools.js"></script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
<link rel="stylesheet" href="../../../_static/custom.css" type="text/css" />
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head>
<body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="newblog">
<span id="id1"></span><h1>又一个新的博客<a class="headerlink" href="#newblog" title="Permalink to this headline">¶</a></h1>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">Publish Date:</th><td class="field-body">2018-01-15</td>
</tr>
</tbody>
</table>
<p>前段时间有朋友和我抱怨博客加载速度太慢了(。之前的博客架在Blogger上,为了让排版稍微美观一些,找了一个第三方的主题,加载了许多外部的
资源,导致网页载入速度非常慢。虽然我自己对于网站在国内的加载速度毫不在意,但是既然还有读者(少的可怜)在看,以及在这极少的读者中有用
户提出了这个问题,那就得解决。前段时间无意中看到一个博客( <a class="reference external" href="https://www.git-pull.com/index.html">git-pull</a> ),觉得主题简洁而又美观,于是开始
着手改造自己的博客。</p>
<p>这次用了「大名鼎鼎」的 <a class="reference external" href="http://www.sphinx-doc.org/en/stable/">Sphinx</a> ,一个软件开发过程中的文档生成工具来作为博客的静态网页生成引擎。
上手Sphinx非常简单,sphinx-quickstart这个工具和一般的博客生成器一样,集成了很多功能,把Makefile都写好了,可以说是完全开箱即用了。
Sphinx的默认主题是 <a class="reference external" href="https://alabaster.readthedocs.io/en/latest/">Alabaster</a> ,现在你看到的这个主题就是在Alabaster上修改而来的。</p>
<p>Sphinx的文档书写采用的是*.rst格式的文本,即 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> ,而不是Markdown。相比
之前,rst比Markdown的语法更加丰富/复杂,同时也提供了更加丰富的功能和可扩展性(虽然我估计我只能用到其中的20%甚至更少啦)。不清楚rst和
Emacs社区的 <a class="reference external" href="https://orgmode.org/">Org Mode</a> 相比哪一个的语法更加复杂呢。(</p>
<p>建设博客离不开几件事情。首先当然就是部署运维啦。Sphinx通过Makefile可以生成静态html网页,托管静态html最方便的地方当然是GitHub Pages啦。
最简单粗暴的方法是在本地的环境中写完rst文本,然后本地 make html 通过之后,将html推送到GitHub Pages中。但是这种方式的移植性不高,想写
博客的话必须坐在自己的电脑前,同时依然存在一些手动的工作。所以当然选择Docker啦。但是这次用Docker的姿势和以往不同。平时我们用Docker的时候
最终都是想要得到docker build的产物docker image,然后由image来进行部署。但是我们这次的目标是GitHub Pages,没法部署容器。所以我在
Dockerfile中生成静态html网页,然后在构建的过程中将静态网页push到repo的gh-pages分支中。当然其实不用Docker也能做到这一点。写一个脚本,
然后在CI平台上执行脚本也行,就不做优劣对比了。</p>
<p>值得一提的是,Docker在17.05-ce版本之后引入了multi stage build的功能,可以在Dockerfile中FROM多个基础镜像,在下一个stage可以直接使用
之前stage构建出的产物。以我的博客这个项目为例。假如我是想通过image来部署,那么我最终的产物是静态html文件,那么我可能需要一个nginx的基础
镜像。nginx:alpine 这个基础镜像很小,不到10MB,在Dockerfile里面将html文件COPY进去之后,最终得到的image也只有10MB左右的大小。但是
之前我们为了得到静态html文件,可能得选用一个python的基础镜像,然后再apt/apk安装一些必要的编译工具,最终只是为了几百kb的html文件,但是
构建的镜像已经上百MB了。有了multi stage build之后,这个问题便非常好地被解决了。看了下面的Dockerfile之后,整体思路就非常清晰了。目前我
在本地写完rst文本,然后git push之后,CircleCI会自动进行Dockerfile的构建,然后将编译生成的静态html推送到gh-pages分支。</p>
<div class="highlight-bash"><div class="highlight"><pre><span></span>FROM python:3.6.0 as builder
LABEL <span class="nv">maintainer</span><span class="o">=</span>clarkzjw<[email protected]>
RUN pip install virtualenv
COPY requirements.txt /app/requirements.txt
COPY bootstrap.py /app/bootstrap.py
RUN /app/bootstrap.py
ADD . /app
WORKDIR /app
RUN /bin/bash -c <span class="s2">"source /app/.venv/bin/activate && make html && make rss && cp rss.xml _build/html"</span>
FROM alpine:latest
RUN sed -i <span class="s1">'s/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g'</span> /etc/apk/repositories
RUN apk add --update git openssh-client <span class="o">&&</span> rm -rf /var/cache/apk/*
WORKDIR /html
ENV <span class="nv">COMMIT_USER</span><span class="o">=</span><span class="s2">"clarkzjw"</span>
ENV <span class="nv">COMMIT_EMAIL</span><span class="o">=</span><span class="s2">"[email protected]"</span>
ARG <span class="nv">GIT_TOKEN</span><span class="o">=</span><span class="s2">""</span>
RUN git config --global user.email <span class="nv">$COMMIT_EMAIL</span> <span class="o">&&</span> git config --global user.name <span class="nv">$COMMIT_USER</span>
RUN git clone https://clarkzjw:<span class="nv">$GIT_TOKEN</span>@github.com/clarkzjw/blog.jinwei.me.git /html <span class="o">&&</span> git checkout gh-pages
COPY --from<span class="o">=</span>builder /app/_build/html /html
RUN <span class="nb">echo</span> <span class="s2">"`date`"</span> > /html/.lastmodify <span class="o">&&</span> git add -A <span class="o">&&</span> git commit -m <span class="s2">"`date`"</span> <span class="o">&&</span> git push origin gh-pages
FROM nginx:alpine
COPY --from<span class="o">=</span>builder /app/_build/html /usr/share/nginx/html
</pre></div>
</div>
<p>另外一个问题是博客的RSS。由于Sphinx最初的设计是作为一个文档生成工具,目前市面上有的和Sphinx结合的RSS生成工具大致有:</p>
<ul class="simple">
<li>Sphinx-contrib模块中的 <a class="reference external" href="https://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/">feed</a></li>
<li>在sphinxcontrib.feed基础上开发的 <a class="reference external" href="https://github.com/junkafarian/sphinxfeed">sphinxfeed</a></li>
<li>以及更新一点的 <a class="reference external" href="https://pypi.python.org/pypi/sphinxcontrib-newsfeed">sphinxcontrib-newsfeed</a></li>
</ul>
<p>其中sphinxcontrib.feed和sphinxfeed的功能性更新都停止在2011年,不兼容Python 3,GitHub上有几个fork,但是也基本没有太多的改进。至于
sphinxcontrib-newsfeed,并不能生成符合RSS规范的输出。。。所以只好自己简单粗暴造一个轮子了!(至少生成的xml能被RSS阅读器认识。。。</p>
<p>RSS 订阅地址是 <a class="reference external" href="https://blog.jinwei.me/rss">https://blog.jinwei.me/rss</a></p>
<p>至于评论嘛。虽然博客流量小,2017年下来一年也没有10条评论,但是作为一个博客,这个功能还是必须得有!考察了目前市面上的评论方案,Disqus现在
差不多可以算是一家独大了。但是十分不喜欢Disqus。一个页面要加载的无关的数据太多了。然后看到了 <a class="reference external" href="https://github.com/posativ/isso">Isso</a> , 第一印象还不错,但是需要自己单独部
署。为了一年10条评论不到的数量级单独部署似乎成本略高。之前还见到了 <a class="reference external" href="https://staticman.net">Staticman</a> , 但是这个方案和GitHub的issue绑定,一个博客实例对应
GitHub的一个repo,然后每篇文章的评论对应这个repo中的issue。但是我不太能接受,毕竟不能强制每个评论的用户都有GitHub帐号。
今天无意中看到了 <a class="reference external" href="https://just-comments.com/">just-comments</a> , 也是一个SaaS解决方案,但是非常地极简,决定先用着试试效果。(</p>
<p>下一步,打算在博客中加入 <a class="reference external" href="https://css.hanzi.co/">漢字標準格式</a> 这套排版框架。毕竟现在的页面排版看起来怪怪的,以及并不美观。(</p>
</div>
<div class="just-comments"
data-allowguests="true"
data-apikey="4bb18080-e236-4513-bd72-3a032f35d3bb">
</div>
<script async defer src="https://just-comments.com/w.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
<script async defer src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo">
<a href="../../../index.html">
<img class="logo" src="../../../_static/img/terminal-icon.png" alt="Logo"/>
</a>
</p>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="../../../index.html">Documentation overview</a><ul>
</ul></li>
</ul>
</div><h3>Projects</h3>
<ul>
<li><a href="https://github.com/clarkzjw/Dehaze">Dehaze</a>
</li>
<li><a href="https://github.com/clarkzjw/GuidedFilter">GuidedFilter</a>
</li>
<li><a href="https://github.com/clarkzjw/LumberJack">LumberJack</a>
</li>
<li><a href="https://github.com/clarkzjw/one-two-three...infinity">one-two-three...infinity</a>
</li>
<li><a href="https://github.com/clarkzjw/nginx-proxy-google">nginx-proxy-google</a>
</li>
<li><a href="https://github.com/clarkzjw/brainfuck">brainfuck</a>
</li>
</ul>
<a class="github-button" href="https://github.com/clarkzjw" aria-label="Follow @clarkzjw on GitHub">Follow @clarkzjw</a>
<a class="twitter-timeline" data-width="220" data-height="800" href="https://twitter.com/_clarkzjw">Tweets by
clarkzjw</a>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©2013 - 2018, clarkzjw.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 1.6.6</a>
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.10</a>
|
<a href="../../../_sources/_posts/2018/01/new-blog.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>
|