小程序性能优化指南​

小程序性能优化指南​

小程序性能优化指南 ​小程序性能优化是提升用户体验的关键环节。本指南将从启动性能、运行时性能、内存管理、网络优化等多个维度,为你提供全面的小程序性能优化策略和实践方案。

性能优化概述 ​性能指标 ​启动性能指标 ​首屏渲染时间:从小程序启动到首屏内容完全显示的时间页面切换时间:页面间跳转的响应时间代码包下载时间:小程序代码包的下载和解析时间运行时性能指标 ​页面滚动流畅度:滚动时的帧率表现交互响应时间:用户操作到界面响应的延迟内存使用量:小程序运行时的内存占用网络性能指标 ​接口响应时间:API 请求的平均响应时间资源加载时间:图片、音频等资源的加载速度网络错误率:网络请求的失败比例性能监控 ​使用小程序性能监控 ​javascript// app.js

App({

onLaunch() {

// 启用性能监控

if (wx.canIUse('getPerformance')) {

const performance = wx.getPerformance()

// 监听性能数据

performance.createObserver((entryList) => {

console.log('性能数据:', entryList.getEntries())

}).observe({ entryTypes: ['render', 'script', 'loadPackage'] })

}

},

onShow() {

// 记录应用显示时间

console.log('应用显示时间:', Date.now())

}

})12345678910111213141516171819自定义性能监控 ​javascript// utils/performance.js

class PerformanceMonitor {

constructor() {

this.marks = new Map()

this.measures = new Map()

}

// 标记时间点

mark(name) {

this.marks.set(name, Date.now())

}

// 测量时间间隔

measure(name, startMark, endMark) {

const startTime = this.marks.get(startMark)

const endTime = this.marks.get(endMark) || Date.now()

if (startTime) {

const duration = endTime - startTime

this.measures.set(name, duration)

console.log(`[PERF] ${name}: ${duration}ms`)

return duration

}

}

// 获取所有测量结果

getMeasures() {

return Object.fromEntries(this.measures)

}

// 清除所有标记

clear() {

this.marks.clear()

this.measures.clear()

}

}

// 全局性能监控实例

const performanceMonitor = new PerformanceMonitor()

export default performanceMonitor1234567891011121314151617181920212223242526272829303132333435363738394041启动性能优化 ​代码包优化 ​代码分包 ​javascript// app.json

{

"pages": [

"pages/index/index",

"pages/profile/profile"

],

"subPackages": [

{

"root": "pages/shop",

"name": "shop",

"pages": [

"list/list",

"detail/detail"

]

},

{

"root": "pages/user",

"name": "user",

"pages": [

"settings/settings",

"orders/orders"

]

}

],

"preloadRule": {

"pages/index/index": {

"network": "all",

"packages": ["shop"]

}

}

}12345678910111213141516171819202122232425262728293031独立分包 ​javascript// app.json

{

"subPackages": [

{

"root": "pages/activity",

"name": "activity",

"pages": [

"detail/detail"

],

"independent": true

}

]

}12345678910111213代码压缩和混淆 ​javascript// project.config.json

{

"setting": {

"minified": true,

"minifyJS": true,

"minifyWXML": true,

"minifyWXSS": true,

"codeProtect": true

}

}12345678910资源优化 ​图片优化 ​javascript// utils/image.js

class ImageOptimizer {

// 图片压缩

static compressImage(src, quality = 0.8) {

return new Promise((resolve, reject) => {

wx.compressImage({

src: src,

quality: quality,

success: resolve,

fail: reject

})

})

}

// 选择合适的图片格式

static chooseImageFormat(src) {

const canvas = wx.createCanvasContext('imageCanvas')

return new Promise((resolve) => {

wx.getImageInfo({

src: src,

success: (res) => {

const { width, height } = res

// 根据图片特征选择格式

if (width * height > 1000000) {

// 大图使用 JPEG

resolve('jpeg')

} else if (src.includes('icon') || src.includes('logo')) {

// 图标使用 PNG

resolve('png')

} else {

// 默认使用 WebP(如果支持)

resolve('webp')

}

}

})

})

}

// 懒加载图片

static lazyLoadImage(selector, options = {}) {

const observer = wx.createIntersectionObserver()

observer.relativeToViewport({ bottom: 100 })

observer.observe(selector, (res) => {

if (res.intersectionRatio > 0) {

const img = res.target

const dataSrc = img.dataset.src

if (dataSrc) {

img.src = dataSrc

img.removeAttribute('data-src')

observer.unobserve(selector)

}

}

})

}

}

