Mini Program Too Slow? Here's How I Optimized It

Last year our company's mini program got brutally roasted by users in app store reviews: "Laggy as hell", "Takes forever to load", "Worse than the web version"...
As the main developer, I was under tremendous pressure. Spent 3 months specifically on performance optimization and finally managed to pull our user rating from 2.1 to 4.3 stars.
Today I'm sharing the performance pitfalls I stepped on and the experience I gained from mini program optimization, hoping to help everyone avoid some detours.
Performance Pitfalls I Stepped On
First Pitfall: Code Package Too Large, Startup Painfully Slow
When I first started making mini programs, I crammed all functionality into the main package, resulting in a 1.8M code package. Users had to wait 5-6 seconds to open the mini program - terrible experience.
Later I learned about WeChat's subpackage mechanism. I split non-core features into subpackages, keeping only homepage and login-related code in the main package, compressing it to 500K. Startup time dropped from 6 seconds to 2 seconds.
Specific approach:
- Split mall, personal center, settings modules into independent subpackages
- Put image resources on CDN instead of bundling them in code
- Regularly clean up unused components and style files
Second Pitfall: Improper setData Usage, Page Stuttering
I used to call setData every time data changed, resulting in frequent page stuttering. Especially on list pages, you could clearly feel frame drops when scrolling.
Later I learned to batch update data, merging multiple setData calls into one. Also only update changed fields, don't pass entire objects.
Hard-learned lesson:
// Wrong approach - frequent setData calls
this.setData({ loading: true });
this.setData({ userInfo: res.data });
this.setData({ loading: false });
// Correct approach - batch updates
this.setData({
loading: false,
userInfo: res.data,
});
Third Pitfall: No Network Request Caching, Repeated Loading
Our mini program had a config API that was requested every time you entered a page. Later I realized this config barely changed and could be completely cached.
Now I cache infrequently changing data locally with reasonable expiration times. User experience improved significantly, especially when network is poor.
How I Optimize Now
Startup Optimization: Let Users Open Your Mini Program Instantly
Subpackage Strategy:
- Main package only contains homepage, login, basic components
- Split subpackages by business modules like mall, personal center, activity pages
- Keep each subpackage under 500K
Preload Optimization:
- Configure preloadRule in app.json to preload potentially accessed subpackages when users browse homepage
- Guide users to "Add to My Mini Programs" to improve cache hit rate
Code Optimization:
- Enable lazy loading:
"lazyCodeLoading": "requiredComponents"
- Compress images, use webp when possible
- Remove console.log and unused code
Rendering Optimization: Say Goodbye to Stuttering and White Screens
setData Optimization:
// My current approach
const updateData = {};
if (needUpdateUser) updateData.userInfo = newUserInfo;
if (needUpdateList) updateData["list[0].status"] = "active";
if (Object.keys(updateData).length > 0) {
this.setData(updateData);
}
Conditional Rendering Optimization:
- Use wx:if for initially hidden content to avoid meaningless rendering
- Use hidden for frequently toggled content to avoid repeated creation/destruction
- Use virtual scrolling for long lists - I use the recycle-view component
Skeleton Screens: Users used to think the program crashed when seeing white screens. Now I add skeleton screens to all pages that need to load data - much better user experience.
Network Optimization: Reduce Waiting Time
Caching Strategy:
// My caching utility function
const cache = {
get(key) {
const data = wx.getStorageSync(key);
if (data && data.expireTime > Date.now()) {
return data.value;
}
return null;
},
set(key, value, expireMinutes = 30) {
wx.setStorageSync(key, {
value,
expireTime: Date.now() + expireMinutes * 60 * 1000,
});
},
};
Request Optimization:
- Merge APIs: Return data needed by one page in a single API call when possible
- Pre-requests: Start requesting next page's data before page navigation
- Failure retry: Auto-retry when network is poor, don't make users manually refresh
User Experience Optimization
Loading States Must Be Clear
I used to forget adding loading states - when users clicked buttons with no response, they'd think the program was broken.
My habits now:
- All async operations must have loading states
- Show loading immediately after button clicks to prevent duplicate clicks
- Network request failures must have clear error messages
Interaction Feedback Must Be Timely
Vibration Feedback: Add vibration feedback for key operations like delete confirmation, payment success. Code is simple:
wx.vibrateShort({ type: "light" });
Toast Messages: Give users clear feedback whether operations succeed or fail - don't make users guess.
Empty State Design
I used to just show blank pages when lists were empty - terrible user experience. Now I design dedicated empty state pages:
- No search results: Show "Try different keywords"
- Network error: Show "Network hiccupped, click to retry"
- Empty list: Show "No data yet, go check out something else"
Some Practical Optimization Tips
Image Optimization
Lazy Loading:
// Use intersection observer for image lazy loading
const observer = wx.createIntersectionObserver();
observer.relativeToViewport().observe(".lazy-image", (res) => {
if (res.intersectionRatio > 0) {
// Start loading image
}
});
Compression and Format:
- Use webp when possible - much smaller file size
- Compress images to appropriate size, don't use originals
- Use icon fonts or SVG for small icons
Memory Management
Timely Cleanup:
// Clean up timers and listeners when page unloads
onUnload() {
if (this.timer) {
clearInterval(this.timer)
}
if (this.observer) {
this.observer.disconnect()
}
}
Compatibility Handling
Device Adaptation:
- Degrade for low-end devices, reduce animations and effects
- Use wx.getSystemInfo to get device info for targeted optimization
- Adapt for notch screens using safe-area related styles
Performance Monitoring
Now I add some performance monitoring to mini programs:
// Startup time monitoring
App({
onLaunch() {
this.launchTime = Date.now();
},
onShow() {
const showTime = Date.now();
console.log("Startup time:", showTime - this.launchTime);
// Report to backend
},
});
I also monitor page load times, API response times and other key metrics to discover performance issues promptly.
Final Thoughts
Mini program performance optimization is an ongoing process, not a one-time job. My habits now:
- Consider performance during development: Don't wait for problems to optimize
- Regular checks: Test performance before every version release
- Pay attention to user feedback: User complaints often point to real problems
- Data-driven: Let data speak, don't optimize based on feelings
After this optimization, our mini program's user retention improved by 30%, and user rating rose from 2.1 to 4.3 stars. Though the process was painful, the results were worth it.
Hope my experience helps everyone. If you've encountered similar problems, welcome to exchange and share!
Follow WeChat Official Account

Scan to get:
- • Latest tech articles
- • Exclusive dev insights
- • Useful tools & resources
💬 评论讨论
欢迎对《Mini Program Too Slow? Here's How I Optimized It》发表评论,分享你的想法和经验