1. 对象存储
对象存储类似云盘,可以将一些小文件存储进去,并暴露出来外链,配合cdn之后访问非常快。我们的目标就是把网站的css、js、图片等其他一些资源上传进去,再通过cdn来加速访问。
这里我使用到的是腾讯云的cos对象存储: https://console.cloud.tencent.com/cos
1.1 新建存储桶
首先新建一个存储桶
选个离自己近的地域,起个名称,先选择公有读私有写。然后一路下一步就行。
1.2 上传文件
点进刚刚建好的存储桶,随便上传一个文件,我传了一个图片
1.3 查看域名
存储桶列表,找到刚刚建好的存储桶,点配置管理,可以看到我们的访问域名
访问域名 文件路径 就可以访问到我们上传到存储桶的资源
可以直接访问测试一下
2. node自动上传
我们可以在存储桶上传我们的js、css之类的文件、不过我们的文件那么多,一个一个上传明显不合理。要你你也不干。
这时候,这些批量又重复的操作应该由我们的node出马,让我们来通过 node来批量上传我们的资源文件
2.1 获取密钥
在密钥管理下可以新建一个密钥,一会要用
2.2 遍历目录
既然要上传所有静态文件,那么就要先拿到所有静态文件的绝对路径。这里我写了个方法文件,可以遍历指定目录,返回一个数组。
代码语言:javascript复制注意,遍历目录的方法是异步的,所以这里使用promise,大概一秒足够遍历完所有文件
1// node fs模块
2const fs = require("fs");
3// node path模块
4const path = require("path");
5
6// 收集所有的文件路径
7const arr = [];
8const fileDisplay = (filePath) => {
9 //根据文件路径读取文件,返回文件列表
10 return new Promise((resolve) => {
11 fs.readdir(filePath, function (err, files) {
12 if (err) return console.error("Error:(spec)", err);
13 files.forEach((filename) => {
14 //获取当前文件的绝对路径
15 const filedir = path.join(filePath, filename);
16 // fs.stat(path)执行后,会将stats类的实例返回给其回调函数。
17 fs.stat(filedir, (eror, stats) => {
18 if (eror) return console.error("Error:(spec)", err);
19 // 是否是文件
20 const isFile = stats.isFile();
21 // 是否是文件夹
22 const isDir = stats.isDirectory();
23 if (isFile) {
24 // 这块我自己处理了多余的绝对路径,第一个 replace 是替换掉那个路径,第二个是所有满足的直接替换掉
25 arr.push(
26 filedir
27 .replace(
28 "D:lhstudyjiaoshoujiavuegenerator-lh-vuegeneratorsapp",
29 ""
30 )
31 .replace(//gim, "/")
32 );
33 }
34 // 如果是文件夹
35 if (isDir) fileDisplay(filedir);
36 });
37 });
38 });
39
40 setTimeout(() => {
41 resolve(arr);
42 }, 1000);
43 });
44};
45module.exports = fileDisplay;
46
2.3 编写上传脚本
脚本思路就是,先把cdn上原来旧的文件清理,然后再将新文件逐一上传。 这里封装了两个方法
代码语言:javascript复制1const fs = require("fs");
2const path = require("path");
3const COS = require("cos-nodejs-sdk-v5");
4//上面封装的遍历目录方法
5const fileDisplay = require("./fileDispaly");
6//2.1拿到的密钥
7const cos = new COS({
8 SecretId: "xxxxxxxxxxxx",
9 SecretKey: "xxxxxxxxxxxxxxx",
10});
11/* 存储桶名称 */
12const bucket = "hylcdn-1305519392";
13/* 存储桶所在地域 */
14const region = "ap-beijing";
15
16// 需要上传的文件夹地址
17const filePath = path.resolve("build/");
18
19// 批量删除文件,先查后删
20const deleteOldFile = () => {
21 return new Promise((resolve) => {
22 cos.getBucket(
23 {
24 Bucket: bucket,
25 Region: region,
26 Prefix: "static/", //要清理的目录
27 Marker: "static/", //要清理的目录
28 MaxKeys: 1000,
29 },
30 function (listError, listResult) {
31 if (listError) return console.log("list error:", listError);
32 var objects = listResult.Contents.map(function (item) {
33 return { Key: item.Key };
34 });
35 if (objects.length) {
36 cos.deleteMultipleObject(
37 {
38 Bucket: bucket,
39 Region: region,
40 Objects: objects,
41 },
42 function (delError, deleteResult) {
43 if (delError) {
44 console.log(delError);
45 }
46 if (deleteResult?.statusCode === 200) {
47 console.log("清理原static目录成功!");
48 resolve();
49 }
50 }
51 );
52 } else {
53 console.log("目录下无资源,无需删除!");
54 resolve();
55 }
56 }
57 );
58 });
59};
60
61//单个上传文件
62const uploadFile = (pathItem) => {
63 cos.putObject(
64 {
65 Bucket: bucket,
66 Region: region,
67 Key: `static/${pathItem.split("static/")[1]}`, //上传到 存储桶 的路径 *
68 StorageClass: "STANDARD",
69 Body: fs.createReadStream(pathItem), // 被上传的 文件对象
70 },
71 function (err, data) {
72 if (data?.statusCode === 200) {
73 console.log(`上传${pathItem.split("/").pop()}到cdn成功!`);
74 }
75 }
76 );
77};
78
79const playUpload = async () => {
80 // 先删除原来的static
81 await deleteOldFile();
82 // 获取即将上传的所有文件路径
83 const fileData = await fileDisplay(filePath);
84 // 开始逐一上传
85 fileData.forEach((item) => {
86 uploadFile(item);
87 });
88};
89
90playUpload();
91
2.4 效果
运行脚本
3. 修改项目的静态文件指向
项目默认一般是指向根目录,我们把它改成我们的存储桶cdn链接(这里我使用了自定义域名,1.3那个访问域名也可以)
以creat-react-app为例
效果,使用了cdn链接后资源加载的非常快
4. 自动化部署
修改package.json scripts配置
将打包,上传cdn,上传服务器 三个脚本合成一个指令
一条龙服务
附上我上传项目到服务器的脚本配置
代码语言:javascript复制1const scpClient = require("scp2")
2const ora = require("ora")
3const server = {
4 host:"xx.xx.xx.xx",//服务器IP
5 port:22,//服务器端口
6 username:"root",//服务器ssh登录用户名
7 password:"xxx",//服务器ssh登录密码
8 path:"/www/wwwroot/my-blog"//服务器web目录
9}
10const loading = ora("正在部署至 " server.host )
11loading.start()
12scpClient.scp("build/", server ,(err)=>{
13loading.stop()
14 if(err) {
15 console.log("部署失败")
16 throw err
17 }else {
18 console.log("部署成功")
19 }
20})
21
可能遇到的问题
1、产生了额外的流量费,欠费。
因为这个存储桶会产生四种流量费,建议都购买一下
- 标准存储容量费用:这个开始会自动送你50个G
- CDN 回源流量费用:这个需要买,一年十块左右
- 标准存储请求费用:一年一块钱
- 外网下行流量费用:一个月三块左右