export default ImageOptimizer12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061字体优化 ​css/* 使用系统字体 */

.text {

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;

}

/* 字体子集化 */

@font-face {

font-family: 'CustomFont';

src: url('fonts/custom-subset.woff2') format('woff2');

font-display: swap;

unicode-range: U+4E00-9FFF; /* 只包含中文字符 */

}123456789101112首屏优化 ​关键路径优化 ​javascript// pages/index/index.js

Page({

data: {

// 首屏必需数据

banners: [],

categories: [],

// 非首屏数据延迟加载

recommendations: null,

activities: null

},

onLoad() {

// 优先加载首屏数据

this.loadCriticalData()

// 延迟加载非关键数据

setTimeout(() => {

this.loadNonCriticalData()

}, 100)

},

async loadCriticalData() {

try {

const [banners, categories] = await Promise.all([

this.getBanners(),

this.getCategories()

])

this.setData({

banners,

categories

})

} catch (error) {

console.error('加载首屏数据失败:', error)

}

},

async loadNonCriticalData() {

try {

const [recommendations, activities] = await Promise.all([

this.getRecommendations(),

this.getActivities()

])

this.setData({

recommendations,

activities

})

} catch (error) {

console.error('加载非关键数据失败:', error)

}

}

})1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253骨架屏 ​xml

{{item.name}}

1234567891011121314151617181920212223242526272829css/* pages/index/index.wxss */

.skeleton {

padding: 20rpx;

}

.skeleton-banner {

width: 100%;

height: 300rpx;

background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);

background-size: 200% 100%;

animation: loading 1.5s infinite;

border-radius: 10rpx;

margin-bottom: 20rpx;

}

.skeleton-categories {

display: flex;

justify-content: space-between;

margin-bottom: 30rpx;

}

.skeleton-category {

width: 120rpx;

height: 120rpx;

background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);

background-size: 200% 100%;

animation: loading 1.5s infinite;

border-radius: 10rpx;

}

.skeleton-item {

width: 100%;

height: 200rpx;

background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);

background-size: 200% 100%;

animation: loading 1.5s infinite;

border-radius: 10rpx;

margin-bottom: 20rpx;

}

@keyframes loading {

0% {

background-position: 200% 0;

}

100% {

background-position: -200% 0;

}

}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748运行时性能优化 ​渲染性能优化 ​减少 setData 调用 ​javascript// 错误示例:频繁调用 setData

Page({

updateList() {

this.data.list.forEach((item, index) => {

this.setData({

[`list[${index}].status`]: 'updated'

})

})

}

})

// 正确示例:批量更新

Page({

updateList() {

const updates = {}

this.data.list.forEach((item, index) => {

updates[`list[${index}].status`] = 'updated'

})

this.setData(updates)

}

})123456789101112131415161718192021优化数据结构 ​javascript// 错误示例:深层嵌套

Page({

data: {

user: {

profile: {

personal: {

name: '张三',

age: 25

}

}

}

},

updateName(newName) {

this.setData({

'user.profile.personal.name': newName

})

}

})

// 正确示例:扁平化数据

Page({

data: {

userName: '张三',

userAge: 25

},

updateName(newName) {

this.setData({

userName: newName

})

}

})123456789101112131415161718192021222324252627282930313233虚拟列表 ​javascript// components/virtual-list/virtual-list.js

Component({

properties: {

items: {

type: Array,

value: []

},

itemHeight: {

type: Number,

value: 100

},

containerHeight: {

type: Number,

value: 600

}

},

data: {

visibleItems: [],

scrollTop: 0,

startIndex: 0,

endIndex: 0

},

lifetimes: {

attached() {

this.updateVisibleItems()

}

},

observers: {

'items, containerHeight, itemHeight'() {

this.updateVisibleItems()

}

},

methods: {

updateVisibleItems() {

const { items, itemHeight, containerHeight } = this.properties

const { scrollTop } = this.data

const visibleCount = Math.ceil(containerHeight / itemHeight)

const startIndex = Math.floor(scrollTop / itemHeight)

const endIndex = Math.min(startIndex + visibleCount + 1, items.length)

const visibleItems = items.slice(startIndex, endIndex).map((item, index) => ({

...item,

index: startIndex + index,

top: (startIndex + index) * itemHeight

}))

this.setData({

visibleItems,

startIndex,

endIndex

})

},

onScroll(e) {

const scrollTop = e.detail.scrollTop

this.setData({ scrollTop })

// 节流更新

clearTimeout(this.scrollTimer)

this.scrollTimer = setTimeout(() => {

this.updateVisibleItems()

}, 16)

}

}

})12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970xml

class="virtual-list"

scroll-y

style="height: {{containerHeight}}px"

bindscroll="onScroll"

scroll-top="{{scrollTop}}"

>

class="virtual-container"

style="height: {{items.length * itemHeight}}px"

>

class="virtual-item"

wx:for="{{visibleItems}}"

wx:key="index"

style="position: absolute; top: {{item.top}}px; height: {{itemHeight}}px"

>

12345678910111213141516171819202122事件优化 ​事件委托 ​javascript// 错误示例:为每个项目绑定事件

Page({

data: {

list: [

{ id: 1, name: '项目1' },

{ id: 2, name: '项目2' }

]

},

onItemTap(e) {

const id = e.currentTarget.dataset.id

console.log('点击项目:', id)

}

})1234567891011121314xml

{{item.name}}

1234javascript// 正确示例:事件委托

Page({

data: {

list: [

{ id: 1, name: '项目1' },

{ id: 2, name: '项目2' }

]

},

onListTap(e) {

const id = e.target.dataset.id

if (id) {

console.log('点击项目:', id)

}

}

})12345678910111213141516xml

{{item.name}}

123456防抖和节流 ​javascript// utils/throttle.js

export function throttle(func, delay) {

let timer = null

return function(...args) {

if (!timer) {

timer = setTimeout(() => {

func.apply(this, args)

timer = null

}, delay)

}

}

}

export function debounce(func, delay) {

let timer = null

return function(...args) {

clearTimeout(timer)

timer = setTimeout(() => {

func.apply(this, args)

}, delay)

}

}

// 使用示例

import { throttle, debounce } from '../../utils/throttle'

Page({

onLoad() {

// 节流滚动事件

this.onScrollThrottled = throttle(this.onScroll.bind(this), 100)

// 防抖搜索

this.onSearchDebounced = debounce(this.onSearch.bind(this), 300)

},

onScroll(e) {

console.log('滚动位置:', e.detail.scrollTop)

},

onSearch(keyword) {

console.log('搜索关键词:', keyword)

// 执行搜索逻辑

}

})12345678910111213141516171819202122232425262728293031323334353637383940414243内存管理优化 ​内存泄漏预防 ​清理定时器 ​javascriptPage({

onLoad() {

// 设置定时器

this.timer = setInterval(() => {

this.updateTime()

}, 1000)

},

onUnload() {

// 清理定时器

if (this.timer) {

clearInterval(this.timer)

this.timer = null

}

},

updateTime() {

this.setData({

currentTime: new Date().toLocaleTimeString()

})

}

})12345678910111213141516171819202122清理事件监听 ​javascriptPage({

onLoad() {

// 监听网络状态变化

this.onNetworkStatusChange = this.handleNetworkStatusChange.bind(this)

wx.onNetworkStatusChange(this.onNetworkStatusChange)

},

onUnload() {

// 移除事件监听

if (this.onNetworkStatusChange) {

wx.offNetworkStatusChange(this.onNetworkStatusChange)

this.onNetworkStatusChange = null

}

},

handleNetworkStatusChange(res) {

console.log('网络状态变化:', res.isConnected)

}

})12345678910111213141516171819图片资源管理 ​javascript// utils/image-cache.js

