☰
微信小程序前后端分离开发实战:V1.0.39版本核心技巧与避坑指南
2026/10/11 17:15:13 网站建设 项目流程

简介:榆落微时光V1.0.39是一套开箱即用的论坛类小程序完整源码,面向具备基础Web开发能力的中初级开发者,助力快速搭建高可用在线社区平台。资源包含前端(WXML/WXSS/JS)与后端(PHP为主)全量代码,共1831个文件,其中819个PHP文件构成核心服务逻辑,328个PNG及17个JPG/GIF等图像资源支撑UI展示,179个JS文件实现交互与状态管理,辅以JSON配置、HTML模板及CSS样式文件,整体压缩包仅16.42MB,轻量易部署。已有308人学习下载,适合作为小程序前后端协同开发、社区系统架构设计与PHP+微信生态实战的参考范例。源码结构清晰,含Admin后台、用户权限体系、帖子CRUD接口及安全防护机制,并集成AmazeUI、Bootstrap等成熟CSS框架,便于二次开发与功能扩展。

开篇:从V1.0.39说起,这个版本到底沉淀了什么

"榆落微时光"这个项目,我断断续续维护了大半年,最近刚把V1.0.39推上线。它是一个典型的微信小程序前后端分离项目,前端用原生小程序框架开发,后端基于Node.js提供接口服务。从最初一个单纯记录日常的小工具,慢慢迭代成了一个集时光记录、打卡习惯、心情日记、数据统计于一体的私密生活助手。

说实话,市面上类似的小程序模板一抓一大把,但真正自己从零搭一套前端+后端,把每一个功能模块都吃透,踩过的坑积累下来,这套经验才是值钱的。尤其是我发现很多开发者卡在最基础的一环——前后端到底怎么分工、接口怎么设计、数据怎么流转、小程序审核那些坑怎么绕。这篇博文,我打算把V1.0.39这个版本里前端和后端的完整实现思路、关键代码逻辑、以及我在实际开发中总结的排查经验,一次性讲清楚。

如果你是刚接触小程序开发的前端新人,或者正在做前后端分离项目的后端同学,又或者你正打算从"能用"升级到"好用",这篇内容都值得你花十几分钟慢慢看。我会涉及不少实测过的问题,比如微信小程序单选框的坑、分包异步化的正确姿势、顶部导航栏高度适配,以及后端接口跨域的那些事,都是真实项目里反复出现的高频问题。

1. 整体设计与技术选型:为什么这么搭

1.1 产品定位与功能边界

先交代一下"榆落微时光"到底是干什么的。核心场景就一句话:让用户用碎片化时间,记录当下心情和生活中的小确幸。围绕这个定位,我规划了四个核心模块:

  • 时光记录:支持文字、图片、地理位置,按时间轴展示
  • 习惯打卡:每日打卡、连续天数统计、提醒设置
  • 心情日记:轻量级日记本,支持标签分类和情绪标记
  • 数据看板:月度/年度统计,打卡率、心情趋势等可视化

这个产品定位决定了技术选型不需要太重,但也不能太轻。用户数据涉及隐私(日记、定位),所以后端的权限控制和数据隔离必须做扎实。V1.0.39这个版本重点打磨的是时光记录模块的体验,把图片上传从原来的单张改成了最多九张,同时增加了草稿箱机制,防止用户写了半天不小心退出导致内容丢失。

1.2 前端技术栈与框架选择

小程序前端我选择的是微信官方原生框架,没上uni-app或者Taro。原因很现实:这个项目核心是微信生态内使用,原生框架在组件兼容性、调试工具、性能调优方面有天然优势。而且微信小程序单选框、地图组件、分包加载这些特性,原生支持是最即时的。

组件库方面,我没有用Vant Weapp这类重量级组件库,而是自己封装了一套轻量UI组件。主要原因是这个小程序页面数量不算多,而且自定义组件在视觉统一性和包体积控制上更灵活。当然,如果你做的是小程序商城这类页面逻辑特别重的项目,Vant Weapp确实能省不少事,这个得看场景。

这里补充一个我实测过的经验:小程序分包异步化的坑。V1.0.39把"数据看板"模块拆到了独立分包里,结果在别的分包页面通过wx.requirePlugin或者异步引用时,经常出现组件找不到的情况。后来排查发现,是因为没有在app.json里正确配置subpackages的root和pages,而且异步化需要基础库版本不低于2.11.2。这个后面我会展开讲。

