由于是小水管服务器,想要网站访问速度快,就得在性能优化方面下点功夫
1.缓存
1.1数据库缓存
基于thinkjs的缓存框架,可以很容易扩展支持不同类型的缓存,比如存放到文件、内存、redis中
- think-cache-file 使用文件存储缓存数据
- think-cache-redis 使用redis存储缓存数据
- think-cache-memcache 使用内存存储缓存数据
由于访问量不大,也不想用那么多中间件,所以暂时使用高速SSD+文件做缓存存储
比如把前台经常要查询的网站配置、栏目列表存储到缓存中
module.exports = class extends think.Model {
/**
* 获取栏目列表
* @return {Array}
*/
async getCacheCategory() {
// 设置缓存 key 为 column,有效期为 30 天
const field = 'id,name,keywords,description,filename,parent_id,type,level,is_nav,icon,version,link';
const list = await this.cache('category', { timeout: 90 * 24 * 3600 * 1000 })
.where({ is_show: 1 })
.field(field)
.order('no_order ASC')
.select();
return list;
}
/**
* 获取系统配置
* @return {Object} config表配置信息
*/
async getCacheConfig() {
const rows = await this.cache('config', { timeout: 90 * 24 * 3600 * 1000 }).select();
const result = {};
rows.forEach(item => {
result[item.key] = item.value;
});
return result;
}
}
2.图片优化
2.1减少资源大小
使用到 从零搭建博客之后台开发 里提到的图片处理服务
- 图片裁剪
- 格式转换 (目前主要用对象存储提供的智能返回webp格式的功能)
获取图片缩略图是在请求时进行而不是上传的时候,为了不影响访问速度,做了一层缓存,如果命中缓存则直接返回缩略图。
module.exports = class extends think.Service {
/**
* 获取缩略图
* @param {String} src 原图地址
* @param {Number} width 目标图片宽度
* @param {Number} height 目标图片高度
* @returns {String}
*/
async getThumbnail({ src, width, height, fit }) {
// 图片地址或宽高未提供
if (think.isEmpty(src) || (!width && !height)) {
return '';
}
const destDirname = `${path.dirname(src)}/thumb`;
const fileSourceName = path.basename(src, path.extname(src));
const dest = `${destDirname}/${fileSourceName}-w${width}-h${height}.jpg`;
if (!this.thumbnailCache) {
const cache = await think.cache('thumbnail');
this.thumbnailCache = cache || {};
}
// 如果命中缓存则直接返回
if (this.thumbnailCache[dest]) {
return dest;
}
// 如果目标文件存在,则写入缓存
const destAbsolutePath = path.join(think.RESOURCE_PATH, dest);
if (think.isExist(destAbsolutePath)) {
this.cacheQueue.push({ value: dest });
} else {
// 如果目标文件不存在,则进行裁剪生成
const step = this.sharpService.resizeAndCrop({
width: +width,
height: +height,
fit: +fit,
src,
dest,
destAbsolutePath
});
this.promiseList.push(step);
}
return dest;
}
// 裁剪图片
async handleCropImage() {
let result = [];
if (this.promiseList.length) {
result = await Promise.allSettled(this.promiseList);
}
await this.addThumbnailCache([...this.cacheQueue, ...result]);
this.promiseList = [];
this.cacheQueue = [];
}
/**
* 添加缩略图缓存
* @param {String} url 缩略图地址
*/
addThumbnailCache(caches) {
if (!caches.length) return;
const temp = caches.reduce((cur, next) => {
if (next.value) {
cur[next.value] = 1;
}
return cur;
}, {});
const thumbnailCache = {
...this.thumbnailCache,
...temp
};
return think.cache('thumbnail', thumbnailCache, { timeout: 90 * 24 * 3600 * 1000 });
}
}
2.3.响应式图片
关于响应式图片,详情可以查看 web性能优化之图片处理
添加vue过滤器来设置图片的srcset属性
/**
* 获取图片的srcset属性
* @param {String} src 图片地址
* @param {Number} width 图片宽度
* @returns {String}
*/
export function getImageSrcSet (src, width = 576) {
let result = ''
const halfWidth = width / 2
const smallWidth = halfWidth < 576 ? 576 : halfWidth
if (src) {
result = `${src}?imageMogr2/thumbnail/!50p ${smallWidth}w, ${src}`
}
return result
}
使用方法:
<img
class="img-full"
:width="680"
:height="440"
:src="imgurl"
:srcset="imgurl | getImageSrcSet(680)"
alt="名称"
/>
2.4懒加载
由于某些搜索引擎爬虫对图片懒加载支持还不够,文章内容添加懒加载可能会影响SEO优化。因此目前只对某些非关键内容添加图片懒加载。
如评论列表的头像和表情等,用了element-ui实现图片懒加载还是比较简单的,直接用el-image组件加上lazy属性就好
<div class="comment-avatar">
<a
rel="noopener noreferrer"
:href="commentData.website ? commentData.website : 'javascript:;'"
:target="commentData.website ? '__blank' : ''"
:title="commentData.website"
>
<el-image class="comment-avatar__picture" :src="getAvatar(commentData)" lazy>
<div slot="error" class="image-slot">
<span class="el-icon-picture-outline" />
</div>
</el-image>
</a>
</div>
3、DNS预解析
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!--添加需要预解析的域名-->
<link rel="preconnect" href="https://at.alicdn.com">
<link rel="preconnect" href="https://cdn.timelessq.com">
<link rel="dns-prefetch" href="https://at.alicdn.com">
<link rel="dns-prefetch" href="https://cdn.timelessq.com">
</head>
</html>
还没有评论,快来抢第一吧