class ImageCache {

constructor(maxSize = 50) {

this.cache = new Map()

this.maxSize = maxSize

}

set(key, value) {

if (this.cache.size >= this.maxSize) {

// 删除最旧的缓存

const firstKey = this.cache.keys().next().value

this.cache.delete(firstKey)

}

this.cache.set(key, value)

}

get(key) {

return this.cache.get(key)

}

clear() {

this.cache.clear()

}

// 预加载图片

preloadImage(src) {

return new Promise((resolve, reject) => {

if (this.cache.has(src)) {

resolve(this.cache.get(src))

return

}

wx.getImageInfo({

src: src,

success: (res) => {

this.set(src, res)

resolve(res)

},

fail: reject

})

})

}

}

const imageCache = new ImageCache()

export default imageCache12345678910111213141516171819202122232425262728293031323334353637383940414243444546数据管理优化 ​分页加载 ​javascriptPage({

data: {

list: [],

page: 1,

pageSize: 20,

hasMore: true,

loading: false

},

onLoad() {

this.loadData()

},

onReachBottom() {

if (this.data.hasMore && !this.data.loading) {

this.loadMore()

}

},

async loadData() {

this.setData({ loading: true })

try {

const res = await this.fetchData(1, this.data.pageSize)

this.setData({

list: res.data,

page: 1,

hasMore: res.data.length === this.data.pageSize,

loading: false

})

} catch (error) {

console.error('加载数据失败:', error)

this.setData({ loading: false })

}

},

async loadMore() {

this.setData({ loading: true })

try {

const nextPage = this.data.page + 1

const res = await this.fetchData(nextPage, this.data.pageSize)

this.setData({

list: [...this.data.list, ...res.data],

page: nextPage,

hasMore: res.data.length === this.data.pageSize,

loading: false

})

} catch (error) {

console.error('加载更多失败:', error)

this.setData({ loading: false })

}

},

async fetchData(page, pageSize) {

return new Promise((resolve) => {

wx.request({

url: '/api/data',

data: { page, pageSize },

success: resolve

})

})

}

})1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465数据缓存策略 ​javascript// utils/cache.js

class DataCache {

constructor() {

this.cache = new Map()

this.expireTime = new Map()

}

set(key, data, ttl = 300000) { // 默认5分钟过期

this.cache.set(key, data)

this.expireTime.set(key, Date.now() + ttl)

}

get(key) {

const expireTime = this.expireTime.get(key)

if (expireTime && Date.now() > expireTime) {

this.delete(key)

return null

}

return this.cache.get(key)

}

delete(key) {

this.cache.delete(key)

this.expireTime.delete(key)

}

clear() {

this.cache.clear()

this.expireTime.clear()

}

// 清理过期缓存

cleanup() {

const now = Date.now()

for (const [key, expireTime] of this.expireTime.entries()) {

if (now > expireTime) {

this.delete(key)

}

}

}

}

const dataCache = new DataCache()

// 定期清理过期缓存

setInterval(() => {

dataCache.cleanup()

}, 60000) // 每分钟清理一次

export default dataCache1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950网络优化 ​请求优化 ​请求合并 ​javascript// utils/request-batch.js

class RequestBatch {

constructor() {

this.queue = []

this.timer = null

}

add(request) {

return new Promise((resolve, reject) => {

this.queue.push({

...request,

resolve,

reject

})

this.scheduleFlush()

})

}

scheduleFlush() {

if (this.timer) return

this.timer = setTimeout(() => {

this.flush()

}, 10) // 10ms 内的请求合并

}

flush() {

if (this.queue.length === 0) return

const requests = this.queue.splice(0)

this.timer = null

// 按接口分组

const groups = new Map()

requests.forEach(req => {

const key = `${req.method || 'GET'}_${req.url}`

if (!groups.has(key)) {

groups.set(key, [])

}

groups.get(key).push(req)

})

// 批量请求

groups.forEach((reqs, key) => {

if (reqs.length === 1) {

// 单个请求直接发送

this.sendRequest(reqs[0])

} else {

// 多个请求合并

this.sendBatchRequest(reqs)

}

})

}

sendRequest(req) {

wx.request({

...req,

success: req.resolve,

fail: req.reject

})

}

sendBatchRequest(requests) {

const batchData = requests.map(req => ({

url: req.url,

method: req.method || 'GET',

data: req.data

}))

wx.request({

url: '/api/batch',

method: 'POST',

data: { requests: batchData },

success: (res) => {

res.data.results.forEach((result, index) => {

requests[index].resolve(result)

})

},

fail: (error) => {

requests.forEach(req => req.reject(error))

}

})

}

}

const requestBatch = new RequestBatch()

export default requestBatch12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788请求缓存 ​javascript// utils/request-cache.js

import dataCache from './cache'

class RequestCache {

constructor() {

this.pendingRequests = new Map()

}

async request(options) {

const cacheKey = this.getCacheKey(options)

// 检查缓存

const cached = dataCache.get(cacheKey)

if (cached) {

return cached

}

// 检查是否有相同的请求正在进行

if (this.pendingRequests.has(cacheKey)) {

return this.pendingRequests.get(cacheKey)

}

// 发送请求

const promise = this.sendRequest(options)

this.pendingRequests.set(cacheKey, promise)

try {

const result = await promise

// 缓存结果

if (options.cache !== false) {

dataCache.set(cacheKey, result, options.cacheTTL)

}

return result

} finally {

this.pendingRequests.delete(cacheKey)

}

}

sendRequest(options) {

return new Promise((resolve, reject) => {

wx.request({

...options,

success: resolve,

fail: reject

})

})

}

getCacheKey(options) {

const { url, method = 'GET', data } = options

return `${method}_${url}_${JSON.stringify(data || {})}`

}

}

const requestCache = new RequestCache()

export default requestCache12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758资源预加载 ​关键资源预加载 ​javascript// utils/preloader.js

class ResourcePreloader {

constructor() {

this.preloadedImages = new Set()

this.preloadedData = new Map()

}

// 预加载图片

async preloadImages(urls) {

const promises = urls.map(url => {

if (this.preloadedImages.has(url)) {

return Promise.resolve()

}

return new Promise((resolve, reject) => {

wx.getImageInfo({

src: url,

success: () => {

this.preloadedImages.add(url)

resolve()

},

fail: reject

})

})

})

try {

await Promise.all(promises)

console.log('图片预加载完成')

} catch (error) {

console.error('图片预加载失败:', error)

}

}

// 预加载数据

async preloadData(requests) {

const promises = requests.map(async (req) => {

try {

const result = await this.request(req)

this.preloadedData.set(req.key, result)

} catch (error) {

console.error(`预加载数据失败 ${req.key}:`, error)

}

})

await Promise.all(promises)

console.log('数据预加载完成')

}

// 获取预加载的数据

getPreloadedData(key) {

return this.preloadedData.get(key)

}

request(options) {

return new Promise((resolve, reject) => {

wx.request({

...options,

success: resolve,

fail: reject

})

})

}

}

const preloader = new ResourcePreloader()

export default preloader12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667智能预加载 ​javascript// utils/smart-preloader.js

class SmartPreloader {

constructor() {

this.userBehavior = new Map()

this.preloadRules = new Map()

}

// 记录用户行为

recordBehavior(page, action, target) {

const key = `${page}_${action}`

if (!this.userBehavior.has(key)) {

this.userBehavior.set(key, new Map())

}

const actionMap = this.userBehavior.get(key)

const count = actionMap.get(target) || 0

actionMap.set(target, count + 1)

// 更新预加载规则

this.updatePreloadRules(key, target, count + 1)

}

// 更新预加载规则

updatePreloadRules(key, target, count) {

if (count >= 3) { // 用户访问3次以上的资源进行预加载

if (!this.preloadRules.has(key)) {

this.preloadRules.set(key, new Set())

}

this.preloadRules.get(key).add(target)

}

}

// 获取预加载建议

getPreloadSuggestions(page, action) {

const key = `${page}_${action}`

return this.preloadRules.get(key) || new Set()

}

// 执行智能预加载

async executeSmartPreload(page, action) {

const suggestions = this.getPreloadSuggestions(page, action)

for (const target of suggestions) {

try {

if (target.startsWith('http')) {

// 预加载图片

await wx.getImageInfo({ src: target })

} else {

// 预加载页面数据

await this.preloadPageData(target)

}

} catch (error) {

console.error(`智能预加载失败 ${target}:`, error)

}

}

}

async preloadPageData(page) {

// 根据页面预加载对应数据

const dataLoaders = {

'product-detail': () => this.preloadProductData(),

'user-profile': () => this.preloadUserData(),

'order-list': () => this.preloadOrderData()

}

const loader = dataLoaders[page]

if (loader) {

await loader()

}

}

}