1.3 后端框架与数据库选型

后端我用的Node.js + Express,数据库选了MySQL 8.0,缓存用了Redis。选这套组合的原因很直接:前后端都用JavaScript/TypeScript,语言统一,维护成本低。如果你熟悉Java,用ruoyi框架或者Spring Boot也完全没问题,核心思路是一样的。

具体到项目结构,我采用了经典的三层架构:

  • 路由层(routes):统一处理HTTP请求,参数校验在入口处完成
  • 业务层(services):核心逻辑全部在这里,不直接操作数据库
  • 数据访问层(models):用Sequelize ORM映射数据库表

其实还有一个重要的中间层——统一的响应格式和异常处理中间件。所有接口返回的JSON结构必须统一,比如{ code: 0, data: {}, message: 'success' },这样前端处理逻辑才不用到处写兼容。这个看似不起眼的设计,在后面排查"前端无法获取数据"这类问题时帮了大忙。

1.4 关键依赖清单

前端依赖:

依赖项版本用途
微信开发者工具最新稳定版开发调试与预览
miniprogram-api-typings^3.12.0TypeScript类型定义
mobx-miniprogram^6.3.0全局状态管理
mobx-miniprogram-bindings^4.1.0绑定React式更新

后端依赖:

依赖项版本用途
Express^4.19.2Web框架
Sequelize^6.37.0ORM
mysql2^3.9.0MySQL驱动
jsonwebtoken^9.0.0JWT鉴权
multer^1.4.5-lts.1文件上传处理
winston^3.13.0日志系统
nodemon^3.1.0开发热更新

2. 前端核心细节与实操要点

2.1 小程序目录结构与分包策略

先看V1.0.39版本的完整目录结构,这个结构是我迭代了十几次后固定下来的,前端项目根目录如下:

miniprogram/ ├── app.js # 全局入口,初始化登录态 ├── app.json # 全局配置,含分包配置 ├── app.wxss # 全局样式 ├── pages/ │ ├── index/ # 首页·时光流 │ ├── record/ # 新建记录 │ ├── habits/ # 习惯打卡 │ ├── diary/ # 心情日记 │ ├── profile/ # 个人中心 │ └── webview/ # H5承载页 ├── packageStats/ # 独立分包:数据看板 │ ├── stats/ │ └── charts/ ├── components/ # 自定义组件 │ ├── time-line/ # 时间轴组件 │ ├── upload-images/ # 多图上传组件 │ ├── empty-state/ # 空状态占位 │ └── calendar-heatmap/ # 热力图组件 ├── utils/ │ ├── request.js # 请求封装 │ ├── auth.js # 登录态管理 │ ├── format.js # 日期/时间格式化 │ └── upload.js # 上传逻辑封装 └── store/ # mobx状态管理

分包策略我详细解释一下。主包体积被限制在2MB以内,这是微信的硬性要求。V1.0.39中,我把"数据看板"和"图表库"拆到了独立分包packageStats,因为ECharts的min版本就有将近1MB,放在主包会直接爆炸。

实际踩坑记录:分包异步化在其它分包中插入组件时,必须在app.json中的分包配置里声明independent: true,但独立分包不能引用主包资源,两者会有冲突。我一开始把图标也放主包里,结果独立分包页面引用时直接白屏。正确做法是:独立分包内的页面尽量使用内置组件或分包内的自定义组件。

2.2 微信小程序单选框的正确使用方式

V1.0.39里新增的心情标签选择器,用的是微信小程序单选框(radio-group)。这里有个特别容易被忽视的问题:radio-group的change事件返回的是被选中的value,而不是整个选项对象。很多新手会在这里写错:

// 错误做法:直接在事件里取整个选项对象 onTagChange(e) { // e.detail.value 是字符串,不是对象 this.setData({ selectedTag: e.detail.value }); }
// 正确做法:先取value,再通过数据映射找到完整对象 onTagChange(e) { const value = e.detail.value; const tag = this.data.tagList.find(item => item.id === value); this.setData({ selectedTag: tag }); }

