(教程) 静态网站部署1: 使用S3+CloudFront

本文写于2021-5-11

这篇文章讲什么?

怎么使用 AWS S3 + CloudFront 部署静态网站
(AWS 中国区)

这篇文章对谁有用?

想部署静态网站的程序员

我为什么写这篇文章?

因为我在这个事情上面浪费了不少时间,希望其他人能通过看我的文章节省时间。

这里的静态网站指的是

React.js / Vue.js 等前端项目 yarn build / npm build 之后
得到的 production build,用来部署的 .html .css .js 文件

问题:为什么选 S3 + CloudFront?

静态网站部署选项

  1. 用自己的服务器(AWS EC2/其他云服务器) + nginx/apache 来做
  2. 托管到第三方:
    • 国内服务商:
    • 国外服务商:
      • Gitlab
      • Bitbucket & aerobatic
      • Github Pages
      • Netlify
      • Surge
      • Vercel
      • Gatsby Cloud
      • Google Cloud Storage
      • Render
      • Firebase
      • Cloudflare
      • Heroku
      • Digital Ocean
      • Azure
      • deployhq
    • 不好分类:
      • AWS S3 + CloudFront(AWS 在国内国外都有区域)

由于我们的用户都是国内用户,所以国外服务商类似 Netlify 和 Github Pages 就不予考虑了,除非有办法加速,目前暂时没有找到好的方案。

如果不考虑网络因素,其实我会选 Netlify 因为用户体验很好,用起来很方便,但由于国内访问速度太慢,所以就不用它。

为什么不用阿里云 OSS / 腾讯云 COS / 七牛 / 21云盒子/等国内服务商?

因为之前我司已经有网站是用 S3+CloudFront 部署的。
而且我司目前大部分东西都是用 AWS (中国区)搞定的。
既然如此就继续沿用这个方案,因为之前已经有成功案例了。
不过之前的是其他同事弄的。这次是我来弄。

为什么不用 AWS Amplify?

中国区不支持(截止至2021-5-13)

S3 负责什么?CloudFront 负责什么?

S3 负责存放文件,就是 .html.css.js 这些文件。
CloudFront 负责做 CDN,加速访问。

能不能不用 CloudFront,只用 S3?

HTTPS 必须通过 CloudFront 来实现。所以必须用 CloudFront。
S3 本身只提供 HTTP 访问。

那用 S3 搭配其他的 CDN?比如 Cloudflare?

这我没试过,不知道,读者可以自己去试试。

步骤概览

在讲具体一步步怎么做之前,先写一个概览:

  1. 把文件传到 AWS S3(.html .css .js 等)
  2. 给 S3 设置权限,变成"可公开访问"
  3. 给 S3 设置"静态网站托管" (S3 就此告一段落,不用再回头来设置了)
  4. 去 CloudFront 设置,指向这个 S3 bucket。同时设定自定义域名(我们的域名是用阿里云管理的,没用 AWS 的 Route 53)域名是 news.(主域名部分隐去).com
  5. 设置 HTTPS 时,证书自己上传一下。

结束了,一共就这几步。

最终成果:

其实这个事情很简单,就是部署个静态站而已。
如果用 Netlify,哪怕是第一次用 Netlify,摸索一下,10分钟也就搞定了。
但 S3+CloudFront 麻烦多了。第一次弄会摸不着头脑。

具体步骤

第一步:新建一个 bucket

到时候所有的静态文件都会放到这个 bucket 里头。

这里随便建了一个 bucket 名字叫做 test-static
我在网上资料说, bucket 名字要和域名一致,但我实测结果是可以不一致,不一致也能用。

里面放一个 index.html。反正是测试嘛,内容随便写写就好了。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>简单网站2021</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
  </head>
  <body>
    <h1>世界你好</h1>
    <h1>本页面用于做一些简单测试</h1>
  </body>
</html>

第二步:修改 S3 Bucket 的权限

弄成可公开访问就行了。

第三步:S3 bucket 的 "存储桶策略"要写一下

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws-cn:s3:::test-static/*"
        }
    ]
}

第四步:启用"静态网站托管"

静态网站托管启用后,会有一个域名。
比如: http://test-static.s3-website.cn-north-1.amazonaws.com.cn/

复制下来,待会我们还用得上这个域名,要填写在其他地方。

第五步:去设置 CloudFront

进入 CloudFront 首页长这样:

这里用黑色方块隐藏掉了一些内容,和本文章无关,是公司的现有设置。

点击左上角蓝色按钮"创建分配"

然后点击"入门"

注意:"源域名"这里,不要用下拉菜单里弹出来的提示,不要在里面选。
填我们刚刚在 S3 开启静态网站托管之后得到的 HTTP 域名:
http://test-static.s3-website.cn-north-1.amazonaws.com.cn/

为什么 AWS 要做这么迷惑的行为,下拉菜单里的不能直接用,这个我也不懂。
反正我只知道下拉菜单里选的不能用,不要管它,这是 AWS 的锅,我们接着做下一步。

选择"将 HTTP 重定向到 HTTPS"

下一步:填这里

备用域名(CNAMEs) 填你想要的自定义域名,
比如我的是 news.[隐去主域名].com 是一个二级域名。
这里也可以填一级域名。

重点来了,HTTPS 这里

点击"传证书至 IAM"按钮,会打开如下窗口:

问题:为什么不用 ACM?

(ACM 指的是 AWS Certificate Manager)

因为用这玩意我怎么设置都不对,搞了很久。
和 CloudFront 搭配的证书用 ACM 怎么搞都不成功。
所以我们不用 ACM。
网上我查信息还看到说,必须去 us-east-1 在 ACM 里导入/新建证书,这样 CloudFront 里才能看到(真是奇葩)
我这里可是 AWS 中国区,哪儿来的 us-ease-1 给我用。我登录国际区的 ACM,整个页面空白,加载失败,所以也不知道是怎么回事。
反正用不了,不用它。

我们去阿里云搞一个免费证书

可以看到红框的 news.xxx.com 就是我们申请好的证书。

那一行的右侧有一个"下载",点击之后会弹出一个窗口,这里选择"其他"那一行。
点击下载。
会得到一个压缩包
5621740_news.xxx.com_other.zip

解压之后有2个文件。

  • 5621740_news.xxx.com.key
  • 5621740_news.xxx.com.pem

一个 .key 一个.pem

.key 里的内容是

-----BEGIN RSA PRIVATE KEY-----
一大堆
-----END RSA PRIVATE KEY-----

.pem 里的内容是

-----BEGIN CERTIFICATE-----
第一段
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
第二段
-----END CERTIFICATE-----

复制粘贴,填到框里:

注意开头结尾的部分也要复制,比如:

-----BEGIN CERTIFICATE-----

的部分

最后

填写完成后,等待 CloudFront 完成即可。

"分配状态"从 inProgress 变成 Deployed 就是完成了。

这时候访问 news.xxx.com 应该是可以看到成果的。

正文结束

至此,已经有一个可以访问的 HTTPS 网站了。

下一篇文章:(教程) 静态网站部署2:如何更新