适用人群:想开发并发布微信小程序的开发者
难度:中等
预计阅读时间:30分钟
一、小程序概述
1.1 什么是微信小程序
微信小程序是运行在微信内部的轻量级应用,无需下载安装,扫码或搜索即可使用。截至2025年,微信小程序日活超过6亿,覆盖电商、工具、社交、服务等几乎所有领域。
| 对比 | 小程序 | 原生APP | H5网页 |
|---|---|---|---|
| 安装 | 不需要 | 需要下载 | 不需要 |
| 入口 | 微信内 | 桌面图标 | 浏览器 |
| 性能 | 中高 | 最高 | 中 |
| 开发成本 | 低 | 高 | 低 |
| 推送能力 | 有限 | 完整 | 无 |
| 支付 | 微信支付 | 多种 | 需对接 |
| 用户获取 | 搜索/扫码/分享 | 应用商店 | 链接 |
| 包大小限制 | 2MB(分包20MB) | 无限制 | 无限制 |
| 适合场景 | 轻量服务/工具/电商 | 复杂应用 | 信息展示 |
1.2 技术方案选择
| 方案 | 语言 | 特点 | 适合 |
|---|---|---|---|
| <strong>原生开发</strong> | WXML+WXSS+JS | 性能最好,能力完整 | 功能复杂/性能要求高 |
| <strong>uni-app</strong> | Vue.js | 一套代码多端(小程序/H5/APP) | 需要多端发布 |
| <strong>Taro</strong> | React | React语法写小程序 | React团队 |
| <strong>mpvue</strong> | Vue.js | Vue语法(已停止维护) | 不推荐新项目 |
| <strong>WePY</strong> | 类Vue | 早期框架(已过时) | 不推荐 |
二、注册与准备
2.1 注册小程序账号
第1步:访问微信公众平台
├── 网址:https://mp.weixin.qq.com
├── 点击「立即注册」
└── 选择「小程序」
第2步:填写注册信息
├── 邮箱(未注册过公众平台的邮箱)
├── 密码
├── 验证邮箱
└── 选择主体类型
第3步:选择主体类型
├── 个人
│ ├── 需要:身份证信息
│ ├── 限制:不能微信支付、不能使用某些API
│ ├── 适合:个人工具、学习项目
│ └── 认证费:不可认证
│
├── 企业
│ ├── 需要:营业执照、对公账户
│ ├── 能力:完整功能(支付、直播等)
│ ├── 认证费:300元/年
│ └── 推荐:商业项目必选
│
├── 个体工商户
│ ├── 需要:营业执照
│ ├── 能力:支持微信支付
│ ├── 认证费:300元/年
│ └── 适合:小型商业项目
│
├── 政府
│ ├── 需要:组织机构代码证
│ └── 认证费:免费
│
└── 其他组织
├── 需要:组织机构代码证
└── 认证费:300元/年
第4步:完善信息
├── 登录小程序后台
├── 设置 → 基本设置
│ ├── 小程序名称(唯一,不可与已有重复)
│ ├── 小程序头像
│ ├── 小程序简介
│ └── 服务类目(选择对应行业)
└── 开发 → 开发管理 → 开发设置
├── AppID(小程序唯一标识,重要!)
├── AppSecret(密钥,不要泄露)
└── 服务器域名(合法域名白名单)
2.2 服务类目与资质要求
不同服务类目需要不同的资质:
无需资质:
├── 工具(计算器、天气、日历等)
├── 教育(在线教育信息)
├── 生活服务(家政、维修)
└── 旅游(旅游攻略)
需要资质:
├── 电商 → ICP备案(可选,平台类需要EDI)
├── 餐饮 → 食品经营许可证
├── 医疗 → 互联网医疗保健信息服务许可证
├── 金融 → 金融业务许可证
├── 教育培训 → 教育培训资质
├── 新闻 → 互联网新闻信息服务许可证
├── 出版 → 网络出版服务许可证
├── 游戏 → 网络文化经营许可证
├── 直播 → 信息网络传播视听节目许可证
└── 社交 → ICP备案
注意:选择的服务类目必须与实际功能一致
微信会定期审核,功能不符会被下架
2.3 开发环境搭建
第1步:下载微信开发者工具
├── 下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
├── 选择对应系统版本(Windows/macOS)
└── 安装并登录(使用注册小程序的微信扫码)
第2步:创建项目
├── 打开开发者工具
├── 点击「+」新建项目
├── 填写信息
│ ├── 项目目录:选择本地文件夹
│ ├── AppID:填写真实AppID(不要用测试号)
│ ├── 项目名称
│ └── 开发模式:小程序
├── 后端服务:不使用云服务 / 使用微信云开发
└── 模板:选择「基础模板」或「空白项目」
第3步:项目设置
├── 详情 → 本地设置
│ ├── 勾选「不校验合法域名」(开发阶段)
│ ├── 勾选「ES6转ES5」
│ ├── 勾选「增强编译」
│ └── 勾选「使用npm模块」
└── 详情 → 基本信息
├── 确认AppID正确
└── 查看项目配置
三、小程序开发详解
3.1 项目结构
miniprogram/
├── app.js # 小程序入口(全局逻辑)
├── app.json # 全局配置(页面路由/窗口/TabBar)
├── app.wxss # 全局样式
├── project.config.json # 项目配置
├── sitemap.json # 搜索优化配置
│
├── pages/ # 页面目录
│ ├── index/ # 首页
│ │ ├── index.js # 页面逻辑
│ │ ├── index.json # 页面配置
│ │ ├── index.wxml # 页面模板(类似HTML)
│ │ └── index.wxss # 页面样式(类似CSS)
│ ├── category/ # 分类页
│ │ ├── category.js
│ │ ├── category.json
│ │ ├── category.wxml
│ │ └── category.wxss
│ ├── detail/ # 详情页
│ │ ├── detail.js
│ │ ├── detail.json
│ │ ├── detail.wxml
│ │ └── detail.wxss
│ ├── cart/ # 购物车
│ │ ├── cart.js
│ │ ├── cart.json
│ │ ├── cart.wxml
│ │ └── cart.wxss
│ └── user/ # 个人中心
│ ├── user.js
│ ├── user.json
│ ├── user.wxml
│ └── user.wxss
│
├── components/ # 自定义组件
│ ├── product-card/ # 商品卡片组件
│ │ ├── product-card.js
│ │ ├── product-card.json
│ │ ├── product-card.wxml
│ │ └── product-card.wxss
│ └── loading/ # 加载组件
│ ├── loading.js
│ ├── loading.json
│ ├── loading.wxml
│ └── loading.wxss
│
├── utils/ # 工具函数
│ ├── request.js # 网络请求封装
│ ├── auth.js # 登录鉴权
│ ├── storage.js # 本地存储
│ └── util.js # 通用工具
│
├── services/ # 业务接口
│ ├── user.js # 用户相关接口
│ ├── product.js # 商品相关接口
│ └── order.js # 订单相关接口
│
├── images/ # 图片资源
│ ├── icons/
│ └── tabbar/
│
└── miniprogram_npm/ # npm构建后的包
3.2 核心配置文件
// app.json - 全局配置
{
"pages": [
"pages/index/index",
"pages/category/category",
"pages/detail/detail",
"pages/cart/cart",
"pages/user/user",
"pages/login/login",
"pages/order/order",
"pages/address/address"
],
"window": {
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "我的小程序",
"navigationBarTextStyle": "black",
"backgroundColor": "#f5f5f5",
"backgroundTextStyle": "dark"
},
"tabBar": {
"color": "#999999",
"selectedColor": "#ff6b00",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "images/tabbar/home.png",
"selectedIconPath": "images/tabbar/home-active.png"
},
{
"pagePath": "pages/category/category",
"text": "分类",
"iconPath": "images/tabbar/category.png",
"selectedIconPath": "images/tabbar/category-active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "images/tabbar/cart.png",
"selectedIconPath": "images/tabbar/cart-active.png"
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "images/tabbar/user.png",
"selectedIconPath": "images/tabbar/user-active.png"
}
]
},
"permission": {
"scope.userLocation": {
"desc": "用于获取您的位置信息,提供附近服务"
}
},
"requiredPrivateInfos": ["getLocation"],
"usingComponents": {
"loading": "/components/loading/loading"
},
"networkTimeout": {
"request": 10000,
"downloadFile": 10000
},
"lazyCodeLoading": "requiredComponents"
}
// project.config.json - 项目配置
{
"description": "项目配置文件",
"packOptions": {
"ignore": [
{ "type": "file", "value": ".eslintrc.js" }
]
},
"setting": {
"urlCheck": false, // 开发阶段关闭域名校验
"es6": true, // ES6转ES5
"enhance": true, // 增强编译
"postcss": true, // 自动补全CSS
"preloadBackgroundData": false,
"minified": true, // 代码压缩
"newFeature": true,
"autoAudits": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"compileType": "miniprogram",
"appid": "your-appid-here",
"projectname": "my-miniprogram",
"condition": {}
}
3.3 核心代码示例
// app.js - 全局入口
App({
globalData: {
userInfo: null,
token: null,
baseUrl: 'https://api.example.com'
},
onLaunch() {
// 小程序启动时执行
this.checkLogin()
this.getSystemInfo()
},
// 检查登录状态
checkLogin() {
const token = wx.getStorageSync('token')
if (token) {
this.globalData.token = token
}
},
// 获取系统信息
getSystemInfo() {
const info = wx.getSystemInfoSync()
this.globalData.statusBarHeight = info.statusBarHeight
this.globalData.screenHeight = info.screenHeight
this.globalData.isIPhoneX = info.model.includes('iPhone X') ||
info.safeArea.top > 20
}
})
// utils/request.js - 网络请求封装
const app = getApp()
const request = (options) => {
return new Promise((resolve, reject) => {
wx.request({
url: `${app.globalData.baseUrl}${options.url}`,
method: options.method || 'GET',
data: options.data || {},
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${app.globalData.token || ''}`,
...options.header
},
success(res) {
if (res.statusCode === 200) {
if (res.data.code === 0) {
resolve(res.data.data)
} else if (res.data.code === 401) {
// token过期,跳转登录
wx.removeStorageSync('token')
wx.navigateTo({ url: '/pages/login/login' })
reject(new Error('登录已过期'))
} else {
wx.showToast({ title: res.data.message || '请求失败', icon: 'none' })
reject(new Error(res.data.message))
}
} else {
wx.showToast({ title: `网络错误(${res.statusCode})`, icon: 'none' })
reject(new Error(`HTTP ${res.statusCode}`))
}
},
fail(err) {
wx.showToast({ title: '网络连接失败', icon: 'none' })
reject(err)
}
})
})
}
module.exports = { request }
<!-- pages/index/index.wxml - 首页模板 -->
<view class="container">
<!-- 搜索栏 -->
<view class="search-bar" bindtap="goSearch">
<view class="search-input">
<text class="icon-search"></text>
<text class="placeholder">搜索商品</text>
</view>
</view>
<!-- 轮播图 -->
<swiper class="banner"
indicator-dots="{{true}}"
autoplay="{{true}}"
interval="{{3000}}"
circular="{{true}}">
<swiper-item wx:for="{{banners}}" wx:key="id">
<image src="{{item.image}}" mode="aspectFill"
bindtap="onBannerTap" data-id="{{item.linkId}}"/>
</swiper-item>
</swiper>
<!-- 分类导航 -->
<view class="category-nav">
<view class="category-item"
wx:for="{{categories}}" wx:key="id"
bindtap="goCategory" data-id="{{item.id}}">
<image src="{{item.icon}}" class="category-icon"/>
<text class="category-name">{{item.name}}</text>
</view>
</view>
<!-- 商品列表 -->
<view class="section">
<view class="section-title">热门推荐</view>
<view class="product-list">
<view class="product-card"
wx:for="{{products}}" wx:key="id"
bindtap="goDetail" data-id="{{item.id}}">
<image src="{{item.image}}" mode="aspectFill" class="product-image"/>
<view class="product-info">
<text class="product-name">{{item.name}}</text>
<text class="product-desc">{{item.desc}}</text>
<view class="product-price-row">
<text class="product-price">¥{{item.price}}</text>
<text class="product-origin-price" wx:if="{{item.originPrice}}">
¥{{item.originPrice}}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" wx:if="{{hasMore}}">
<loading wx:if="{{loading}}"/>
<text wx:else bindtap="loadMore">加载更多</text>
</view>
<view class="no-more" wx:if="{{!hasMore && products.length > 0}}">
— 没有更多了 —
</view>
</view>
// pages/index/index.js - 首页逻辑
const { request } = require('../../utils/request')
Page({
data: {
banners: [],
categories: [],
products: [],
page: 1,
hasMore: true,
loading: false
},
onLoad() {
this.loadBanners()
this.loadCategories()
this.loadProducts()
},
// 下拉刷新
onPullDownRefresh() {
this.setData({ page: 1, products: [], hasMore: true })
Promise.all([
this.loadBanners(),
this.loadProducts()
]).finally(() => {
wx.stopPullDownRefresh()
})
},
// 上拉加载更多
onReachBottom() {
if (this.data.hasMore && !this.data.loading) {
this.loadMore()
}
},
// 加载轮播图
async loadBanners() {
const banners = await request({ url: '/api/banners' })
this.setData({ banners })
},
// 加载分类
async loadCategories() {
const categories = await request({ url: '/api/categories' })
this.setData({ categories })
},
// 加载商品
async loadProducts() {
if (this.data.loading) return
this.setData({ loading: true })
try {
const products = await request({
url: '/api/products',
data: { page: this.data.page, limit: 10 }
})
this.setData({
products: this.data.page === 1
? products
: [...this.data.products, ...products],
hasMore: products.length >= 10,
page: this.data.page + 1
})
} finally {
this.setData({ loading: false })
}
},
loadMore() {
this.loadProducts()
},
goSearch() {
wx.navigateTo({ url: '/pages/search/search' })
},
goCategory(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({ url: `/pages/category/category?id=${id}` })
},
goDetail(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({ url: `/pages/detail/detail?id=${id}` })
},
onBannerTap(e) {
const id = e.currentTarget.dataset.id
if (id) {
wx.navigateTo({ url: `/pages/detail/detail?id=${id}` })
}
},
// 分享
onShareAppMessage() {
return {
title: '发现好物,快来看看!',
path: '/pages/index/index'
}
},
onShareTimeline() {
return {
title: '发现好物,快来看看!'
}
}
})
// pages/index/index.json - 首页页面配置
{
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"usingComponents": {
"loading": "/components/loading/loading"
}
}
/* pages/index/index.wxss - 首页样式 */
.container {
background: #f5f5f5;
min-height: 100vh;
}
.search-bar {
padding: 20rpx 30rpx;
background: #fff;
}
.search-input {
display: flex;
align-items: center;
padding: 16rpx 24rpx;
background: #f5f5f5;
border-radius: 36rpx;
gap: 12rpx;
}
.placeholder {
color: #999;
font-size: 28rpx;
}
.banner {
width: 100%;
height: 360rpx;
}
.banner image {
width: 100%;
height: 100%;
}
.category-nav {
display: flex;
flex-wrap: wrap;
padding: 30rpx 20rpx;
background: #fff;
margin-bottom: 20rpx;
}
.category-item {
width: 20%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20rpx;
}
.category-icon {
width: 88rpx;
height: 88rpx;
margin-bottom: 10rpx;
}
.category-name {
font-size: 24rpx;
color: #333;
}
.section {
background: #fff;
padding: 30rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
}
.product-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.product-card {
width: calc(50% - 10rpx);
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
}
.product-image {
width: 100%;
height: 340rpx;
}
.product-info {
padding: 16rpx 20rpx;
}
.product-name {
font-size: 26rpx;
color: #333;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.product-desc {
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
}
.product-price-row {
display: flex;
align-items: baseline;
gap: 12rpx;
margin-top: 12rpx;
}
.product-price {
font-size: 32rpx;
color: #ff6b00;
font-weight: bold;
}
.product-origin-price {
font-size: 22rpx;
color: #ccc;
text-decoration: line-through;
}
.load-more, .no-more {
text-align: center;
padding: 30rpx;
color: #999;
font-size: 24rpx;
}
3.4 微信登录与用户信息
// utils/auth.js - 登录模块
const { request } = require('./request')
// 微信登录(获取openid)
const wxLogin = () => {
return new Promise((resolve, reject) => {
wx.login({
success(res) {
if (res.code) {
// 将code发送到后端换取openid和session_key
request({
url: '/api/auth/wx-login',
method: 'POST',
data: { code: res.code }
}).then(data => {
// 保存token
wx.setStorageSync('token', data.token)
getApp().globalData.token = data.token
getApp().globalData.userInfo = data.userInfo
resolve(data)
}).catch(reject)
} else {
reject(new Error('登录失败'))
}
},
fail: reject
})
})
}
// 获取用户信息(需要用户授权)
const getUserProfile = () => {
return new Promise((resolve, reject) => {
wx.getUserProfile({
desc: '用于完善用户资料',
success(res) {
resolve(res.userInfo)
},
fail(err) {
reject(err)
}
})
})
}
// 检查登录状态并跳转
const checkLoginAndRedirect = () => {
const token = wx.getStorageSync('token')
if (!token) {
wx.navigateTo({ url: '/pages/login/login' })
return false
}
return true
}
module.exports = { wxLogin, getUserProfile, checkLoginAndRedirect }
// services/user.js - 用户相关接口
const { request } = require('../utils/request')
// 获取用户信息
const getUserInfo = () => request({ url: '/api/user/info' })
// 更新用户信息
const updateUserInfo = (data) => request({
url: '/api/user/info',
method: 'PUT',
data
})
// 获取收货地址列表
const getAddressList = () => request({ url: '/api/user/addresses' })
// 添加收货地址
const addAddress = (data) => request({
url: '/api/user/addresses',
method: 'POST',
data
})
module.exports = { getUserInfo, updateUserInfo, getAddressList, addAddress }
3.5 微信支付集成
// utils/payment.js - 微信支付
const { request } = require('./request')
/**
* 发起微信支付
* @param {string} orderId 订单ID
*/
const wxPayment = (orderId) => {
return new Promise(async (resolve, reject) => {
try {
// 1. 从后端获取支付参数
const payParams = await request({
url: '/api/pay/create',
method: 'POST',
data: { orderId }
})
// 2. 调用微信支付
wx.requestPayment({
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: payParams.signType || 'MD5',
paySign: payParams.paySign,
success(res) {
// 支付成功
resolve(res)
},
fail(err) {
if (err.errMsg.includes('cancel')) {
// 用户取消
reject(new Error('用户取消支付'))
} else {
// 支付失败
reject(new Error('支付失败'))
}
}
})
} catch (err) {
reject(err)
}
})
}
module.exports = { wxPayment }
四、自定义组件开发
// components/product-card/product-card.js
Component({
// 属性
properties: {
product: {
type: Object,
value: {}
},
showAction: {
type: Boolean,
value: true
}
},
// 数据
data: {
isFavorite: false
},
// 方法
methods: {
onTap() {
this.triggerEvent('tap', { id: this.properties.product.id })
},
onFavorite(e) {
this.setData({ isFavorite: !this.data.isFavorite })
this.triggerEvent('favorite', {
id: this.properties.product.id,
isFavorite: this.data.isFavorite
})
},
onAddCart(e) {
this.triggerEvent('addcart', { id: this.properties.product.id })
}
}
})
<!-- components/product-card/product-card.wxml -->
<view class="card" bindtap="onTap">
<image src="{{product.image}}" mode="aspectFill" class="image"/>
<view class="info">
<text class="name">{{product.name}}</text>
<view class="bottom">
<text class="price">¥{{product.price}}</text>
<view class="actions" wx:if="{{showAction}}">
<view class="btn-fav {{isFavorite ? 'active' : ''}}"
catchtap="onFavorite">
{{isFavorite ? '已收藏' : '收藏'}}
</view>
<view class="btn-cart" catchtap="onAddCart">加入购物车</view>
</view>
</view>
</view>
</view>
// components/product-card/product-card.json
{
"component": true,
"usingComponents": {}
}
五、云开发(可选)
微信云开发是Serverless方案,无需自己搭建服务器。
功能:
├── 云函数:Node.js运行环境,按调用计费
├── 云数据库:JSON数据库,类似MongoDB
├── 云存储:文件上传下载
└── 云托管:容器化部署
开通步骤:
1. 开发者工具 → 云开发 → 开通
2. 创建环境(免费版有配额限制)
3. 在app.js中初始化
费用(按量计费):
├── 云函数:0.00011108元/GB·秒
├── 数据库:0.007元/万次读,0.035元/万次写
├── 存储:0.0043元/GB·天
└── 免费额度:每月有一定的免费配额
// 云函数示例:cloud/functions/login/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
exports.main = async (event) => {
const wxContext = cloud.getWXContext()
return {
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID
}
}
// 前端调用云函数
wx.cloud.callFunction({
name: 'login',
data: {},
success(res) {
console.log('openid:', res.result.openid)
}
})
// 云数据库操作
const db = wx.cloud.database()
const _ = db.command
// 添加
await db.collection('todos').add({
data: { text: '学习小程序', done: false, createTime: db.serverDate() }
})
// 查询
const { data } = await db.collection('todos')
.where({ done: false })
.orderBy('createTime', 'desc')
.limit(20)
.get()
// 更新
await db.collection('todos').doc('doc-id').update({
data: { done: true }
})
// 删除
await db.collection('todos').doc('doc-id').remove()
六、体验版与审核前测试
6.1 体验版发布
体验版用于内部测试,无需审核。
步骤:
1. 开发者工具 → 点击「上传」
2. 填写版本号(如 1.0.0)和项目备注
3. 上传成功后,在小程序后台操作
4. 登录 mp.weixin.qq.com
5. 管理 → 版本管理
6. 在「开发版本」中找到刚上传的版本
7. 点击「选为体验版」
8. 设置体验版有效期(最长30天)
添加体验成员:
1. 成员管理 → 体验成员
2. 添加微信号(最多15人,未认证账号)
3. 认证后最多200人
体验成员使用:
1. 微信扫码体验版二维码
2. 或搜索小程序名称 → 切换到体验版
6.2 调试与排查
常见问题排查:
1. 白屏/页面不显示
├── 检查pages路径是否正确
├── 检查JSON配置是否有语法错误
└── 查看Console日志
2. 网络请求失败
├── 检查是否配置了合法域名
├── 开发阶段:设置 → 不校验合法域名
├── 生产环境:必须配置HTTPS域名
└── 检查域名是否有ICP备案
3. 登录失败
├── 确认AppID是否正确
├── 确认后端session_key处理是否正确
└── 不要将session_key传给前端
4. 支付失败
├── 确认已开通微信支付
├── 确认商户号与小程序已关联
├── 确认支付参数签名正确
└── 确认金额单位为分
5. 组件不显示
├── 检查usingComponents配置
├── 检查组件路径是否正确
└── 检查组件JSON中component字段是否为true
七、提交审核与发布
7.1 提交审核完整流程
第1步:代码上传
├── 开发者工具 → 点击「上传」
├── 版本号:语义化版本(如 1.0.0)
├── 项目备注:说明本次更新内容
└── 等待上传完成
第2步:配置审核信息
├── 登录 mp.weixin.qq.com
├── 管理 → 版本管理
├── 在「开发版本」中找到版本
├── 点击「提交审核」
├── 填写审核信息:
│ ├── 测试账号(如果需要登录)
│ │ ├── 账号:xxx
│ │ └── 密码:xxx
│ ├── 测试密码(如果功能有密码保护)
│ ├── 补充说明(审核员需要注意的事项)
│ └── 配置功能页面(重要!)
│ ├── 添加小程序的功能页面路径
│ ├── 填写标题
│ └── 上传截图(展示核心功能)
└── 确认提交
第3步:等待审核
├── 审核时间:通常1-7天
├── 加急审核:每年有3次加急机会,2小时内出结果
├── 查看审核状态:
│ ├── mp.weixin.qq.com → 版本管理
│ └── 微信通知
└── 审核结果通知方式:
├── 邮件通知
├── 微信公众平台通知
└── 微信服务通知
第4步:审核结果处理
├── 审核通过
│ ├── 可选择「立即发布」或「定时发布」
│ ├── 发布后全量用户可用
│ └── 建议在流量低峰期发布(凌晨)
│
├── 审核被拒
│ ├── 查看拒绝原因(详细说明)
│ ├── 修复问题
│ ├── 重新上传并提交
│ └── 可在7天内申诉
│
└── 常见拒绝原因及解决
├── 功能不完整/无法使用
│ └── 确保所有页面和功能可正常访问
├── 内容违规
│ └── 检查是否违反平台规则
├── 类目不符
│ └── 修改服务类目或取得相应资质
├── 缺少测试账号
│ └── 提供可登录的测试账号
├── 页面无法访问
│ └── 确保服务器正常运行
└── UI设计问题
└── 确保界面完整、美观、无乱码
7.2 审核要点清单
提交前自查清单:
□ 所有页面可以正常打开
□ 所有功能可以正常使用(不要有TODO/占位符)
□ 网络请求域名已配置到合法域名
□ 服务器正常运行,接口返回正常
□ 登录功能正常(如需要登录)
□ 支付功能正常(如有支付)
□ 图片和资源加载正常
□ 页面布局在不同机型上正常显示
□ 没有明显的Bug和崩溃
□ 没有测试数据和调试代码
□ 隐私政策页面可访问
□ 用户协议页面可访问(如有)
□ 服务类目与实际功能一致
□ 已取得所需资质(如有)
□ 提供了测试账号(如需要登录)
□ 没有诱导分享、诱导关注等行为
□ 没有虚拟支付(iOS端限制)
□ 没有未报备的直播功能
□ 内容健康,不违反法律法规
7.3 版本更新与灰度发布
版本更新流程:
1. 开发新版本
2. 上传代码
3. 提交审核
4. 审核通过
5. 发布(可选择灰度发布)
灰度发布(逐步放量):
├── 发布时选择「灰度发布」
├── 设置灰度比例(如先放10%用户)
├── 观察数据和反馈
├── 没有问题后逐步增加比例
└── 最终全量发布
版本回退:
├── 如果新版本有严重问题
├── 版本管理 → 已发布版本 → 回退
├── 只能回退到上一个版本
└── 回退后需要重新提交审核才能再次发布
八、小程序运营与数据分析
8.1 数据分析
小程序后台提供的数据:
1. 概况数据
├── 累计用户数
├── 昨日新增用户
├── 昨日活跃用户
└── 今日实时数据
2. 访问分析
├── 访问次数/人数
├── 新访客/老访客比例
├── 平均停留时长
├── 次均停留时长
├── 访问深度分布
└── 访问页面排行
3. 实时统计
├── 实时访问曲线
├── 实时访问来源
└── 实时访客地区分布
4. 用户画像
├── 性别分布
├── 年龄分布
├── 地区分布
└── 终端分布(机型/系统版本)
5. 来源分析
├── 搜索
├── 扫描二维码
├── 会话分享
├── 公众号
├── 附近的小程序
└── 其他来源
8.2 小程序SEO优化
搜索优化配置(sitemap.json):
{
"rules": [
{
"action": "allow",
"page": "pages/index/index"
},
{
"action": "allow",
"page": "pages/detail/detail",
"params": ["id"],
"matching": "inclusive"
},
{
"action": "disallow",
"page": "*"
}
]
}
优化要点:
1. 小程序名称包含核心关键词
2. 小程序描述详细且包含关键词
3. 页面标题(navigationBarTitleText)要有关键词
4. 页面路径清晰有意义
5. 配置sitemap允许搜索引擎收录
6. 提交页面收录(搜索 → 搜索设置 → 页面收录)
7. 保持更新频率
8.3 推广方式
| 方式 | 说明 | 效果 |
|---|---|---|
| 搜索优化 | 配置关键词、优化描述 | 被动流量,长期有效 |
| 二维码 | 线下物料/海报/名片 | 线下场景 |
| 公众号关联 | 公众号菜单/文章嵌入 | 私域流量 |
| 社交分享 | 用户分享给好友/群 | 裂变传播 |
| 附近的小程序 | 基于地理位置 | 本地商家 |
| 小程序互跳 | 与其他小程序互相跳转 | 换量合作 |
| 微信广告 | 朋友圈广告/公众号广告 | 付费推广 |
| 视频号 | 视频号挂载小程序 | 内容引流 |
| 搜一搜 | 品牌搜索/服务搜索 | 搜索流量 |
| 直播带货 | 小程序内直播 | 电商 |
九、费用清单
| 项目 | 费用 | 必须? |
|---|---|---|
| 小程序注册 | 免费 | 是 |
| 微信认证 | 300元/年 | 企业必须,个人可选 |
| 域名 | 50-100元/年 | 是(需ICP备案) |
| 服务器 | 50-500元/月 | 是(云开发可免费) |
| SSL证书 | 0-1000元/年 | 是(Let's Encrypt免费) |
| 微信支付商户号 | 0元开通 | 如需支付 |
| 支付手续费 | 0.6% | 每笔交易 |
| 短信验证码 | 0.04-0.06元/条 | 如需手机登录 |
| <strong>总计(最低)</strong> | <strong>约500-1500元/年</strong> | 基础配置 |
十、完整开发时间预估
| 阶段 | 工作内容 | 时间 |
|---|---|---|
| 注册准备 | 账号注册、域名、服务器 | 1-2天 |
| UI设计 | 页面设计、切图 | 3-7天 |
| 前端开发 | 页面开发、交互逻辑 | 2-4周 |
| 后端开发 | API接口、数据库 | 2-4周 |
| 联调测试 | 前后端联调、Bug修复 | 1-2周 |
| 体验测试 | 内部测试、优化 | 3-5天 |
| 提交审核 | 审核与修改 | 1-2周 |
| <strong>总计</strong> | <strong>6-10周</strong> |