另外一个坑是单选框的样式定制。默认的小圆圈样式很丑,flex布局下跟文字对齐也有问题。我最终是这样处理的:把radio的默认样式隐藏(opacity: 0),然后用自定义的view来做视觉呈现,通过label的for属性关联。这样既保留了原生组件的语义,又完全控制了UI表现。

2.3 微信小程序顶部导航栏高度适配

这是V1.0.39版本里做沉浸式头部时最头疼的问题。小程序顶部导航栏高度不是一个固定值,不同机型、不同系统版本,甚至是否开启胶囊按钮都会影响实际高度。我封装了一个工具函数:

// utils/navigation.js function getNavigationBarHeight() { const systemInfo = wx.getSystemInfoSync(); const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); // 顶部状态栏高度(刘海屏更高) const statusBarHeight = systemInfo.statusBarHeight; // 胶囊按钮高度 const menuButtonHeight = menuButtonInfo.height; // 胶囊按钮与状态栏的间距 const menuButtonTop = menuButtonInfo.top; // 导航栏总高度 = 状态栏高度 + 胶囊上下边距 + 胶囊高度 const navBarHeight = (menuButtonTop - statusBarHeight) * 2 + menuButtonHeight; return { statusBarHeight, navBarHeight, totalHeight: statusBarHeight + navBarHeight, menuButtonInfo }; }

这个思路大家一定要记住:胶囊按钮的位置是动态计算的,而不是写死44px。在iPhone X之后的全面屏机型上,状态栏高度是44-47px,普通机型是20px,写死的话UI直接错乱。

另外一个相关问题是自定义导航栏还涉及wx.setNavigationBarTitle失效的问题。当你使用了自定义导航栏(在app.json里配置"navigationStyle": "custom"),默认API设置标题就不生效了,必须自己通过setData控制页面标题的text节点。

2.4 多图上传组件的实现细节

V1.0.39将图片从单张升级为九张,这里涉及一个非常典型的性能优化场景。我之前直接用wx.uploadFile循环上传,结果在小程序端会阻塞UI渲染,尤其在安卓低端机上,卡顿特别明显。后来改成了并发控制上传:

// utils/upload.js async function uploadImages(filePaths, concurrency = 3) { const results = []; let index = 0; async function worker() { while (index < filePaths.length) { const current = index++; const filePath = filePaths[current]; try { const res = await uploadOne(filePath); results[current] = { success: true, url: res.url }; } catch (err) { results[current] = { success: false, error: err }; } } } const workers = Array.from({ length: Math.min(concurrency, filePaths.length) }, () => worker()); await Promise.all(workers); return results; }

这样控制并发数为3,既保证上传速度,又不会因为同时发起太多请求导致微信小程序网络层异常。这里还有一个关键点:每张图在上传前必须进行压缩。我使用wx.compressImage接口,把图片质量压缩到80%,长边限制在1920px,否则用户相册里一张几MB的照片上传到服务器,流量消耗和存储成本都扛不住。

2.5 前端请求封装与错误处理

utils/request.js是小程序前端的命脉。我基于Promise封装了wx.request,统一处理以下几件事:

  1. 自动附带Authorization请求头(从wx.getStorageSync('token')读取)
  2. 响应状态码统一判断,业务错误码统一弹出Toast
  3. 处理401未授权:自动尝试刷新token,刷新失败则跳转登录页
  4. 网络异常统一提示"网络开小差了"
  5. 支持取消请求(用于页面卸载时清理)

这里分享一个实战心得:微信小程序的wx.request不会遵循HTTP的Cache-Control头,所以如果后端接口返回了304状态码,小程序端可能依然拿不到缓存结果。V1.0.39里,对于数据看板的统计数据,我在前端用wx.setStorageSync做了30秒短缓存,而不是依赖后端缓存头,实测下来请求量明显下降。

我发现一个关于“前端面试题”相关热词背后用户最关心的点——闭包、事件循环、this指向,在小程序开发中同样高频踩坑。比如在自定义组件中使用setData回调时,如果不把this用箭头函数绑定,很容易出现"setData is not a function"。这些都是基本功,我强烈建议在项目里统一使用箭头函数或提前绑定。

3. 后端API设计与核心实现

3.1 数据模型与数据库设计

V1.0.39版本的数据库一共17张表。核心几张表的设计思路如下:

users(用户表)

