Tech:部署静态Web或资源

最节省的方式部署一个静态站点。

需求阐述

任务:把已经渲染好的静态网站,部署到外网可以访问。

最简单的办法大概 3 种:

  • github page: 但是访问速度其慢或者走电信网络不稳定;且一口气完全暴露资源代码
  • nginx suburl: 但是这样一来,主站点的带宽占满 (特别阿里云这种收费奇怪的云厂商)
  • qiniu cdn: 静态资源托管,但是带宽大小未知

最终决定,还是选择最便宜的方式吧,也不是啥特别贵重的资料,数据安全性OK。

配置七牛云

一句话: 新建空间,然后绑定自定义域名

具体步骤,按照七牛的提示即可,这里是一些 attentions:

  • 域名需要在大陆备案过
  • 协议选择 https,避免被运营商劫持;以及减少 http 跳转 https 的流量
  • 根据网站的语种选择覆盖范围,只是中文书写的话,大陆就行
  • ‘内容管理’ 中设置默认域名为自己绑定的域名,千万不要使用其提供测试域名
  • ‘空间设置’ 中打开 ‘默认首页设置’, 打开 ‘空间日志’
  • 上传的 404 会在空间生成一个 ‘errno-404’ 的文件 (尽管 ‘空间设置’ 页面没有反应)

其他设置,无关紧要,高级玩家,随意。

上传文件

上传已经渲染好的文件

最好有一个 mac 端专用的图形工具,现在先将就,借用SDK 吧。

网上有一台网友已经写好的代码: github地址

先要安装 qiniu, typing 包:

1
$ pip install qiniu typing

然后在服务端修改运行下面的代码:

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
from qiniu import Auth, put_file, etag, urlsafe_base64_encode, BucketManager
from typing import List, Dict
import os
from qiniu import build_batch_delete

class Sync:
"""
同步目录至七牛云
"""
def __init__(
self,
access_key: str,
secret_key: str,
bucket_name: str,
sync_dir: str,
exclude: List,
cover: bool,
remove_redundant: bool,
):
self.bucket_name = bucket_name
self.q = Auth(access_key, secret_key)
self.bucket = BucketManager(self.q)
self.sync_dir = sync_dir
self.exclude = exclude
self.cover = cover
self.remove_redundant = remove_redundant
self.sync()
def sync(self):
"""
同步操作
:return:
"""
remote_files = self.list_remote()
local_files = self.list_local()
# 首先删除远端仓库中多余的文件
remove_remote_files = []
for remote_filename in remote_files:
if remote_filename not in local_files:
remove_remote_files.append(remote_filename)
self.bucket.batch(build_batch_delete(self.bucket_name, remove_remote_files))
# 上传本地文件到远端(仅上传远端不存在的以及修改过的)
for local_filename in local_files:
if (
local_filename not in remote_files
or local_files[local_filename]["hash"]
!= remote_files[local_filename]["hash"]
):
print("puting " + local_filename)
ret, info = put_file(
self.q.upload_token(self.bucket_name, local_filename, 3600),
local_filename,
local_files[local_filename]["fullpath"],
)
def list_remote(self) -> Dict:
"""
列出远程仓库所有的文件信息
:return: List
"""
result = {}
for file in self.bucket.list(self.bucket_name)[0]["items"]:
result[file["key"]] = file
return result
def list_local(self) -> Dict:
"""
列出本地仓库所有的文件信息
"""
files = {}
def get_files(path):
for filename in os.listdir(path):
if filename in self.exclude:
continue
fullpath = os.path.join(path, filename)
if os.path.isfile(fullpath):
key = fullpath.split(self.sync_dir)[1]
files[key] = {"fullpath": fullpath, "hash": etag(fullpath)}
else:
get_files(fullpath)
get_files(self.sync_dir)
return files

if __name__ == "__main__":
Sync(
access_key="", # access_key
secret_key="", # secret_key
bucket_name="blog", # bucket_name
sync_dir="", # 静态文件目录(后面必须有斜杠/)
exclude=[".DS_Store"],
cover=True,
remove_redundant=True,
)

这个脚本的一个亮点就是,如果本地目录没有修改,那么根本不要上传(且可以去重)

调试空间

如果上传上去的网页有问题,一般都是缓存问题(七牛的文件已经更新,但显示还是旧的)

不相信的话,可以把空间内文件全部删除,然后看看是否依旧能访问。

官方的刷新和我们的 client/browser 刷新不一样:

缓存刷新,是指删除客户资源在 CDN 节点的缓存,以便更新新的资源。

client缓存请用强制刷新: ‘Command + shift + r’ 或者浏览器调试 ‘network’ 里面 ‘disable cache’。

调试时,如果还有缓存异常,那么修改七牛空间设置,’文件客户端缓存 maxAge’ 改为 1。

  • 注意,仅刚开始调试的时候这么干,初始调试完备之后,请改回来 ‘31536000’,即 365 天。

设置刷新

