Best Practices
This guide outlines best practices for mini program development to help you create high-quality, maintainable, and performant applications.
Code Organization
Project Structure
Organize your project with a clear and logical structure:
project/
├── app.js # App instance
├── app.json # Global configuration
├── app.wxss # Global styles
├── pages/ # Pages directory
│ └── ...
├── components/ # Reusable components
│ └── ...
├── services/ # API and business logic
│ └── ...
├── utils/ # Utility functions
│ └── ...
├── assets/ # Static assets
│ └── ...
└── config/ # Configuration files
└── ...
Naming Conventions
- Use kebab-case for file and directory names:
user-profile.js
- Use camelCase for variable and function names:
getUserInfo()
- Use PascalCase for component names:
<UserProfile />
- Use UPPER_SNAKE_CASE for constants:
MAX_RETRY_COUNT
Code Modularization
Break down your code into small, focused modules:
- Each component should have a single responsibility
- Extract reusable logic into utility functions
- Group related functionality into services
Performance Optimization
Minimize Initial Load Time
- Use subpackages for large applications
- Lazy load non-critical resources
- Optimize image sizes (use appropriate formats and compression)
- Remove unused code and dependencies
Reduce Render Time
- Minimize the use of
setData()
- Batch updates with a single
setData()
call - Only update changed data, not the entire object
- Use
wx:if
instead ofhidden
for elements that are frequently toggled
javascript
// Bad practice
this.setData({
userInfo: userInfo,
products: products,
settings: settings
})
// Good practice
this.setData({
'userInfo.name': userInfo.name,
'products[0].price': products[0].price
})
Memory Management
- Release resources when they're no longer needed
- Unsubscribe from events in
onUnload()
- Close connections (WebSocket, Bluetooth, etc.) when done
- Avoid memory leaks by cleaning up references
javascript
Page({
onLoad() {
this.audioContext = wx.createInnerAudioContext()
wx.onAccelerometerChange(this.handleAccelerometerChange)
},
onUnload() {
// Clean up resources
this.audioContext.destroy()
wx.offAccelerometerChange(this.handleAccelerometerChange)
}
})
UI/UX Design
Responsive Design
- Use relative units (rpx) for layout
- Test on different screen sizes
- Implement adaptive layouts
- Consider device orientation changes
Loading States
- Show loading indicators for asynchronous operations
- Implement skeleton screens for content-heavy pages
- Provide feedback for user actions
- Handle empty states gracefully
javascript
Page({
data: {
isLoading: true,
products: [],
isEmpty: false
},
onLoad() {
this.fetchProducts()
},
fetchProducts() {
wx.showLoading({ title: 'Loading...' })
api.getProducts()
.then(products => {
this.setData({
products,
isEmpty: products.length === 0,
isLoading: false
})
})
.catch(error => {
this.setData({
isLoading: false,
isEmpty: true
})
})
.finally(() => {
wx.hideLoading()
})
}
})
Error Handling
- Display user-friendly error messages
- Provide recovery options when possible
- Log errors for debugging
- Implement fallback content
Data Management
State Management
- Keep state organized and predictable
- Consider using a state management library for complex apps
- Minimize global state
- Pass data down through properties
API Communication
- Create a centralized API service
- Implement request/response interceptors
- Handle token refresh automatically
- Cache responses when appropriate
javascript
// api.js
const request = (url, options = {}) => {
const token = getToken()
return new Promise((resolve, reject) => {
wx.request({
url: `${BASE_URL}${url}`,
...options,
header: {
'Authorization': token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
...options.header
},
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data)
} else if (res.statusCode === 401) {
// Handle unauthorized (token expired)
refreshToken()
.then(() => request(url, options))
.then(resolve)
.catch(reject)
} else {
reject(res)
}
},
fail: reject
})
})
}
Data Persistence
- Use storage appropriately (don't store sensitive data)
- Clear outdated cache
- Handle storage errors
- Implement data migration for app updates
Security
Data Protection
- Never store sensitive data in client-side storage
- Encrypt sensitive data when necessary
- Use HTTPS for all network requests
- Implement proper authentication and authorization
Input Validation
- Validate all user inputs
- Sanitize data before displaying it
- Prevent injection attacks
- Use content security policies
Secure Communication
- Implement proper SSL certificate validation
- Use token-based authentication
- Implement proper session management
- Protect against CSRF attacks
Testing
Unit Testing
- Test individual functions and components
- Mock dependencies
- Focus on edge cases
- Maintain high test coverage
Integration Testing
- Test component interactions
- Verify API integrations
- Test navigation flows
- Validate form submissions
Manual Testing
- Test on actual devices
- Verify performance on low-end devices
- Test with poor network conditions
- Validate accessibility features
Deployment
Version Control
- Use semantic versioning
- Maintain a changelog
- Tag releases
- Use feature branches for development
Continuous Integration
- Automate builds
- Run tests automatically
- Perform static code analysis
- Check for security vulnerabilities
Release Management
- Implement staged rollouts
- Monitor for errors after deployment
- Have a rollback strategy
- Collect user feedback
Documentation
Code Documentation
- Document complex logic
- Add JSDoc comments to functions
- Explain non-obvious decisions
- Keep documentation up-to-date
javascript
/**
* Calculates the discount price based on user level and product category
* @param {Object} product - The product object
* @param {string} product.category - Product category
* @param {number} product.price - Original price
* @param {Object} user - The user object
* @param {number} user.level - User level (1-5)
* @returns {number} The calculated discount price
*/
function calculateDiscountPrice(product, user) {
// Implementation
}
Project Documentation
- Maintain a README file
- Document setup procedures
- List dependencies
- Provide troubleshooting guides
Cross-Platform Development
Code Compatibility
- Use conditional compilation for platform-specific code
- Create platform abstraction layers
- Test on all target platforms
- Follow each platform's design guidelines
Framework Selection
- Choose frameworks based on project requirements
- Consider long-term maintenance
- Evaluate community support
- Assess performance implications
Accessibility
Inclusive Design
- Provide text alternatives for images
- Ensure sufficient color contrast
- Support screen readers
- Make touch targets large enough
Internationalization
- Separate text from code
- Support multiple languages
- Consider cultural differences
- Handle different text lengths
Monitoring and Analytics
Error Tracking
- Implement error logging
- Set up alerts for critical errors
- Track error rates
- Prioritize fixes based on impact
Performance Monitoring
- Track key performance metrics
- Monitor API response times
- Identify bottlenecks
- Set performance budgets
User Analytics
- Track user behavior
- Analyze navigation patterns
- Measure feature usage
- Identify drop-off points
Conclusion
Following these best practices will help you create mini programs that are performant, maintainable, and provide a great user experience. Remember that best practices evolve over time, so stay updated with the latest developments in the mini program ecosystem.
Next Steps
- Performance Optimization for more detailed performance tips
- Debugging Tips for troubleshooting techniques
- Deployment for publishing your mini program