字段名类型说明
idint主键自增
openidvarchar(64)微信openid,唯一索引
nicknamevarchar(50)昵称
avatarvarchar(255)头像URL
statustinyint1正常 0封禁
last_login_atdatetime最后登录时间

records(时光记录表)

字段名类型说明
idint主键
user_idint所属用户
contenttext文字内容
imagesjson图片URL数组
locationvarchar(255)位置描述
latitudedecimal(10,7)纬度
longitudedecimal(10,7)经度
mood_tagvarchar(20)心情标签
created_atdatetime创建时间

habits(习惯表)

字段名类型说明
idint主键
user_idint所属用户
namevarchar(50)习惯名称
iconvarchar(10)图标
remind_timetime提醒时间
statustinyint1进行中 0已结束

补充一个设计细节:记录表的images字段用的是JSON类型,而不是单独建一张图片表。这个取舍基于实际业务——记录图片只在查看记录详情时一次性读取,不需要跨表查询。如果未来要做图片搜索或者按图片维度聚合,再考虑拆分。

3.2 统一响应格式与异常处理

后端所有接口统一返回格式,这个一定要从一开始就定好,不然后面前后端联调会非常痛苦。我的封装如下:

// utils/response.js function success(data = null, message = 'ok') { return { code: 0, data, message }; } function error(code = 1, message = 'error') { return { code, data: null, message }; }

配合Express的全局错误处理中间件:

// app.js 中注册全局异常处理 app.use((err, req, res, next) => { logger.error(`${req.method} ${req.path}`, err); if (err.name === 'UnauthorizedError') { return res.status(401).json(error(401, '登录已过期')); } if (err.name === 'ValidationError') { return res.status(400).json(error(400, err.message)); } return res.status(500).json(error(500, '服务器内部错误')); });

这个设计让前端只需检查code字段是否为0,不需要每个接口单独做异常判断。在"前端无法获取数据"的排查场景里,这个统一结构能让你快速区分是后端接口报错,还是前端渲染问题。

3.3 JWT鉴权与微信登录流程

小程序的登录认证流程,和传统Web应用有很大区别。核心区别在于:小程序端通过wx.login获取的是临时code,这个code必须发送到后端,再由后端通过微信的接口换取openid和session_key。真正的登录态由后端管理,给前端签发JWT。

V1.0.39版本的登录时序如下:

  1. 小程序端调用wx.login(),获取临时code
  2. 小程序端将code通过request发送到后端POST /api/auth/login
  3. 后端用code调用微信接口jscode2session,换取openid和session_key
  4. 后端根据openid查询或创建用户记录
  5. 后端签发JWT(payload包含user_id,有效期7天),返回给前端
  6. 前端将JWT存到wx.setStorageSync('token'),后续请求自动附带

有一个容易忽略的细节:必须校验code的时效性。微信的code有效期只有5分钟,且只能用一次。如果前端因为网络异常重复发送同一个code,第二次会直接失败。我专门加了日志来排查这个问题,发现大部分"登录失败"都是这个原因。

3.4 文件上传的后端处理

配合前端的多图上传,后端使用multer处理图片接收,思路如下:

// routes/upload.js const multer = require('multer'); const path = require('path'); const fs = require('fs'); const storage = multer.diskStorage({ destination(req, file, cb) { const date = new Date(); const dir = path.join(__dirname, `../../uploads/${date.getFullYear()}/${date.getMonth() + 1}`); fs.mkdirSync(dir, { recursive: true }); cb(null, dir); }, filename(req, file, cb) { const ext = path.extname(file.originalname); const unique = Date.now() + '-' + Math.round(Math.random() * 1e9); cb(null, `${unique}${ext}`); } }); const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 }, // 5MB限制 fileFilter(req, file, cb) { const allowTypes = ['image/jpeg', 'image/png', 'image/webp']; if (allowTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('不支持的图片格式')); } } }); router.post('/image', authMiddleware, upload.array('file', 9), (req, res) => { const urls = req.files.map(f => `/uploads/${f.filename}`); res.json(success(urls)); });

这里有个非常关键的生产环境问题:直接存本地磁盘在多有服务器场景下不可靠。如果后续部署用到多个Node.js实例,用户上传的图片可能落在不同的机器上,访问就404了。V1.0.39目前是单机部署,所以本地存储没问题;如果你打算上云,需要换成对象存储(如阿里云OSS或腾讯云COS),上传流程改为:后端生成预签名URL,前端直接上传到对象存储,再把文件信息回传后端记录。