之后,自己主动设置刷新缓存: 官网说明

  1. 如果你知道哪个文件更新了,一般首页的 index.html 会更新 (新增加的文件自动更新,不需要刷新),那么刷新改文件即可。
    • 比如我的情况 “/index.html”, “tags/index.html”, “categories/index.html” 等
  2. 每天更新的次数是 500 次文件,10次目录;如果一次性写好,在本地调试好了才 flush,那么直接刷新一次目录就好了,但该方式比较浪费流量。

借助官方 SDK ,编码解决问题

精细控制情况太繁杂,且一般我都是本地调试的完完整整才会向上push,所以下面就用 sdk 刷新主路径 ‘/‘ 的方式来处理:

(其实就是在原有的代码后面,发送一个 post http 请求)

1.首先现根据自己的 sk (secret key) 生成一个独一无二的 token:

1
$ echo "/v2/tune/refresh" |openssl dgst -binary -hmac "用户SK" -sha1 |base64 | tr + - | tr / _

2.然后把 token 填写如下面的代码中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 写一个方法发送 post 请求
#
import requests, json

request_headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'QBox <用户AK>:<生成的token>'
}
request_url = 'http://fusion.qiniuapi.com/v2/tune/refresh'
request_data = {
"urls":[<url1>, <url2>, <url3>, ...],
"dirs":[<要刷新的目录1>, <要刷新的目录2>, <dir3>, ...],
}

result = requests.post(request_url, data=json.dumps(request_data), headers=request_headers)
print(result)

运行结果大致如下:

1
2
$ python3 ./up.py 
{"code":200,"error":"success","requestId":"xxxx","taskIds":{"https://yan.commonheart-yk.com/":"yyyy"},"invalidUrls":null,"invalidDirs":null,"urlQuotaDay":500,"urlSurplusDay":500,"dirQuotaDay":10,"dirSurplusDay":8}

说我的查询还很多,完事儿刷新目录就剩 8 次了。

整合流程

建立在你本地 serve static 完全没有问题,就差上传的基础上

整合修改一下,完整的代码大概如下:

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
from qiniu import Auth, put_file, etag, urlsafe_base64_encode, BucketManager
from typing import List, Dict
import os
from qiniu import build_batch_delete

import requests, json

class Sync:
"""
同步目录至七牛云
"""
def __init__(
self,
access_key: str,
secret_key: str,
bucket_name: str,
sync_dir: str,
exclude: List,
cover: bool,
remove_redundant: bool,
):
self.bucket_name = bucket_name
self.q = Auth(access_key, secret_key)
self.bucket = BucketManager(self.q)
self.sync_dir = sync_dir
self.exclude = exclude
self.cover = cover
self.remove_redundant = remove_redundant
self.sync()
def sync(self):
"""
同步操作
:return:
"""
remote_files = self.list_remote()
local_files = self.list_local()
# 首先删除远端仓库中多余的文件
remove_remote_files = []
for remote_filename in remote_files:
if remote_filename not in local_files:
remove_remote_files.append(remote_filename)
self.bucket.batch(build_batch_delete(self.bucket_name, remove_remote_files))
# 上传本地文件到远端(仅上传远端不存在的以及修改过的)
for local_filename in local_files:
if (
local_filename not in remote_files
or local_files[local_filename]["hash"]
!= remote_files[local_filename]["hash"]
):
print("puting " + local_filename)
ret, info = put_file(
self.q.upload_token(self.bucket_name, local_filename, 3600),
local_filename,
local_files[local_filename]["fullpath"],
)
def list_remote(self) -> Dict:
"""
列出远程仓库所有的文件信息
:return: List
"""
result = {}
for file in self.bucket.list(self.bucket_name)[0]["items"]:
result[file["key"]] = file
return result
def list_local(self) -> Dict:
"""
列出本地仓库所有的文件信息
"""
files = {}
def get_files(path):
for filename in os.listdir(path):
if filename in self.exclude:
continue
fullpath = os.path.join(path, filename)
if os.path.isfile(fullpath):
key = fullpath.split(self.sync_dir)[1]
files[key] = {"fullpath": fullpath, "hash": etag(fullpath)}
else:
get_files(fullpath)
get_files(self.sync_dir)
return files

if __name__ == "__main__":
ac_str = '你的 access_key'
sk_str = '你的 secret_key'
token_str = '你的 token'
Sync(
access_key=ac_str, # access_key
secret_key=sk_str, # secret_key
bucket_name="你的空间名", # bucket_name
sync_dir="需要上传的目录", # 静态文件目录(后面必须有斜杠/)
exclude=[".DS_Store"],
cover=True,
remove_redundant=True,
)

# refresh the dir/file
request_headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'QBox ' + ac_str + ':' + token_str
}
request_url = 'http://fusion.qiniuapi.com/v2/tune/refresh'
request_data = {
"dirs":['需要刷新的 url 路径'], # 这里的数据根据你的需要来
}
result = requests.post(request_url, data=json.dumps(request_data),
headers=request_headers)
print(result.text)

如果你自己设置了 404 页面,那么请在上面的逻辑删除远端文件前,过滤掉 ‘errno-404’ 文件。(太简单,实现:略)

文章目录
  1. 1. 需求阐述
  2. 2. 配置七牛云
  3. 3. 上传文件
  4. 4. 调试空间
  5. 5. 设置刷新
  6. 6. 整合流程
|