从一个小项目谈 Web 开发
前阵子和室友一个做了一个关于追梦的网站(《追者》, 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 会更 优雅 好用 ,这次项目并没有尝试,有机会尝试下。
二、后端
后端开发工具:
- 包管理、环境隔离 pip、virtualenv
- pyenv (https://github.com/yyuu/pyenv)
- pyenv-virtualenv (https://github.com/yyuu/pyenv-virtualenv)
- pip-tools (https://github.com/nvie/pip-tools),其中的 pip-dump 可以方便的把 requirements 写到 requirements*.txt 中。以前都是 pip freeze > requirements.txt .
- 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 开发社交类网站,“标配”的插件有:
- FLask-Login。
- Flask-WTF。
- Flask-SQLAlchemy
- Flask-Script
除此之外,《追者》也使用了其他 Extendsions:
- Flask-Babel。多语言支持插件。这个项目本身是面向本科应届毕业生,实际上是否支持多语言都无所谓。但由于习惯问题,为了能够让代码、模板中尽量不出现中文,使用了 Flask-Babel 来把中文集中到 .po 文件中。
- Flask-Bcrypt。Flask 上的 Bcrypt 加密算法。
- Flask-Cache。《追者》中有几个排名,rank 值每天计算一次,这些 rank 值并不值得保存到数据库。这些数据并没有持久化的需要,保存到内存中比较好,因此《追者》选择把这些 rank 值存到 Redis 。Flask-Cache 封装了对 Redis 的操作,提供了简便的接口。
- Flask-OAuthlib。《追者》支持通过微博登录,用这个插件来支持微博登录。
在生产环境中还会遇到一些开发过程中不会遇到的问题,使用 Sentry 跟踪生产环境出现的 Bug,安装 raven。
三、前端
- node & npm。
- bower。用 bower 安装前端使用到的一些库。
- gulp。开发工具。
- Stylus & coffeescript。
- uglify
- 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 来自动化更新版本。
六、结语
虽然以前做过很多项目,也明白每一层技术栈都有很多内容可以学、可以做。但是这个项目真的让我深刻体会到这点。 以往开发,会比较注重后端开发工具使用,但服务器、前端、发布这几部分就没有太过注意。
在讨论功能之前,我觉得这个网站应该不会很难,开发不会花太多时间。但开发过后才意识到,如果要严格按照工程要求来做的话,即使这么简单的网站,也是要花费很多精力,看来自己估计工作量的经验还是不足。