前阵子和室友一个做了一个关于追梦的网站(《追者》, https://ichaser.net),产品本身的功能很简单,但是从技术层面来看,《追者》也是普普通通的一个网站。也许和平常我所开发的 Web 不同的是,这个 Web 每一层技术栈都尝试使用一些现代化开发工具,特别是前端工具链。这篇 Blog 记录了这个网站使用的一些工具和技术架构,作为这个网站的技术总结。当然,所列举的工具并不一定是最“现代化”的,欢迎一起讨论。

一、服务器

服务器使用了我一贯喜欢的搭配 Nginx + Gunicorn + Gevent。 iChaser 采用了灰度发布的方式,设置了 stage 和 prod。为了方便分别发布 stage 和 prod,服务器配置了 Supervisord (http://supervisord.org/)。酱就能通过命令来重启对应的服务:

$ supervisorctl restart ichaser:prod
$ supervisorctl restart ichaser:stage

另外,tonyseek 多次提示 circus & systemd 会更 优雅 好用 ,这次项目并没有尝试,有机会尝试下。

二、后端

后端开发工具:

  1. 包管理、环境隔离 pip、virtualenv
  2. pyenv (https://github.com/yyuu/pyenv)
  3. pyenv-virtualenv (https://github.com/yyuu/pyenv-virtualenv)
  4. pip-tools (https://github.com/nvie/pip-tools),其中的 pip-dump 可以方便的把 requirements 写到 requirements*.txt 中。以前都是 pip freeze > requirements.txt .
  5. foreman (Ruby 写的工具,Python 可以使用 Honcho)。Procfile 可以配置前端后端运行的名,前端可以用一些前端开发工具,例如 Browser-Sync ,同步更新浏览器页面;12-factor (http://12factor.net/) 提倡 Store config in environment ,配置 .env 文件,通过 foreman 可以使 app 达到这一规范。另外,在生产环境中,supervisord 配置文件中也可以配置 env,达到这规范的成本并不高。

后端开发使用 Flask 框架,以及 Flask 的 Extensions。用 Flask 开发社交类网站,“标配”的插件有:

  1. FLask-Login。
  2. Flask-WTF。
  3. Flask-SQLAlchemy
  4. Flask-Script

除此之外,《追者》也使用了其他 Extendsions:

  1. Flask-Babel。多语言支持插件。这个项目本身是面向本科应届毕业生,实际上是否支持多语言都无所谓。但由于习惯问题,为了能够让代码、模板中尽量不出现中文,使用了 Flask-Babel 来把中文集中到 .po 文件中。
  2. Flask-Bcrypt。Flask 上的 Bcrypt 加密算法。
  3. Flask-Cache。《追者》中有几个排名,rank 值每天计算一次,这些 rank 值并不值得保存到数据库。这些数据并没有持久化的需要,保存到内存中比较好,因此《追者》选择把这些 rank 值存到 Redis 。Flask-Cache 封装了对 Redis 的操作,提供了简便的接口。
  4. Flask-OAuthlib。《追者》支持通过微博登录,用这个插件来支持微博登录。

在生产环境中还会遇到一些开发过程中不会遇到的问题,使用 Sentry 跟踪生产环境出现的 Bug,安装 raven。

三、前端

  1. node & npm。
  2. bower。用 bower 安装前端使用到的一些库。
  3. gulp。开发工具。
  4. Stylus & coffeescript。
  5. uglify
  6. browser-sync

gulpfile 中配置 watch 命令,监视项目中所有 stylus 和 coffee 文件是否有改动,由 browser-sync 完成浏览器刷新工作。

uglify 只在发布的时候会触发,把编译后的 css 和 js 压缩一下。

由于在一熊实习的时候经常写 coffeescript ,熟悉了后写起来也挺顺手,于是就选择了 coffeescript 做预编译了。 而 Stylus 语法简单,熟悉 css 之后上手并没有太大困难。

四、测试

测试框架使用的是 pytest,但是这个项目里没有写测试。= =。。。

五、发布

发布前,需要更新项目新的版本号。更新版本号,使用 bumpversion 这个工具。 bumpversion 会更新项目中所有有关版本的文件,例如 setup.py 中的 version 字段。然后会 tag 当前版本:

$ bumpversion minor
$ git push --tags origin。

把 tag push 到仓库后,travis 会对仓库进行测试(好吧这个项目木有),然后构建、打包成一个 wheel 文件。

登录服务器:

$ pip install https://github.com/xxxxx

安装最新版本的项目,执行:

$ supervisorctl restart ichaser:*

重启服务。

另外,发布部分,可以写一个 fabfile 来自动化更新版本。

六、结语

虽然以前做过很多项目,也明白每一层技术栈都有很多内容可以学、可以做。但是这个项目真的让我深刻体会到这点。 以往开发,会比较注重后端开发工具使用,但服务器、前端、发布这几部分就没有太过注意。

在讨论功能之前,我觉得这个网站应该不会很难,开发不会花太多时间。但开发过后才意识到,如果要严格按照工程要求来做的话,即使这么简单的网站,也是要花费很多精力,看来自己估计工作量的经验还是不足。