加速网站访问速度
分析
在发布的时候使用 qiniu nodejs sdk 将编译后的资源全部上传到七牛云,如果使用 history 路由,index.html 得使用 nginx 或者其它 web 服务器进行部署
安装 qiniu nodejs sdk
yarn add qiniu -D
// or
npm install qiniu -D
创建 qiniu.upload.js 用于上传资源文件
放在项目根路径下
const qiniu = require("qiniu");
const glob = require("glob");
const mime = require("mime");
const path = require("path");
const crypto = require("crypto");
const fs = require("fs");
// 编译后的目录
const distDir = "./dist";
const isWindow = /^win/.test(process.platform);
let pre = path.resolve(__dirname, distDir + "/") + (isWindow ? "\\" : "");
pre = pre.replace(/\\/g, "/");
const files = glob.sync(`${path.join(__dirname, distDir + "/**/*.*")}`);
const bucket = "";
const accessKey = "";
const secretKey = "";
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
const config = new qiniu.conf.Config({
// bucket 区域
zone: qiniu.zone.Zone_z2
});
const formUploader = new qiniu.form_up.FormUploader(config);
const bucketManager = new qiniu.rs.BucketManager(mac, config);
// 上传文件列表
async function uploadFiles(files) {
files.map(async file => {
const key = getFileKey(pre, file);
let md5 = await getFileMd5(file);
let info = await getQiniuFileInfo(bucket, key);
const fileExist =
info && info.respInfo && info.respInfo.data && info.respInfo.data.md5;
if (fileExist && info.respInfo.data.md5 === md5) {
console.log(`文件已存在且没有改变,跳过上传 key: ${key} md5: ${md5}`);
} else {
const changeStr =
fileExist && info.respInfo.data.md5 !== md5
? "文件发生改变重新上传,"
: "未存在的文件,";
try {
await uploadFIle(key, file);
console.log(`${changeStr}上传成功 key: ${key}`);
} catch (e) {
console.log(`${changeStr}上传失败 key: ${key} error:`, e);
}
}
});
}
// 封装单文件上传
function uploadFIle(key, localFile) {
const extname = path.extname(localFile);
const mimeName = mime.getType(extname);
const putExtra = new qiniu.form_up.PutExtra({ mimeType: mimeName });
const putPolicy = new qiniu.rs.PutPolicy({
// 覆盖上传
scope: bucket + ":" + key
});
const uploadToken = putPolicy.uploadToken(mac);
return new Promise((resolve, reject) => {
formUploader.putFile(uploadToken, key, localFile, putExtra, function(
err,
respBody,
respInfo
) {
if (err) {
reject(err);
} else {
if (respInfo.statusCode === 200) {
resolve({ respBody, respInfo });
} else {
reject(respInfo);
}
}
});
});
}
// 获取七牛文件信息
function getQiniuFileInfo(bucket, key) {
return new Promise(resolve => {
bucketManager.stat(bucket, key, function(err, respBody, respInfo) {
resolve({ respBody, respInfo });
});
});
}
// 获取文件的 key
function getFileKey(pre, file) {
if (file.indexOf(pre) > -1) {
const key = file.split(pre)[1];
return key.startsWith("/") ? key.substring(1) : key;
}
return file;
}
// 获取文件 md5
function getFileMd5(file) {
return new Promise(reslove => {
let md5sum = crypto.createHash("md5");
let stream = fs.createReadStream(file);
stream.on("data", function(chunk) {
md5sum.update(chunk);
});
stream.on("end", function() {
let fileMd5 = md5sum.digest("hex");
reslove(fileMd5);
});
});
}
(async () => {
console.time("上传文件到 cdn");
await uploadFiles(files);
console.timeEnd("上传文件到 cdn");
})();
修改 vue.config.js 的 publicPath
const cdnDomain = 'cdn地址'
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? cdnDomain : '/'
}
上传
方式一:手动执行命令
node qiniu.upload.js
方式二:编译正式环境的时候一并执行
"scripts": {
"build": "vue-cli-service build && node qiniu.upload.js"
},
写的不好,仅供参考