326 lines
7.9 KiB
JavaScript
326 lines
7.9 KiB
JavaScript
|
|
// 性能优化工具 - 提升小程序性能和用户体验
|
||
|
|
class PerformanceOptimizer {
|
||
|
|
constructor() {
|
||
|
|
this.imageCache = new Map();
|
||
|
|
this.requestCache = new Map();
|
||
|
|
this.lazyLoadObserver = null;
|
||
|
|
this.performanceMetrics = {
|
||
|
|
pageLoadTimes: [],
|
||
|
|
apiResponseTimes: [],
|
||
|
|
imageLoadTimes: []
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 图片优化 =====
|
||
|
|
|
||
|
|
// 图片懒加载
|
||
|
|
initLazyLoad() {
|
||
|
|
// 创建懒加载观察器
|
||
|
|
this.lazyLoadObserver = wx.createIntersectionObserver();
|
||
|
|
|
||
|
|
this.lazyLoadObserver.observe('.lazy-image', (res) => {
|
||
|
|
if (res.intersectionRatio > 0) {
|
||
|
|
// 图片进入视口,开始加载
|
||
|
|
const dataset = res.dataset;
|
||
|
|
if (dataset && dataset.src) {
|
||
|
|
this.loadImage(dataset.src, res.id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 优化图片加载
|
||
|
|
async loadImage(src, elementId) {
|
||
|
|
try {
|
||
|
|
const startTime = Date.now();
|
||
|
|
|
||
|
|
// 检查缓存
|
||
|
|
if (this.imageCache.has(src)) {
|
||
|
|
const cachedImage = this.imageCache.get(src);
|
||
|
|
this.updateImageElement(elementId, cachedImage);
|
||
|
|
return cachedImage;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 预加载图片
|
||
|
|
const imageInfo = await this.preloadImage(src);
|
||
|
|
|
||
|
|
// 缓存图片信息
|
||
|
|
this.imageCache.set(src, imageInfo);
|
||
|
|
|
||
|
|
// 更新元素
|
||
|
|
this.updateImageElement(elementId, imageInfo);
|
||
|
|
|
||
|
|
// 记录性能指标
|
||
|
|
const loadTime = Date.now() - startTime;
|
||
|
|
this.recordImageLoadTime(loadTime);
|
||
|
|
|
||
|
|
return imageInfo;
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error('图片加载失败:', error);
|
||
|
|
// 使用默认图片
|
||
|
|
this.updateImageElement(elementId, { path: '/assets/images/placeholder.png' });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 预加载图片
|
||
|
|
preloadImage(src) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
wx.getImageInfo({
|
||
|
|
src: src,
|
||
|
|
success: resolve,
|
||
|
|
fail: reject
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 更新图片元素
|
||
|
|
updateImageElement(elementId, imageInfo) {
|
||
|
|
// 这里需要页面配合实现具体的更新逻辑
|
||
|
|
console.log('更新图片元素:', elementId, imageInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 请求优化 =====
|
||
|
|
|
||
|
|
// 请求缓存
|
||
|
|
async cacheRequest(key, requestFn, ttl = 300000) { // 默认5分钟缓存
|
||
|
|
const now = Date.now();
|
||
|
|
|
||
|
|
// 检查缓存
|
||
|
|
if (this.requestCache.has(key)) {
|
||
|
|
const cached = this.requestCache.get(key);
|
||
|
|
if (now - cached.timestamp < ttl) {
|
||
|
|
console.log('使用缓存数据:', key);
|
||
|
|
return cached.data;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const startTime = Date.now();
|
||
|
|
const data = await requestFn();
|
||
|
|
const responseTime = Date.now() - startTime;
|
||
|
|
|
||
|
|
// 缓存数据
|
||
|
|
this.requestCache.set(key, {
|
||
|
|
data: data,
|
||
|
|
timestamp: now
|
||
|
|
});
|
||
|
|
|
||
|
|
// 记录性能指标
|
||
|
|
this.recordApiResponseTime(responseTime);
|
||
|
|
|
||
|
|
return data;
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error('请求失败:', error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 清除过期缓存
|
||
|
|
clearExpiredCache() {
|
||
|
|
const now = Date.now();
|
||
|
|
const maxAge = 600000; // 10分钟
|
||
|
|
|
||
|
|
for (const [key, value] of this.requestCache.entries()) {
|
||
|
|
if (now - value.timestamp > maxAge) {
|
||
|
|
this.requestCache.delete(key);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 内存优化 =====
|
||
|
|
|
||
|
|
// 清理内存
|
||
|
|
cleanupMemory() {
|
||
|
|
// 清理图片缓存
|
||
|
|
if (this.imageCache.size > 50) {
|
||
|
|
const entries = Array.from(this.imageCache.entries());
|
||
|
|
const toDelete = entries.slice(0, entries.length - 30);
|
||
|
|
toDelete.forEach(([key]) => {
|
||
|
|
this.imageCache.delete(key);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 清理请求缓存
|
||
|
|
this.clearExpiredCache();
|
||
|
|
|
||
|
|
// 触发垃圾回收(如果可用)
|
||
|
|
if (wx.triggerGC) {
|
||
|
|
wx.triggerGC();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 监控内存使用
|
||
|
|
monitorMemory() {
|
||
|
|
if (wx.getPerformance) {
|
||
|
|
const performance = wx.getPerformance();
|
||
|
|
const memory = performance.memory;
|
||
|
|
|
||
|
|
if (memory) {
|
||
|
|
console.log('内存使用情况:', {
|
||
|
|
used: this.formatBytes(memory.usedJSHeapSize),
|
||
|
|
total: this.formatBytes(memory.totalJSHeapSize),
|
||
|
|
limit: this.formatBytes(memory.jsHeapSizeLimit)
|
||
|
|
});
|
||
|
|
|
||
|
|
// 如果内存使用超过80%,触发清理
|
||
|
|
if (memory.usedJSHeapSize / memory.jsHeapSizeLimit > 0.8) {
|
||
|
|
console.warn('内存使用过高,开始清理');
|
||
|
|
this.cleanupMemory();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 性能监控 =====
|
||
|
|
|
||
|
|
// 记录页面加载时间
|
||
|
|
recordPageLoadTime(loadTime) {
|
||
|
|
this.performanceMetrics.pageLoadTimes.push(loadTime);
|
||
|
|
|
||
|
|
// 只保留最近100条记录
|
||
|
|
if (this.performanceMetrics.pageLoadTimes.length > 100) {
|
||
|
|
this.performanceMetrics.pageLoadTimes.shift();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 记录API响应时间
|
||
|
|
recordApiResponseTime(responseTime) {
|
||
|
|
this.performanceMetrics.apiResponseTimes.push(responseTime);
|
||
|
|
|
||
|
|
if (this.performanceMetrics.apiResponseTimes.length > 100) {
|
||
|
|
this.performanceMetrics.apiResponseTimes.shift();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 记录图片加载时间
|
||
|
|
recordImageLoadTime(loadTime) {
|
||
|
|
this.performanceMetrics.imageLoadTimes.push(loadTime);
|
||
|
|
|
||
|
|
if (this.performanceMetrics.imageLoadTimes.length > 100) {
|
||
|
|
this.performanceMetrics.imageLoadTimes.shift();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 获取性能报告
|
||
|
|
getPerformanceReport() {
|
||
|
|
const report = {
|
||
|
|
pageLoad: this.calculateStats(this.performanceMetrics.pageLoadTimes),
|
||
|
|
apiResponse: this.calculateStats(this.performanceMetrics.apiResponseTimes),
|
||
|
|
imageLoad: this.calculateStats(this.performanceMetrics.imageLoadTimes),
|
||
|
|
cacheStats: {
|
||
|
|
imageCache: this.imageCache.size,
|
||
|
|
requestCache: this.requestCache.size
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
console.log('性能报告:', report);
|
||
|
|
return report;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 计算统计数据
|
||
|
|
calculateStats(times) {
|
||
|
|
if (times.length === 0) {
|
||
|
|
return { avg: 0, min: 0, max: 0, count: 0 };
|
||
|
|
}
|
||
|
|
|
||
|
|
const sum = times.reduce((a, b) => a + b, 0);
|
||
|
|
const avg = sum / times.length;
|
||
|
|
const min = Math.min(...times);
|
||
|
|
const max = Math.max(...times);
|
||
|
|
|
||
|
|
return {
|
||
|
|
avg: Math.round(avg),
|
||
|
|
min: min,
|
||
|
|
max: max,
|
||
|
|
count: times.length
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 工具方法 =====
|
||
|
|
|
||
|
|
// 格式化字节数
|
||
|
|
formatBytes(bytes) {
|
||
|
|
if (bytes === 0) return '0 B';
|
||
|
|
|
||
|
|
const k = 1024;
|
||
|
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
|
|
|
||
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
// 防抖函数
|
||
|
|
debounce(func, wait) {
|
||
|
|
let timeout;
|
||
|
|
return function executedFunction(...args) {
|
||
|
|
const later = () => {
|
||
|
|
clearTimeout(timeout);
|
||
|
|
func(...args);
|
||
|
|
};
|
||
|
|
clearTimeout(timeout);
|
||
|
|
timeout = setTimeout(later, wait);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// 节流函数
|
||
|
|
throttle(func, limit) {
|
||
|
|
let inThrottle;
|
||
|
|
return function executedFunction(...args) {
|
||
|
|
if (!inThrottle) {
|
||
|
|
func.apply(this, args);
|
||
|
|
inThrottle = true;
|
||
|
|
setTimeout(() => inThrottle = false, limit);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// 🔥 ===== 初始化和清理 =====
|
||
|
|
|
||
|
|
// 初始化性能优化
|
||
|
|
init() {
|
||
|
|
console.log('初始化性能优化器');
|
||
|
|
|
||
|
|
// 初始化懒加载
|
||
|
|
this.initLazyLoad();
|
||
|
|
|
||
|
|
// 定期清理内存
|
||
|
|
setInterval(() => {
|
||
|
|
this.cleanupMemory();
|
||
|
|
}, 300000); // 5分钟清理一次
|
||
|
|
|
||
|
|
// 定期监控内存
|
||
|
|
setInterval(() => {
|
||
|
|
this.monitorMemory();
|
||
|
|
}, 60000); // 1分钟监控一次
|
||
|
|
}
|
||
|
|
|
||
|
|
// 销毁优化器
|
||
|
|
destroy() {
|
||
|
|
console.log('销毁性能优化器');
|
||
|
|
|
||
|
|
// 清理懒加载观察器
|
||
|
|
if (this.lazyLoadObserver) {
|
||
|
|
this.lazyLoadObserver.disconnect();
|
||
|
|
this.lazyLoadObserver = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 清理缓存
|
||
|
|
this.imageCache.clear();
|
||
|
|
this.requestCache.clear();
|
||
|
|
|
||
|
|
// 清理性能指标
|
||
|
|
this.performanceMetrics = {
|
||
|
|
pageLoadTimes: [],
|
||
|
|
apiResponseTimes: [],
|
||
|
|
imageLoadTimes: []
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 创建全局单例
|
||
|
|
const performanceOptimizer = new PerformanceOptimizer();
|
||
|
|
|
||
|
|
module.exports = performanceOptimizer;
|