Cloud Development
Cloud Development is a serverless cloud computing solution designed specifically for mini program developers. It provides database, storage, cloud functions, and other backend capabilities without requiring traditional server management. This guide will help you understand and implement cloud development in your mini program projects.
Introduction to Cloud Development
What is Cloud Development?
Cloud Development (CloudBase) is a serverless backend-as-a-service (BaaS) solution that enables developers to build applications without managing server infrastructure. It integrates directly with mini program development environments, providing a seamless experience for building full-stack applications.
Key Features
- Database: NoSQL database for storing and querying data
- Storage: File storage system for images, videos, and other assets
- Cloud Functions: Serverless functions for backend logic
- Authentication: User authentication and management
- Static Hosting: Host static web content
- Real-time Data Updates: Subscribe to data changes in real-time
- Scheduled Tasks: Run tasks on a schedule
- Monitoring and Logging: Track usage and troubleshoot issues
Benefits
- No Server Management: Focus on application logic instead of infrastructure
- Auto Scaling: Automatically scales based on demand
- Pay-as-you-go: Only pay for what you use
- Integrated Development: Seamless integration with mini program IDEs
- Security: Built-in security features and best practices
- Reduced Development Time: Accelerate backend development
Getting Started
Setting Up Cloud Development
For WeChat Mini Programs
Enable Cloud Development:
- Open WeChat Developer Tools
- Create or open a mini program project
- Click on "Details" in the project settings
- Enable "Use Cloud Base"
- Select a cloud environment or create a new one
Initialize Cloud in Your Code:
javascript// app.js App({ onLaunch: function() { if (!wx.cloud) { console.error('Please use WeChat Developer Tools 1.02.1908232 or higher'); } else { wx.cloud.init({ env: 'your-env-id', traceUser: true, }); } } });
For Alipay Mini Programs
Enable Cloud Development:
- Open Alipay Developer Tools
- Create or open a mini program project
- Go to "Cloud Development" in the toolbar
- Follow the setup instructions
Initialize Cloud in Your Code:
javascript// app.js App({ onLaunch: function() { my.cloud.init({ env: 'your-env-id' }); } });
For Cross-Platform Frameworks
For frameworks like Taro or uni-app, you'll need to use platform-specific APIs or plugins:
Taro Example:
// app.js
import Taro from '@tarojs/taro';
Taro.cloud.init({
env: 'your-env-id',
traceUser: true
});
uni-app Example:
// main.js
// Use conditional compilation to handle different platforms
// #ifdef MP-WEIXIN
wx.cloud.init({
env: 'your-env-id',
traceUser: true
});
// #endif
// #ifdef MP-ALIPAY
my.cloud.init({
env: 'your-env-id'
});
// #endif
Creating a Cloud Environment
WeChat Cloud Environment:
- In WeChat Developer Tools, go to "Cloud Development"
- Click "Create Environment"
- Choose a name and region
- Select your resource plan
Alipay Cloud Environment:
- In Alipay Developer Tools, go to "Cloud Development"
- Click "Create Environment"
- Follow the setup instructions
Cloud Database
Cloud Database is a NoSQL database service that allows you to store and query data in JSON-like documents.
Basic Operations
Adding Data
// Add a single record
wx.cloud.database().collection('users').add({
data: {
name: 'John Doe',
age: 25,
city: 'Shanghai',
createTime: wx.cloud.database().serverDate()
}
}).then(res => {
console.log('Added document with ID:', res._id);
}).catch(err => {
console.error('Add failed:', err);
});
// Add multiple records (using cloud function)
wx.cloud.callFunction({
name: 'batchAdd',
data: {
collection: 'users',
data: [
{ name: 'Alice', age: 30, city: 'Beijing' },
{ name: 'Bob', age: 28, city: 'Guangzhou' }
]
}
}).then(res => {
console.log('Batch add successful:', res);
}).catch(err => {
console.error('Batch add failed:', err);
});
Querying Data
const db = wx.cloud.database();
// Get a single record by ID
db.collection('users').doc('record-id').get().then(res => {
console.log('Data:', res.data);
}).catch(err => {
console.error('Query failed:', err);
});
// Query with conditions
db.collection('users')
.where({
age: db.command.gt(20).and(db.command.lt(30))
})
.get()
.then(res => {
console.log('Query results:', res.data);
})
.catch(err => {
console.error('Query failed:', err);
});
// Complex queries
db.collection('users')
.where({
city: 'Shanghai',
age: db.command.gt(20)
})
.orderBy('age', 'desc')
.limit(10)
.get()
.then(res => {
console.log('Query results:', res.data);
});
Updating Data
const db = wx.cloud.database();
// Update a single record
db.collection('users').doc('record-id').update({
data: {
age: 26,
'address.city': 'Beijing'
}
}).then(res => {
console.log('Updated successfully:', res);
}).catch(err => {
console.error('Update failed:', err);
});
// Update multiple records (using cloud function)
wx.cloud.callFunction({
name: 'batchUpdate',
data: {
collection: 'users',
where: { city: 'Shanghai' },
data: { country: 'China' }
}
}).then(res => {
console.log('Batch update successful:', res);
});
Deleting Data
const db = wx.cloud.database();
// Delete a single record
db.collection('users').doc('record-id').remove().then(res => {
console.log('Removed successfully:', res);
}).catch(err => {
console.error('Remove failed:', err);
});
// Delete multiple records (using cloud function)
wx.cloud.callFunction({
name: 'batchDelete',
data: {
collection: 'users',
where: { city: 'Shanghai' }
}
}).then(res => {
console.log('Batch delete successful:', res);
});
Advanced Database Features
Transactions
For operations that require atomicity, you can use transactions (only available in cloud functions):
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
exports.main = async (event, context) => {
const { fromAccount, toAccount, amount } = event;
try {
return await db.runTransaction(async transaction => {
// Get current balances
const fromUser = await transaction.get(db.collection('accounts').doc(fromAccount));
const toUser = await transaction.get(db.collection('accounts').doc(toAccount));
// Check if enough balance
if (fromUser.data.balance < amount) {
throw new Error('Insufficient balance');
}
// Update balances
await transaction.update(db.collection('accounts').doc(fromAccount), {
data: {
balance: db.command.inc(-amount)
}
});
await transaction.update(db.collection('accounts').doc(toAccount), {
data: {
balance: db.command.inc(amount)
}
});
return { success: true };
});
} catch (e) {
return { success: false, error: e.message };
}
};
Aggregation
For complex data analysis, you can use aggregation pipelines:
const db = wx.cloud.database();
const $ = db.command.aggregate;
db.collection('orders')
.aggregate()
.match({
status: 'completed',
createTime: $.gte(new Date('2023-01-01'))
})
.group({
_id: '$productId',
totalSales: $.sum('$amount'),
count: $.sum(1)
})
.sort({
totalSales: -1
})
.limit(10)
.end()
.then(res => {
console.log('Top 10 products:', res.list);
});
Real-time Data Updates
Subscribe to database changes in real-time:
const db = wx.cloud.database();
const watcher = db.collection('messages')
.where({ roomId: 'room1' })
.watch({
onChange: function(snapshot) {
console.log('Data changed:', snapshot.docChanges);
console.log('Current data:', snapshot.docs);
// Update UI with new data
},
onError: function(err) {
console.error('Watch error:', err);
}
});
// Stop watching when no longer needed
// watcher.close();
Cloud Storage
Cloud Storage allows you to store and retrieve files such as images, videos, and documents.
Basic Operations
Uploading Files
// Upload from local file path
wx.chooseImage({
count: 1,
success: res => {
const filePath = res.tempFilePaths[0];
const cloudPath = `images/${Date.now()}-${Math.floor(Math.random() * 1000)}${filePath.match(/\.[^.]+?$/)[0]}`;
wx.cloud.uploadFile({
cloudPath,
filePath,
success: res => {
console.log('Upload successful, file ID:', res.fileID);
// Save fileID to database if needed
wx.cloud.database().collection('images').add({
data: {
fileID: res.fileID,
uploadTime: wx.cloud.database().serverDate()
}
});
},
fail: err => {
console.error('Upload failed:', err);
}
});
}
});
Downloading Files
wx.cloud.downloadFile({
fileID: 'cloud://your-env-id.xxxx-xxxx/images/example.jpg',
success: res => {
// tempFilePath can be used as the src attribute of an image tag
const tempFilePath = res.tempFilePath;
console.log('Download successful, temp file path:', tempFilePath);
// Display the image
this.setData({
imageUrl: tempFilePath
});
},
fail: err => {
console.error('Download failed:', err);
}
});
Getting File URLs
wx.cloud.getTempFileURL({
fileList: ['cloud://your-env-id.xxxx-xxxx/images/example.jpg'],
success: res => {
console.log('File URLs:', res.fileList);
// Use the URLs for image display, sharing, etc.
const url = res.fileList[0].tempFileURL;
this.setData({
imageUrl: url
});
},
fail: err => {
console.error('Get URL failed:', err);
}
});
Deleting Files
wx.cloud.deleteFile({
fileList: ['cloud://your-env-id.xxxx-xxxx/images/example.jpg'],
success: res => {
console.log('Delete result:', res.fileList);
},
fail: err => {
console.error('Delete failed:', err);
}
});
Advanced Storage Features
Batch Operations
// Batch get URLs
wx.cloud.getTempFileURL({
fileList: [
'cloud://your-env-id.xxxx-xxxx/images/example1.jpg',
'cloud://your-env-id.xxxx-xxxx/images/example2.jpg',
'cloud://your-env-id.xxxx-xxxx/images/example3.jpg'
],
success: res => {
const urls = res.fileList.map(item => item.tempFileURL);
console.log('URLs:', urls);
}
});
// Batch delete
wx.cloud.deleteFile({
fileList: [
'cloud://your-env-id.xxxx-xxxx/images/example1.jpg',
'cloud://your-env-id.xxxx-xxxx/images/example2.jpg'
],
success: res => {
console.log('Batch delete results:', res.fileList);
}
});
File Access Control
You can control file access by setting permissions in the cloud console or programmatically:
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
try {
const result = await cloud.openapi.cloudbase.addPermission({
env: 'your-env-id',
resource: 'storage.object',
action: 'storage.getObject',
condition: {
'resource.path': ['/images/public/*']
},
principal: { 'service': ['cloudbase.anonymous'] }
});
return result;
} catch (err) {
return err;
}
};
Cloud Functions
Cloud Functions allow you to run backend code in a serverless environment, triggered by events or direct calls.
Creating and Deploying Cloud Functions
Create a Cloud Function:
- In WeChat Developer Tools, go to "Cloud Development" > "Cloud Functions"
- Click "Add Cloud Function"
- Enter a name (e.g., "getUserInfo")
- A template function will be created
Write Function Code:
javascript// cloud/getUserInfo/index.js const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); exports.main = async (event, context) => { const { OPENID } = cloud.getWXContext(); try { // Get user from database const userResult = await db.collection('users').where({ _openid: OPENID }).get(); // Return user data or create new user if not found if (userResult.data.length > 0) { return { success: true, data: userResult.data[0] }; } else { // Create new user const newUser = { _openid: OPENID, createdAt: db.serverDate(), points: 0, nickname: event.nickname || 'New User' }; const addResult = await db.collection('users').add({ data: newUser }); return { success: true, data: { ...newUser, _id: addResult._id }, isNew: true }; } } catch (err) { return { success: false, error: err.message }; } };
Deploy the Function:
- Click "Upload and Deploy" in the cloud function editor
- Wait for the deployment to complete
Calling Cloud Functions
From Mini Program
// Call without parameters
wx.cloud.callFunction({
name: 'getUserInfo',
success: res => {
console.log('User info:', res.result);
if (res.result.success) {
this.setData({
userInfo: res.result.data,
isNewUser: res.result.isNew || false
});
}
},
fail: err => {
console.error('Call function failed:', err);
}
});
// Call with parameters
wx.cloud.callFunction({
name: 'updateUserProfile',
data: {
nickname: 'John Doe',
avatar: 'https://example.com/avatar.jpg',
gender: 1
}
}).then(res => {
console.log('Profile updated:', res.result);
}).catch(err => {
console.error('Update failed:', err);
});
From Another Cloud Function
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
try {
// Call another cloud function
const result = await cloud.callFunction({
name: 'getUserInfo',
data: {
nickname: event.nickname
}
});
return result.result;
} catch (err) {
return {
success: false,
error: err.message
};
}
};
Triggers for Cloud Functions
Cloud functions can be triggered by various events:
HTTP Triggers
Create an HTTP endpoint for your function:
// cloud/api/index.js
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
// Parse HTTP method and path
const { method, path } = event;
if (method === 'GET' && path === '/users') {
// Handle GET /users
const db = cloud.database();
const users = await db.collection('users').limit(10).get();
return {
statusCode: 200,
body: JSON.stringify(users.data)
};
} else if (method === 'POST' && path === '/users') {
// Handle POST /users
const db = cloud.database();
const { name, email } = event.body ? JSON.parse(event.body) : {};
if (!name || !email) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Name and email are required' })
};
}
const result = await db.collection('users').add({
data: { name, email, createdAt: db.serverDate() }
});
return {
statusCode: 201,
body: JSON.stringify({ id: result._id })
};
} else {
// Handle 404
return {
statusCode: 404,
body: JSON.stringify({ error: 'Not found' })
};
}
};
Configure the HTTP trigger in the cloud console or function configuration.
Timer Triggers
Schedule functions to run at specific intervals:
// cloud/dailyTasks/index.js
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
exports.main = async (event, context) => {
try {
// Reset daily counters
await db.collection('statistics').where({
type: 'daily'
}).update({
data: {
count: 0,
lastReset: db.serverDate()
}
});
// Generate daily reports
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const startOfDay = new Date(yesterday);
startOfDay.setHours(0, 0, 0, 0);
const endOfDay = new Date(yesterday);
endOfDay.setHours(23, 59, 59, 999);
const orders = await db.collection('orders')
.where({
createTime: db.command.gte(startOfDay).and(db.command.lte(endOfDay))
})
.get();
// Calculate statistics
const totalSales = orders.data.reduce((sum, order) => sum + order.amount, 0);
const orderCount = orders.data.length;
// Save report
await db.collection('reports').add({
data: {
date: yesterday,
totalSales,
orderCount,
createdAt: db.serverDate()
}
});
return {
success: true,
message: 'Daily tasks completed successfully'
};
} catch (err) {
return {
success: false,
error: err.message
};
}
};
Configure the timer trigger in the cloud console (e.g., "0 0 * * *" for daily at midnight).
Database Triggers
React to changes in the database:
// cloud/onOrderCreate/index.js
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
exports.main = async (event, context) => {
const { dataList } = event;
for (const { doc, docId, updateFields } of dataList) {
try {
// New order created
if (doc && doc.status === 'new') {
// Send notification to admin
await cloud.openapi.subscribeMessage.send({
touser: 'admin-open-id',
templateId: 'template-id',
data: {
thing1: {
value: `New order: ${docId}`
},
amount3: {
value: doc.amount
},
time4: {
value: new Date().toLocaleString()
}
}
});
// Update inventory
for (const item of doc.items) {
await db.collection('products').doc(item.productId).update({
data: {
stock: db.command.inc(-item.quantity)
}
});
}
// Update order status
await db.collection('orders').doc(docId).update({
data: {
status: 'processing',
processingTime: db.serverDate()
}
});
}
} catch (err) {
console.error(`Error processing order ${docId}:`, err);
}
}
return { success: true };
};
Configure the database trigger in the cloud console, specifying the collection to watch.
Authentication and Security
User Authentication
WeChat Authentication
WeChat mini programs automatically authenticate users with their WeChat accounts:
// Get user OpenID
wx.cloud.callFunction({
name: 'login',
success: res => {
const openid = res.result.openid;
console.log('User OpenID:', openid);
// Store openid for future use
this.setData({ openid });
},
fail: err => {
console.error('Login failed:', err);
}
});
// Cloud function for login
// cloud/login/index.js
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext();
return {
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
};
};
Custom Authentication
For more complex authentication needs:
// Cloud function for custom authentication
// cloud/customLogin/index.js
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
const crypto = require('crypto');
exports.main = async (event, context) => {
const { username, password } = event;
const wxContext = cloud.getWXContext();
try {
// Find user by username
const userResult = await db.collection('users').where({
username: username
}).get();
if (userResult.data.length === 0) {
return {
success: false,
error: 'User not found'
};
}
const user = userResult.data[0];
// Check password (using hash comparison)
const hashedPassword = crypto
.createHash('sha256')
.update(password + user.salt)
.digest('hex');
if (hashedPassword !== user.password) {
return {
success: false,
error: 'Invalid password'
};
}
// Update user with WeChat OpenID if not already linked
if (!user.openid) {
await db.collection('users').doc(user._id).update({
data: {
openid: wxContext.OPENID,
lastLogin: db.serverDate()
}
});
} else {
await db.collection('users').doc(user._id).update({
data: {
lastLogin: db.serverDate()
}
});
}
// Generate session token
const token = crypto.randomBytes(32).toString('hex');
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 7); // Token valid for 7 days
await db.collection('sessions').add({
data: {
token,
userId: user._id,
openid: wxContext.OPENID,
createdAt: db.serverDate(),
expiresAt
}
});
return {
success: true,
token,
expiresAt,
user: {
_id: user._id,
username: user.username,
nickname: user.nickname,
role: user.role
}
};
} catch (err) {
return {
success: false,
error: err.message
};
}
};
Security Rules
Cloud Database and Storage support security rules to control access:
Database Security Rules
In the cloud console, you can set collection-level security rules:
{
"read": true,
"write": "auth.openid != null",
"create": "auth.openid != null",
"update": "auth.openid != null && auth.openid == doc._openid",
"delete": "auth.openid != null && auth.openid == doc._openid"
}
For more complex rules:
{
"read": true,
"write": "auth.openid != null",
"create": "auth.openid != null && doc._openid == auth.openid",
"update": "auth.openid != null && ((doc._openid == auth.openid) || (get('database.collection.roles').where({_openid: auth.openid, role: 'admin'}).size() > 0))",
"delete": "auth.openid != null && get('database.collection.roles').where({_openid: auth.openid, role: 'admin'}).size() > 0"
}
Storage Security Rules
Similarly, you can set storage security rules:
{
"read": true,
"write": "auth.openid != null"
}
For path-specific rules:
{
"read": true,
"write": {
"condition": "auth.openid != null",
"path_regex": "^/public/.*"
}
}
Advanced Topics
Serverless Architecture Patterns
Microservices with Cloud Functions
Organize your backend as microservices:
cloud/
├── auth/
│ ├── login.js
│ ├── register.js
│ └── resetPassword.js
├── users/
│ ├── getProfile.js
│ ├── updateProfile.js
│ └── deleteAccount.js
├── products/
│ ├── listProducts.js
│ ├── getProductDetails.js
│ └── searchProducts.js
└── orders/
├── createOrder.js
├── getOrderStatus.js
└── cancelOrder.js
Event-Driven Architecture
Use database triggers and message queues for event-driven flows:
// Order processing workflow
// 1. Create order (client-side)
// 2. Trigger: onOrderCreate -> validate and process payment
// 3. Trigger: onPaymentComplete -> update inventory and notify shipping
// 4. Trigger: onShipmentUpdate -> notify customer
Performance Optimization
Database Indexing
Create indexes for frequently queried fields:
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
exports.main = async (event, context) => {
try {
await db.collection('orders').createIndex({
keys: {
userId: 1,
status: 1,
createTime: -1
},
name: 'userId_status_createTime'
});
return { success: true };
} catch (err) {
return { success: false, error: err.message };
}
};
Caching Strategies
Implement caching for frequently accessed data:
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
const db = cloud.database();
// Simple in-memory cache (note: each function instance has its own memory)
const cache = {};
const CACHE_TTL = 60 * 1000; // 1 minute
exports.main = async (event, context) => {
const { category } = event;
const cacheKey = `products_${category}`;
// Check cache
if (cache[cacheKey] && cache[cacheKey].timestamp > Date.now() - CACHE_TTL) {
console.log('Cache hit for', cacheKey);
return {
source: 'cache',
data: cache[cacheKey].data
};
}
// Cache miss, fetch from database
try {
const query = category ? { category } : {};
const result = await db.collection('products')
.where(query)
.limit(20)
.get();
// Update cache
cache[cacheKey] = {
timestamp: Date.now(),
data: result.data
};
return {
source: 'database',
data: result.data
};
} catch (err) {
return {
success: false,
error: err.message
};
}
};
Monitoring and Debugging
Logging
Implement structured logging:
// In a cloud function
const cloud = require('wx-server-sdk');
cloud.init();
function log(level, message, data = {}) {
const timestamp = new Date().toISOString();
console.log(JSON.stringify({
level,
timestamp,
message,
...data
}));
}
exports.main = async (event, context) => {
try {
log('info', 'Function started', { event });
// Function logic here
const result = await someOperation();
log('info', 'Function completed', { result });
return result;
} catch (err) {
log('error', 'Function failed', { error: err.message, stack: err.stack });
return { success: false, error: err.message };
}
};
Debugging Cloud Functions
Local Testing:
- Use the cloud function local debugging feature in developer tools
- Set breakpoints and inspect variables
- View console logs in real-time
Remote Debugging:
- Add detailed logging to your functions
- Use try-catch blocks to handle errors gracefully
- Return detailed error information for debugging
Monitoring:
- Use the cloud console to monitor function executions
- Track metrics like execution count, duration, and errors
- Set up alerts for abnormal conditions
Best Practices
Security Best Practices
- Always validate user input in both client and server code
- Use security rules to control access to database and storage
- Implement proper authentication for all sensitive operations
- Store sensitive data only in cloud functions or secure storage
- Use HTTPS for all external API calls
- Implement rate limiting to prevent abuse
- Regularly audit your security rules and permissions
Performance Best Practices
- Use indexes for frequently queried fields
- Limit query results to reduce data transfer
- Implement caching for frequently accessed data
- Optimize cloud function cold starts by keeping functions focused
- Use batch operations when working with multiple records
- Minimize dependencies in cloud functions
- Use appropriate database structures for your data access patterns
Cost Optimization
- Monitor usage to understand your consumption patterns
- Optimize database queries to reduce read/write operations
- Use efficient storage patterns to minimize storage costs
- Implement TTL (Time-To-Live) for temporary data
- Use caching to reduce database operations
- Optimize cloud function execution time to reduce compute costs
- Consider using scheduled batch processing for non-time-sensitive operations
Conclusion
Cloud Development provides a powerful, serverless backend solution for mini program developers. By leveraging cloud databases, storage, and functions, you can build sophisticated applications without managing traditional server infrastructure.
As you develop with Cloud Development, remember to follow best practices for security, performance, and cost optimization. Regularly monitor your application's usage and performance to ensure it meets your users' needs efficiently.
For more information and advanced topics, refer to the official documentation for your platform's cloud development service: