2018年9月23日星期日

把我的个人网站推倒重来(Part 3 - 用 Netlify 做静态网站发布)

之前两篇文章讲述了我用 Harp 和 Bootstrap 搭建新版个人网站的过程,执行 harp compile 进行构建,输出的 www 目录就是我们想要的静态网站。我可以找个传统的静态网站 host,然后通过 FTP 这种古老的方式把文件上传上去。然而这真是我在第一篇文章中说到的一个痛点,我不希望通过 FTP 部署,最好是好像我熟悉的 Heroku 那样通过 GitHub 触发部署,我每次本地更新后执行一下 git push 就行。

Heroku

因为我已经熟悉 Heroku,所以我想到的第一个服务自然是 Heroku。Heroku 官方提供一个静态网站 buildpack,把 www 目录扔进去就可以了。当然这样还是不够简单,最好是把源代码扔进去,然后 buildpack 自动帮我调用 harp compile。曾经有人做过这样一个 Harp 专用 buildpack,可惜现在已经不维护了。基于 Heroku 官方的静态网站 buildpack 自己写一个 Harp 专用 buildpack 也不是很难,而且还能继承静态网站 buildpack 那一堆 header、redirect 等配置功能。

然而 Heroku 的免费版有两个问题:

  1. 应用会自动休眠——一段时间没有请求后它就会让你的服务进入睡眠状态,直到有新请求时再唤醒。要避免这个问题,需要每个月花 $7 来升级到业余爱好者版。有一个方法能够绕过这个问题,那就是在 Heroku 上加载某些用来监控服务可靠性的 add-on,因为这种 add-on 会定期访问你的网站检查可靠性,相当于帮你不停地阻止休眠。
  2. 不支持自定义域名 HTTP——同样是必须每个月花 $7 升级才能解决。绕过的办法也不是没有,那就是用 Cloudflare 做负载均衡器,然后用它免费提供的 HTTPS 服务。(Hue Explorer 就是用这个方法做 HTTPS 的。)引入 Cloudflare 的代价是,我必须把 DNS nameserver 迁到 Cloudflare,不能继续用 Google Domains 自带的 nameserver。

尽管每个月 $7 也不是很贵,但因为我知道我的个人网站很有可能部署后就几年都不碰一下,还要惦记着在 Heroku 上保持有效的付款方式好像有点麻烦,而一旦忘记了就可能导致网站下线。因此 Heroku 不是一个很好的解决方案。

因为我最近读完了《Working with Static Sites: Bringing the Power of Simplicity to Modern Sites》,所以就翻开了看看书中还推荐哪些静态网站的 host,然后就找到了以下两个服务。

Surge.sh

Surge.sh 超级简单,它甚至没有一个基于 web 的应用管理界面,它只提供一个命令行工具把你指定的目录发布到 CDN 上。没错,Surge.sh 提供的是非常直白的 CDN 服务,你提供一个要发布的目录,它就保证所有文件都能通过一个特定的域名在 CDN 上访问到。没有 Heroku 那么复杂的功能,连动态服务器都没有,一切都是静态的。

我安装了 Surge.sh 的命令行工具,把我老版本的个人网站部署上去了,然后发现它存在两个问题:

  1. 不支持自定义域名 HTTP——这跟 Heroku 一样,只是付费的专业版更贵,每个月要 $30。此外 Surge.sh 不像 Heroku 那样交钱了它就自动调用 LetsEncrypt 帮你认证域名然后申请证书,它需要你手动申请证书。我希望部署后永远不需要维护的,这跟我的理想有点差距。
  2. 每次都要重复上传所有文件——习惯了 git 只上传 delta 的速度,体验了几次 Surge.sh 整个目录重新上传的速度,然后就不想再用了。我的理想还是执行 git push 就能完成发布。(git 利用 rsync 实现 delta 上传,很早就有人提议 Surge.sh 用 rsync 但至今尚未实现。)

Surge.sh 有意思的地方是,所有的配置都在你上传的文件里面了。需要指定域名?写一个 CNAME 文件。需要配置重定向?写一个 ROUTE 文件。

Netlify

