前言
为了加速网站首次访问的速度,我通过一顿操作+node脚本,以后网站每次部署都会自动将所有静态资源(css、js、图片等)上传我的cdn域名上,大大加快了网站访问速度。写篇文章记录下
可以访问我的个人网站,查看效果https://hyl999.co
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 遍历目录
既然要上传所有静态文件,那么就要先拿到所有静态文件的绝对路径。这里我写了个方法文件,可以遍历指定目录,返回一个数组。
注意,遍历目录的方法是异步的,所以这里使用promise,大概一秒足够遍历完所有文件
// node fs模块
const fs = require("fs");
// node path模块
const path = require("path");
// 收集所有的文件路径
const arr = [];
const fileDisplay = (filePath) => {
//根据文件路径读取文件,返回文件列表
return new Promise((resolve) => {
fs.readdir(filePath, function (err, files) {
if (err) return console.error("Error:(spec)", err);
files.forEach((filename) => {
//获取当前文件的绝对路径
const filedir = path.join(filePath, filename);
// fs.stat(path)执行后,会将stats类的实例返回给其回调函数。
fs.stat(filedir, (eror, stats) => {
if (eror) return console.error("Error:(spec)", err);
// 是否是文件
const isFile = stats.isFile();
// 是否是文件夹
const isDir = stats.isDirectory();
if (isFile) {
// 这块我自己处理了多余的绝对路径,第一个 replace 是替换掉那个路径,第二个是所有满足的直接替换掉
arr.push(
filedir
.replace(
"D:lhstudyjiaoshoujiavuegenerator-lh-vuegeneratorsapp",
""
)
.replace(//gim, "/")
);
}
// 如果是文件夹
if (isDir) fileDisplay(filedir);
});
});
});
setTimeout(() => {
resolve(arr);
}, 1000);
});
};
module.exports = fileDisplay;
2.3 编写上传脚本
脚本思路就是,先把cdn上原来旧的文件清理,然后再将新文件逐一上传。 这里封装了两个方法
const fs = require("fs");
const path = require("path");
const COS = require("cos-nodejs-sdk-v5");
//上面封装的遍历目录方法
const fileDisplay = require("./fileDispaly");
//2.1拿到的密钥
const cos = new COS({
SecretId: "xxxxxxxxxxxx",
SecretKey: "xxxxxxxxxxxxxxx",
});
/* 存储桶名称 */
const bucket = "hylcdn-1305519392";
/* 存储桶所在地域 */
const region = "ap-beijing";
// 需要上传的文件夹地址
const filePath = path.resolve("build/");
// 批量删除文件,先查后删
const deleteOldFile = () => {
return new Promise((resolve) => {
cos.getBucket(
{
Bucket: bucket,
Region: region,
Prefix: "static/", //要清理的目录
Marker: "static/", //要清理的目录
MaxKeys: 1000,
},
function (listError, listResult) {
if (listError) return console.log("list error:", listError);
var objects = listResult.Contents.map(function (item) {
return { Key: item.Key };
});
if (objects.length) {
cos.deleteMultipleObject(
{
Bucket: bucket,
Region: region,
Objects: objects,
},
function (delError, deleteResult) {
if (delError) {
console.log(delError);
}
if (deleteResult?.statusCode === 200) {
console.log("清理原static目录成功!");
resolve();
}
}
);
} else {
console.log("目录下无资源,无需删除!");
resolve();
}
}
);
});
};
//单个上传文件
const uploadFile = (pathItem) => {
cos.putObject(
{
Bucket: bucket,
Region: region,
Key: `static/${pathItem.split("static/")[1]}`, //上传到 存储桶 的路径 *
StorageClass: "STANDARD",
Body: fs.createReadStream(pathItem), // 被上传的 文件对象
},
function (err, data) {
if (data?.statusCode === 200) {
console.log(`上传${pathItem.split("/").pop()}到cdn成功!`);
}
}
);
};
const playUpload = async () => {
// 先删除原来的static
await deleteOldFile();
// 获取即将上传的所有文件路径
const fileData = await fileDisplay(filePath);
// 开始逐一上传
fileData.forEach((item) => {
uploadFile(item);
});
};
playUpload();
2.4 效果
运行脚本
3. 修改项目的静态文件指向
项目默认一般是指向根目录,我们把它改成我们的存储桶cdn链接(这里我使用了自定义域名,1.3那个访问域名也可以)
以creat-react-app为例
效果,使用了cdn链接后资源加载的非常快
4. 自动化部署
修改package.json scripts配置
将打包,上传cdn,上传服务器 三个脚本合成一个指令
一条龙服务
附上我上传项目到服务器的脚本配置
const scpClient = require("scp2")
const ora = require("ora")
const server = {
host:"xx.xx.xx.xx",//服务器IP
port:22,//服务器端口
username:"root",//服务器ssh登录用户名
password:"xxx",//服务器ssh登录密码
path:"/www/wwwroot/my-blog"//服务器web目录
}
const loading = ora("正在部署至 " + server.host )
loading.start()
scpClient.scp("build/", server ,(err)=>{
loading.stop()
if(err) {
console.log("部署失败")
throw err
}else {
console.log("部署成功")
}
})
可能遇到的问题
1、产生了额外的流量费,欠费。
因为这个存储桶会产生四种流量费,建议都购买一下
- 标准存储容量费用:这个开始会自动送你50个G
- CDN 回源流量费用:这个需要买,一年十块左右
- 标准存储请求费用:一年一块钱
- 外网下行流量费用:一个月三块左右