3.5 后端跨域配置详解

前后端分离项目最常见的联调问题就是跨域。虽然小程序端wx.request不遵循浏览器同源策略,理论上不需要CORS,但在开发者工具里预览,以及如果你有Web管理后台,就必须处理跨域。

我用了cors中间件,按环境动态配置:

const cors = require('cors'); const allowedOrigins = process.env.NODE_ENV === 'production' ? ['https://admin.yuluo.com'] : ['http://localhost:8080', 'http://192.168.1.100:8080']; app.use(cors({ origin(origin, callback) { // 如果origin为undefined,比如通过Postman请求,直接放行 if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true, // 携带cookie maxAge: 86400 // 预检请求缓存1天 }));

在实际部署时还遇到过一个很隐蔽的问题:使用Nginx反向代理后,如果你在Nginx层也配置了跨域头,而后端又在代码里配置了跨域头,双重重叠会导致部分浏览器报"Access-Control-Allow-Origin重复"错误。处理方案:要么全在Nginx层配置,要么全在应用层配置,不要两层都配。

4. 版本迭代中的问题排查与避坑经验

4.1 微信小程序审核那些事

V1.0.39在提审时遇到一个很典型的问题:小程序涉及记录文字和图片,被审核方要求补充文娱-其他视频类目。实际上我们的产品并不播放视频,但审核系统可能因为某些关键词匹配误判了。

我总结的排查思路:

  1. 先仔细阅读驳回理由,区分是"涉及服务类目"还是"内容安全"问题
  2. 如果是类目问题,确认是否有对应资质(ICP备案、软件著作权等)
  3. 如果确实不涉及,通过"申诉"通道提交说明,附上录屏或页面截图
  4. 多数情况下,补充隐私协议和用户授权弹窗可以顺利过审

一个有效建议:在提审前,把用户的隐私授权流程前置。无论是否采集用户隐私,都在用户第一次打开小程序时主动弹窗说明数据使用规则,这能避免很多审核麻烦。

4.2 微信小程序地图组件的正确选择

热词里有"微信小程序可以使用天地图画地图组件吗",这个我实测过。答案是:微信小程序原生地图组件<map>不支持天地图,它只适配腾讯地图的SDK。如果你需要使用天地图的数据源,目前主流的做法有两种:

  1. WebView方案:用web-view组件加载天地图的H5页面,适合展示复杂地图业务
  2. 地图SDK方式:使用天地图官方提供的Web API,通过web-view封装调用

在V1.0.39版本中,时光记录的位置查看功能用原生<map>组件就够了,因为只是展示定位点,不需要天地图的影像底图。如果后续有更专业的地图需求,我会考虑引入高德地图的web服务API,在小程序端用wx.request调用,而不是直接嵌入地图组件。

4.3 "前端无法获取数据"的排查方法论

这是我在群里看到提问最多的一类问题,也是V1.0.39开发过程中我自己踩过的坑。这里给出我总结的排查金字塔:

从下往上依次排查:

第一层:后端服务是否在正常运行。检查nodemon是否崩了、进程是否还在监听端口。命令:lsof -i:3000

第二层:接口地址是否正确。小程序端url要区分开发环境(本地IP+端口)和生产环境(域名),且本地调试时避开微信开发者工具的缓存问题。

第三层:网络请求是否发送成功。打开开发者工具的Network面板,看请求状态码和响应体。如果请求直接pending,检查代理设置;如果返回500,看后端日志。

第四层:前端解析是否出错。很多数据在浏览器里显示正常,在小程序里白屏,是因为小程序不支持某些ES6+语法或DOM操作。

第五层:数据绑定是否更新。设置setData之后,确认data字段是否真的变化了,注意setData是异步的,如果紧接着读取this.data可能拿到旧值。

4.4 微信小程序抓包技巧

小程序抓包,很多新手问我到底怎么操作。这里提供一个我已经验证的方案,用Charles + 微信开发者工具:

  1. 打开微信开发者工具,点击右上角"详情" -> "本地设置",勾选"不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书"

  2. 在Charles中开启SSL Proxying,添加*通配符或者只添加你的后端接口域名

  3. 默认情况下,开发者工具发出的请求会走系统代理。如果抓不到包,可以在启动命令行时加入代理参数

注意:真机调试时抓包更麻烦。需要在手机WiFi设置里配置HTTP代理,且微信小程序的HTTPS链接在Charles里显示为乱码时,需要在手机安装Charles的根证书。

4.5 微信小程序蓝牙功能与安卓14适配

热词里提到"安卓14小程序蓝牙",这个我在接入蓝牙打卡设备时踩了不少坑。微信小程序蓝牙API(wx.openBluetoothAdapter、wx.startBluetoothDevicesDiscovery等)受系统版本影响很大,尤其是Android 12以上新增的附近设备权限限制。

V1.0.39版本虽然没用蓝牙,但我之前一个手环联动项目遇到的适配经验,可以分享给大家:

  • 在app.json中不能直接声明蓝牙权限,而是需要用户主动授权
  • Android 12+上,必须先调用wx.authorize({ scope: 'scope.bluetooth' }),否则无法获取扫描结果
  • 安卓14上,扫描蓝牙设备时会弹出系统级的附近设备权限申请,如果用户拒绝,wx.onBluetoothDeviceFound会静默失效,代码层面不会报错
  • 推荐使用wx.getSystemSetting()和wx.getAppAuthorizeSetting()检查权限状态,引导用户回系统设置开启

4.6 前端使用Worker上传大文件的优化

这个问题我非常推荐大家关注。V1.0.39版本里的一个用户反馈是:在弱网环境下传九张图,页面会卡顿甚至闪退。排查后定位到主线程被文件读取和压缩阻塞了。

我当时的优化方案是用wx.createWorker创建一个Worker线程,将图片压缩和上传前的预处理操作放到Worker中执行,主线程只负责渲染进度条。示例如下:

// 主线程中 const worker = wx.createWorker('workers/upload-worker.js'); worker.postMessage({ type: 'compress', filePath: tempFilePath }); worker.onMessage((res) => { if (res.type === 'compressed') { // 拿到压缩后的路径,继续上传流程 uploadToServer(res.compressedPath); } });

Worker方案需要注意的是:Worker文件也是打包体积的一份子,且不能直接使用wx.uploadFile。我这边是让Worker完成压缩,生成临时文件,再通过主线程的postMessage把路径传回,由主线程执行上传。这样既保证了不阻塞UI,又避开了Worker网络API限制。

4.7 后端跨域与Nginx部署实战

最后说一下V1.0.39的部署方案。我用Docker部署了整个前后端项目,前端静态资源打镜像,后端Node服务打镜像,用Docker Compose一键启动。Nginx负责反向代理和静态资源服务。

一个关键的Nginx配置示例:

server { listen 80; server_name api.yuluo.com; # 后端API反向代理 location /api/ { proxy_pass http://node-server:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 上传文件访问 location /uploads/ { proxy_pass http://node-server:3000/uploads/; } }

这里有一个细节:proxy_pass末尾的斜杠。如果写成proxy_pass http://node-server:3000;(不带斜杠),请求/api/user会被转发为/api/user;如果写成http://node-server:3000/,转发时会剥掉/api前缀,变成/user。这个区别直接影响接口路径匹配,很多跨域排查到最后发现是多个斜杠的问题,浪费了很多时间。

写在最后

做"榆落微时光"这个项目,从一开始的简单页面到V1.0.39的完整产品形态,我最大的体会是:小程序的坑不在于某个API有多难,而在于碎片化的环境兼容性和版本碎片化。

同一个API,在iOS和Android上表现不同;同一个组件,在基础库2.10和2.30上行为不同;同一个布局,在不同机型的刘海屏上像素级错乱。这些问题必须在项目开始前就做好心理建设,并且通过规范化的封装去屏蔽差异。

如果你也准备做一个小程序前后端分离项目,我的建议是:先把后端接口规范和前端请求层定好,再往上堆业务功能。另外,不要迷信最新的框架和工具,能稳定运行的旧方案,永远比新引入但没吃透的方案靠谱。

我后续打算把V1.0.39中使用的图表库从ECharts迁移到更轻量的Canvas自绘方案,进一步压缩分包体积。如果你也在做类似的小程序项目,遇到了前端或者后端的具体问题,欢迎在这篇文章底下留言交流,我看到都会回复。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询