const smartPreloader = new SmartPreloader()

export default smartPreloader1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374样式和动画优化 ​CSS 优化 ​减少重排和重绘 ​css/* 错误示例:会触发重排 */

.bad-animation {

transition: width 0.3s, height 0.3s, left 0.3s, top 0.3s;

}

/* 正确示例:只触发合成 */

.good-animation {

transition: transform 0.3s, opacity 0.3s;

}

/* 使用 transform 替代位置属性 */

.move-element {

transform: translateX(100px) translateY(50px);

}

/* 使用 opacity 替代 visibility */

.fade-element {

opacity: 0;

}12345678910111213141516171819优化选择器 ​css/* 错误示例:复杂选择器 */

.container .list .item .title .text {

color: #333;

}

/* 正确示例:简化选择器 */

.item-title-text {

color: #333;

}

/* 使用类选择器替代标签选择器 */

.button {

background: #007bff;

}

/* 避免通配符选择器 */

.container * {

box-sizing: border-box; /* 避免这样使用 */

}12345678910111213141516171819动画优化 ​使用 CSS 动画替代 JS 动画 ​css/* CSS 动画 */

@keyframes slideIn {

from {

transform: translateX(-100%);

opacity: 0;

}

to {

transform: translateX(0);

opacity: 1;

}

}

.slide-in {

animation: slideIn 0.3s ease-out;

}

/* 硬件加速 */

.hardware-accelerated {

transform: translateZ(0);

will-change: transform;

}123456789101112131415161718192021动画性能监控 ​javascript// utils/animation-monitor.js

class AnimationMonitor {

constructor() {

this.animations = new Map()

this.performanceData = []

}

// 开始监控动画

startMonitoring(name) {

const startTime = performance.now()

this.animations.set(name, {

startTime,

frames: 0,

droppedFrames: 0

})

this.monitorFrames(name)

}

// 监控帧率

monitorFrames(name) {

const animation = this.animations.get(name)

if (!animation) return

const checkFrame = () => {

if (this.animations.has(name)) {

animation.frames++

// 检查是否掉帧

const expectedFrames = (performance.now() - animation.startTime) / 16.67

if (animation.frames < expectedFrames * 0.9) {

animation.droppedFrames++

}

requestAnimationFrame(checkFrame)

}

}

requestAnimationFrame(checkFrame)

}

// 结束监控

endMonitoring(name) {

const animation = this.animations.get(name)

if (!animation) return

const duration = performance.now() - animation.startTime

const fps = (animation.frames / duration) * 1000

const dropRate = animation.droppedFrames / animation.frames

const data = {

name,

duration,

fps,

dropRate,

frames: animation.frames,

droppedFrames: animation.droppedFrames

}

this.performanceData.push(data)

this.animations.delete(name)

console.log(`动画性能 ${name}:`, data)

return data

}

// 获取性能报告

getPerformanceReport() {

return {

totalAnimations: this.performanceData.length,

averageFPS: this.performanceData.reduce((sum, data) => sum + data.fps, 0) / this.performanceData.length,

averageDropRate: this.performanceData.reduce((sum, data) => sum + data.dropRate, 0) / this.performanceData.length,

animations: this.performanceData

}

}

}

const animationMonitor = new AnimationMonitor()

export default animationMonitor12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879工具和调试 ​性能分析工具 ​自定义性能分析器 ​javascript// utils/profiler.js