Netlify 给我的第一印象就是 Heroku 和 Surge.sh 中间的平衡点。它的服务性质跟 Surge.sh 一样,为静态网站提供 host,而不像 Heroku 那样可以用来 host 动态网站。然而它的管理界面更像是 Heroku,配置能够在 web 上面完成,既能拖放上传整个目录,也能关联 GitHub 在 git push 时触发部署。

git push 部署

在设置好 GitHub 关联后,我尝试用 Netlify 自动部署我现有的代码。Heroku 有 buildpack 的概念,可以在 buildpack 中执行很复杂的事情,例如说指定依赖于 Node 平台上的 Harp 然后执行 harp compile。因为 Netlify 没有 buildpack 的概念,只有一个简单的「build command」文本框,我一开始还以为它做不了很复杂的事情。在研究了一番文档和别人的开源项目后,我发现只需要在「build command」填入 npm install -g harp && harp compile 就可以了。因为 Netlify 的构建系统内置了常见的脚本语言平台,所以不需要 buildpack 这样复杂的概念,直接就有现成的 npm 可以调用。接着「publish directory」填入 www,输出的静态文件目录就会成为服务的根目录。

在 Netilfy 上成功部署一次 GitHub 代码后,接下来的就很简单了。它跟 Heroku 一样,每次我本地修改完源代码只需要 git push 就会触发它部署。因为它的部署过程比 Heroku 的 buildpack 简单,所以部署速度非常快。如果我留意到部署没有成功,我可以打开 Netlify 看日志,看看什么导致部署失败了。很多时候是我写的 Harp 页面有问题,导致 harp compile 执行出错,后来我养成了 git commit 前先调用 harp compile 验证的习惯,也就是没问题了。

HTTPS 证书

Netlify 可以配置自定义域名,而且免费支持 HTTPS。(当然也是调用 LetsEncrypt 颁发证书。)可能因为我在 Netlify 添加域名时还在用 Cloudflare,没有正规地把域名指向 Netlify 的地址,只是把流量倒过去了,所以导致证书申请卡住了。后来我把 DNS 指向 Netlify 地址了,然后找他们客服帮忙,很快就搞掂了证书的问题。

这时候我发现 Cloudflare 已经没有存在的意义了,就考虑把 Cloudflare 撤销掉,但在撤销之前还是做了几个比较。第一个比较是证书本身,Cloudflare 免费版让多个网站共用一张 LetsEncrypt 证书,然后通过 SNI 支持多域名。Netlify 专门为我的 catchen.me 申请一张独立的 LetsEncrypte 证书,然后用 SNI 在这张证书上添加子域名(其实只有 www.catchen.me 一个子域名)。尽管大多数用户并不会去留意证书的细节,但我自己一张证书这感觉就很爽。

CSS/JS 打包

在上一篇文章里我说到,我把 Bootstrap 和 jQuery 的 CSS/JS 文件都放到了我自己的部署目录当中去,这样浏览器就不需要连接不同的域名和 IP 来下载这些文件。Netlify 提供一组优化选项,帮我打包和压缩这些文件。因为 harp compile 并不对 CSS/JS 进行打包和压缩,所以我就选择了让 Netlify 进行优化。

这是 Netlify 比 Heroku 和 Surge.sh 要好的地方,照顾到了 Harp 这种不自带 Webpack 且不进行优化的构建流程。使用 Cloudflare 的话,它可以帮忙进行压缩,但没有打包的选项。同样是免费的 HTTPS,这方面 Netlify 比 Cloudflare 有优势。

CDN

尽管这些 CSS/JS 文件在部署时都存在于我网站的 /css//js/ 目录当中,但一旦启用 Netlify 打包功能这些文件就不会从我的域名进行加载,打包后的版本只存在于 Cloudfront 上面,也就是 AWS 的 CDN。我尝试拿它跟 Cloudflare 的 CDN 进行对比,发现 AWS 的节点数量略微比 Cloudflare 的多一些但也没有绝对的优势。

基于上述对比,我最终选择了使用 Netlify 来发布我新版的个人网站,并且不使用 Cloudflare 来做优化,全盘依赖于 Netlify 自身的优化。这一步做完之后,新版网站就重新上线了。接下来还有很多细节可以优化,如果你想要了解更多的话,欢迎通过邮件RSS/Atom 订阅我的博客。

没有评论:

发表评论