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

mini programperformance optimizationuser experiencemobile development
Lafu Code
Lafu Code
-- views

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:

  1. Consider performance during development: Don't wait for problems to optimize
  2. Regular checks: Test performance before every version release
  3. Pay attention to user feedback: User complaints often point to real problems
  4. 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

WeChat Official Account QR Code

Scan to get:

  • • Latest tech articles
  • • Exclusive dev insights
  • • Useful tools & resources

💬 评论讨论

欢迎对《Mini Program Too Slow? Here's How I Optimized It》发表评论,分享你的想法和经验