class Profiler {

constructor() {

this.profiles = new Map()

this.isEnabled = true

}

// 开始性能分析

start(name) {

if (!this.isEnabled) return

this.profiles.set(name, {

startTime: performance.now(),

startMemory: this.getMemoryUsage(),

marks: []

})

}

// 添加标记点

mark(profileName, markName) {

if (!this.isEnabled) return

const profile = this.profiles.get(profileName)

if (profile) {

profile.marks.push({

name: markName,

time: performance.now() - profile.startTime,

memory: this.getMemoryUsage()

})

}

}

// 结束性能分析

end(name) {

if (!this.isEnabled) return

const profile = this.profiles.get(name)

if (!profile) return

const endTime = performance.now()

const endMemory = this.getMemoryUsage()

const result = {

name,

duration: endTime - profile.startTime,

memoryDelta: endMemory - profile.startMemory,

marks: profile.marks,

timestamp: new Date().toISOString()

}

this.profiles.delete(name)

this.logResult(result)

return result

}

// 获取内存使用情况

getMemoryUsage() {

if (wx.getPerformance && wx.getPerformance().memory) {

return wx.getPerformance().memory.usedJSHeapSize

}

return 0

}

// 记录结果

logResult(result) {

console.group(`性能分析: ${result.name}`)

console.log(`总耗时: ${result.duration.toFixed(2)}ms`)

console.log(`内存变化: ${(result.memoryDelta / 1024 / 1024).toFixed(2)}MB`)

if (result.marks.length > 0) {

console.log('标记点:')

result.marks.forEach(mark => {

console.log(` ${mark.name}: ${mark.time.toFixed(2)}ms`)

})

}

console.groupEnd()

}

// 启用/禁用分析器

setEnabled(enabled) {

this.isEnabled = enabled

}

}

const profiler = new Profiler()

export default profiler12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788使用示例 ​javascript// pages/product/detail.js

import profiler from '../../utils/profiler'

Page({

onLoad(options) {

profiler.start('page-load')

this.loadProductData(options.id)

},

async loadProductData(id) {

profiler.mark('page-load', 'start-api-request')

try {

const product = await this.fetchProduct(id)

profiler.mark('page-load', 'api-request-complete')

this.setData({ product })

profiler.mark('page-load', 'data-set-complete')

await this.loadRelatedProducts(product.categoryId)

profiler.mark('page-load', 'related-products-loaded')

} catch (error) {

console.error('加载产品数据失败:', error)

} finally {

profiler.end('page-load')

}

}

})123456789101112131415161718192021222324252627282930调试工具 ​性能监控面板 ​javascript// components/performance-panel/performance-panel.js

Component({

data: {

visible: false,

fps: 0,

memory: 0,

networkRequests: 0,

errors: []

},

lifetimes: {

attached() {

this.startMonitoring()

},

detached() {

this.stopMonitoring()

}

},

methods: {

// 开始监控

startMonitoring() {

// 监控 FPS

this.monitorFPS()

// 监控内存

this.monitorMemory()

// 监控网络请求

this.monitorNetwork()

// 监控错误

this.monitorErrors()

},

// 监控帧率

monitorFPS() {

let frames = 0

let lastTime = performance.now()

const countFPS = () => {

frames++

const currentTime = performance.now()

if (currentTime - lastTime >= 1000) {

this.setData({ fps: frames })

frames = 0

lastTime = currentTime

}

if (this.data.visible) {

requestAnimationFrame(countFPS)

}

}

requestAnimationFrame(countFPS)

},

// 监控内存

monitorMemory() {

const updateMemory = () => {

if (wx.getPerformance && wx.getPerformance().memory) {

const memory = wx.getPerformance().memory.usedJSHeapSize / 1024 / 1024

this.setData({ memory: memory.toFixed(2) })

}

if (this.data.visible) {

setTimeout(updateMemory, 1000)

}

}

updateMemory()

},

// 监控网络请求

monitorNetwork() {

const originalRequest = wx.request

let requestCount = 0

wx.request = (options) => {

requestCount++

this.setData({ networkRequests: requestCount })

return originalRequest.call(wx, options)

}

},

// 监控错误

monitorErrors() {

const originalError = console.error

const errors = []

console.error = (...args) => {

errors.push({

message: args.join(' '),

timestamp: new Date().toLocaleTimeString()

})

this.setData({ errors: errors.slice(-10) }) // 只保留最近10个错误

return originalError.apply(console, args)

}

},

// 切换面板显示

toggle() {

this.setData({ visible: !this.data.visible })

if (this.data.visible) {

this.startMonitoring()

}

},

// 清除错误日志

clearErrors() {

this.setData({ errors: [] })

}

}

})123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120xml

性能监控

×

FPS:

{{fps}}

内存:

{{memory}}MB

网络请求:

{{networkRequests}}

错误日志

清除

{{item.timestamp}}

{{item.message}}

性能

12345678910111213141516171819202122232425262728293031323334353637383940414243最佳实践总结 ​性能优化检查清单 ​启动性能 ​[ ] 代码包大小控制在 2MB 以内[ ] 使用分包加载非关键功能[ ] 首屏数据优先加载[ ] 实现骨架屏提升感知性能[ ] 关键资源预加载运行时性能 ​[ ] 减少 setData 调用频率[ ] 优化数据结构,避免深层嵌套[ ] 使用虚拟列表处理长列表[ ] 实现事件委托减少事件绑定[ ] 添加防抖节流优化高频事件内存管理 ​[ ] 及时清理定时器和事件监听[ ] 实现图片缓存和懒加载[ ] 使用分页加载控制数据量[ ] 定期清理过期缓存网络优化 ​[ ] 实现请求缓存和去重[ ] 合并相似请求减少网络开销[ ] 关键资源预加载[ ] 智能预加载基于用户行为样式和动画 ​[ ] 使用 transform 和 opacity 实现动画[ ] 避免复杂 CSS 选择器[ ] 启用硬件加速[ ] 监控动画性能性能监控指标 ​关键指标 ​首屏时间 < 1.5s页面切换时间 < 300ms滚动帧率 > 50fps内存使用 < 100MB网络请求成功率 > 99%监控实现 ​javascript// utils/performance-metrics.js

class PerformanceMetrics {

constructor() {

this.metrics = {

firstScreenTime: 0,

pageTransitionTime: 0,

scrollFPS: 0,

memoryUsage: 0,

networkSuccessRate: 0

}

}

// 记录首屏时间

recordFirstScreenTime(time) {

this.metrics.firstScreenTime = time

this.reportMetric('first_screen_time', time)

}

// 记录页面切换时间

recordPageTransitionTime(time) {

this.metrics.pageTransitionTime = time

this.reportMetric('page_transition_time', time)

}

// 上报性能指标

reportMetric(name, value) {

// 上报到性能监控平台

wx.request({

url: '/api/performance/report',

method: 'POST',

data: {

metric: name,

value: value,

timestamp: Date.now(),

userAgent: wx.getSystemInfoSync()

}

})

}

// 获取性能报告

getReport() {

return {

...this.metrics,

timestamp: new Date().toISOString(),

recommendations: this.getRecommendations()

}

}

// 获取优化建议

getRecommendations() {

const recommendations = []

if (this.metrics.firstScreenTime > 1500) {

recommendations.push('首屏时间过长,建议优化关键路径')

}

if (this.metrics.pageTransitionTime > 300) {

recommendations.push('页面切换时间过长,建议减少数据传输')

}

if (this.metrics.scrollFPS < 50) {

recommendations.push('滚动性能不佳,建议优化渲染逻辑')

}

if (this.metrics.memoryUsage > 100) {

recommendations.push('内存使用过高,建议检查内存泄漏')

}

return recommendations

}

}

const performanceMetrics = new PerformanceMetrics()

export default performanceMetrics1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374扩展资源 ​官方文档 ​小程序性能优化指南小程序分包加载小程序性能监控工具推荐 ​微信开发者工具:内置性能分析面板小程序助手:性能监控和分析Fundebug:错误监控和性能分析Sentry:应用性能监控学习资源 ​微信小程序性能优化最佳实践前端性能优化技术分享小程序开发者社区讨论通过本指南的学习和实践,你应该能够全面掌握小程序性能优化的各个方面,从启动性能到运行时性能,从内存管理到网络优化,系统性地提升小程序的用户体验。记住,性能优化是一个持续的过程,需要结合实际业务场景和用户反馈不断调整和改进。

相关文章

打造柔顺美丽的比熊犬——美容梳毛全攻略(掌握比熊犬美容的技巧与方法,让你的爱宠更加迷人动人)

bet体育365官网正规平台 08-30

什么老什么老的成语(什么老什么老的成语)(40个)

bet体育365官网正规平台 06-27

清炖羊排的制作步骤及独家调料分享

365体育ios 01-14

20个跑者从未做过的胯部灵活性训练

365体育ios 01-10