在得物的小程序生态实践

一、前言

提起微信小程序,相信所有人都不陌生,下面这个典型使用场景你一定经历过:

餐馆落座——微信扫桌角小程序码——使用微信小程序点餐🍔

微信小程序(下文简称:小程序)作为一种在微信平台内运行的应用程序,用户无需前往应用商店下载安装包即可使用,可以在微信内被便捷地获取和传播,2017年一经推出便迅速成为热门技术关键词,得物也随即发布了得物App小程序,欢迎扫码体验:

七年时间过去了,小程序的周边配套已经十分成熟,微信官方对小程序生态进行了很多迭代——微信开发者工具从难用到可用、小程序API经历了多轮简化和拓展、数据分析能力逐渐完善,同时开源社区也贡献了非常多的开发框架、实践记录等。

得物内部也形成了自己的小程序开发生态,本文主要介绍一些得物App小程序版本迭代中形成的开发指南、实践经验等,给小程序新手开发者一些实践经验,如果你已经是个小程序开发高手了,那么欢迎交流指正我们做得好的/不好的部分。

事实上,“小程序”这种技术架构并非微信首创,但无疑微信小程序是目前生态建设最完整、用户量最大的小程序生态。

二、小程序运行机制

先简单介绍一下小程序的运行机制和架构设计。

小程序的架构设计初衷是“快”,同时又需要对展示内容做严格的安全管控,所以采用了Webview结合Native的Hybrid技术,设计了双线程模型架构:

渲染层:小程序界面由Webview渲染,一部分较复杂组件用客户端原生渲染,以提供更好的性能。

逻辑层:一个JavaScript沙箱环境(利用原生客户端系统的JavaScript的解释引擎创建),只执行有关小程序业务逻辑的代码,不能访问任何浏览器相关接口,以避免恶意代码运行:在运行时访问DOM树获取敏感数据、跳转到其他在线网页等。

上述渲染层和逻辑层只是上层的抽象概念,在不同运行环境下有各自技术实现,如下表:

小程序本质上是Web和Native的结合——成熟的Web渲染技术负责界面渲染、Native提供客户端原生API补充Web的短板;由于Web基于单线程模型且开放灵活,因此微信隔离了渲染层与逻辑层,以此作为对内容安全管控的有效控制手段。

目前小程序在渲染层上已经有了基于"Skyline渲染线程"的新型架构,减少了双线程架构之间的通信开销和内存占用,理论上拥有更好的性能,需要单独开启,可自行查阅相关文档。

三、开发阶段

从小程序的运行机制可以得知:小程序在开发、发布、运行等每个环节都依赖于微信自身的生态而非传统Web,所以有很多特有的设计。先介绍一些基础概念和知识:

用户端运行的小程序资源文件需要先上传到微信侧,然后才能推送到用户端,微信限制了资源体积大小:

  • 整个小程序所有分包大小不超过20M(开通虚拟支付后的小游戏不超过30M);
  • 单个分包/主包大小不能超过2M。

主包:小程序默认启动页面/TabBar页面的构建产物,以及一些所有分包都需用到公共资源/JS脚本;

分包:为了提高初始化加载速度,开发者可以划分以页面为维度的分包,分包只包含一些子级页面的代码。

跨平台框架选型

如果你的项目确实只需要运行在微信小程序平台,选用微信小程序原生开发方式或许是一个更好的选择——能随时接入微信小程序的最新特性和API,缺点就是不够灵活,如果日后还想要在别的平台开展相同的业务,需要额外开发工作。

更普遍的情况是,大多数开发者都选用跨端框架去开发小程序,毕竟程序员都喜欢 Write once, run anywhere,所以支持小程序端的跨平台框架在小程序刚推出的前几年如雨后春笋般层出不穷。

当然,截止到2024这个时间节点,其中很多框架都已经停止维护(比如remax、mpvue、wepy...),目前比较推荐的跨平台框架有:uni-app、Taro,两者异同比较:

一句话总结:喜欢写Vue的话用uni-app,喜欢写React用Taro,这两者在小程序平台上的表现来说都没有绝对的优势和劣势,社区活跃度都很高,时至今日都在持续更新维护中。

目前在得物内部,uni-app和Taro都有使用。

包体积优化

主包/分包配置

从前文中可以得知,微信限制了单个分包/主包大小不能超过2M,因此需要规划合理的目录,以uni-app的开发目录做示例:

├── ...
├── bin // 构建命令
├── loaders
├── src
│   ├── assets // 静态资源
│   ├── components // 通用组件
│   ├── pages // 主包目录
│   ├── product // product分包目录
│   ├── order // order分包目录
│   ├── ...
│   ├── sdk // 外部SDK
│   ├── store // 全局状态
│   ├── style // 样式文件
│   ├── utils // 通用方法
│   └── wxcomponents // 小程序原生组件
├── ...

小程序根目录下的app.json文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多tab等。(选用不同的跨平台框架会有不同的配置方式和语法,但是殊途同归,编译到小程序平台的配置文件都会遵从小程序规范,下文将用小程序原生语法做说明。)

需要额外注意的是,考虑到小程序有主包和分包的设计,将关联性较强的页面放在同一目录里可以更合理地配置分包,示例如下

// app.json
{// 主包页面"pages": ["pages/index/index","pages/xxxxx/index",],// 分包配置页面"subPackages": [{"root": "product","pages": ["xxxxx/index",]},],"window": {// 全局相关配置},"tabBar": {// tabBar相关配置}
}

即便是合理地配置了分包且做好了目录规划,也依然可能超过2M的体积限制,这个时候我们的优化手段跟Web项目基本相同,这里不再赘述,主要手段:静态资源从cdn加载、代码压缩、依赖优化分析等。

分仓开发

小程序的构建发布机制决定了所有页面都要一起打包、上传,在开发阶段也是如此。

我们曾经真实经历的开发流程:

  1. 打开IDE,打开项目代码;
  2. 运行微信平台构建命令:npm run mp-weixin;
  3. 运行字节平台构建命令:npm run mp-bytedance;
  4. 运行QQ平台构建命令:npm run mp-qq;
  5. 运行Web构建命令:npm run h5;
  6. 打开微信开发者工具、字节开发者工具、QQ开发者工具、Chrome浏览器,在不同工具中预览页面。

上古时期的噩梦

我们的小程序业务代码已经非常庞大,面对这样复杂的多线程开发流程,开发阶段的编译构建给研发电脑极大的内存压力,卡顿属实家常便饭。

为了能更高效地进行开发工作,我们利用Webpack的虚拟模块能力,结合私有npm包管理,将业务代码收敛进了各业务域的仓库内,做到了:

将一个完整的小程序项目,分割成多个能独立进行开发、部署的子应用(基于独立git仓库),同时又可以将所有子应用作为一个完整小程序应用打包发布。

时至今日,分仓开发在得物成为了“过去式”——由于后续的一波研发电脑大升级(唯快不破M2 Pro+力大砖飞32GB RAM),同时得物在QQ平台&字节平台的小程序也停止了迭代。只运行Web构建和小程序构建,并不会卡顿影响开发效率,所以目前已经不再需要分仓开发模式。

限于本文主题和篇幅,这里我们不再过多赘述分仓开发相关实现,有兴趣的话记得关注我们,后续可以整理一波技术文档以供方案参考~

提效工具

在Web中切换API环境有天然的域名隔离,可以直接访问不同域名下部署的站点。而在小程序中,像原生App一样,页面路径在用户端是无感且不能修改的,而且小程序没有安装包的概念,同一时间只存在一个体验版。所以为了更方便去调试和测试,可以做一些提效小工具。

API环境切换功能

在TabBar页面可以开发一个环境切换功能,例如:

  <view v-if="!IS_PRODUCTION" class="changeServiceEnv"><view class="changeTitle">环境切换</view><radio-group @change="radioChange"><radiov-for="item in ENV_Array":key="item":value="item":checked="item === SERVICE_ENV"class="radio-info">{{ item }}</radio></radio-group></view>
radioChange(e) {let { value } = e.detailthis.$store.commit('SET_SERVICE_ENV', value)uni.showToast({ title: `当前环境是${this.SERVICE_ENV}` })
}

这样就可以做到在单一体验版中自由切换API环境,验证不同环境下的数据展现和业务逻辑了。

DEV面板

在测试场景下,尝试访问路径较深的页面会比较耗时繁琐,和很多原生App的测试包做法一样,可以开发一个全局的DEV面板。

但是受限于小程序的架构设计:小程序每跳转到一个页面,实际上都是打开一个新的Webview,在这种设计架构下,虽然可以注册全局组件,但是如果想要在每个页面都渲染出全局组件,还是需要在每个页面都写一遍全局组件的代码,这样并不cool,我们探索出来的方案:

在非生产环境的Webpack配置中使用注入全局组件的loader:

  • 分析小程序页面配置,计算并得到路由表,这一步具体怎么实现跟选用的框架相关;
  • loader的上下文环境this.resourcePath指向真实的文件路径,将它和上一步拿到路由表进行匹配,如果未命中,则不做任何操作;
  • 分析命中路由表的文件,从中找到模版代码,紧随第一个标签,在其后方插入全局组件代码:
    • 这一步可以用正则,也可以用AST;
    • 对于我们的项目来说,在.vue文件的<template/>标签中查找第一个标签用正则很方便,所以我们直接正则替换。

关键代码:

// 全局loader主要代码
function modifyTemplateString(inputString, customTag) {// 查找 <template> 标签内容let templateStartif (inputString.indexOf('<template>') > -1) {templateStart = inputString.indexOf('<template>') + '<template>'.length}const templateEnd = inputString.indexOf('</template>')const templateContent = inputString.substring(templateStart, templateEnd).trim()let modifiedTemplateContent = ''// 在 <template> 第一个元素开头插入自定义标签modifiedTemplateContent = templateContent.replace(/(^\s*<\w+(?:-\w+)*\b(?:\s+(?:"[^"]*"|'[^']*'|[^>"])+)?\s*>)/, `$1\n${customTag}`)// 替换原始字符串中的 <template> 和 <script> 内容return inputString.replace(templateContent, () => modifiedTemplateContent)
}module.exports = function loader(source) {const relPath = path.relative(path.join(__dirname, '../', './src'), this.resourcePath)// <devPanel>是已经在全局中注册过的全局组件return modifyTemplateString(source, '<devPanel></devPanel>')
}

这样就能自动在所有页面渲染出全局DEV按钮组件了,可以更加方便地进行各种快捷操作,实现效果如下

自动化发布

小程序开发完成之后,微信开发者工具提供了上传入口,构建产物上传之后,需要到小程序后台再设置为体验版,如下图所示:

每个开发者都这样操作会造成后台系统上有很多的开发者版本,而且不同系统环境下的构建产物可能不一样,这样的工作流低效且不稳定,所以通过专门的机器执行构建,并将构建产物上传到微信服务器是更可靠的选择。

目前我们的发布工作流如下

1. 开发人员将代码合入指定分支后,会触发发布平台的持续部署任务,打包机拉取代码后执行命令:

// 打包机执行的命令
#!/usr/bin/env node
const shell = require('shelljs')
const signale = require('signale')
const { Signale } = signale
const ci = require('miniprogram-ci')async function main() {const interactive = new Signale({ interactive: true })interactive.pending(task)// 执行构建命令const result = shell.exec(`npm run build`)if (result.code !== 0) {// 如果构建失败了 退出interactive.error(task)process.exit(1)} else {const project = new ci.Project({type: 'miniProgram',projectPath: '/dist/dev/mp-weixin',ignores: ['node_modules/**/*'],})// 将构建产物上传至微信服务器ci.upload({project,}).then(res => {console.log('上传成功')// 通过IM通知相关测试/研发验证体验版小程序}).catch(err => {console.log('上传失败')interactive.error(task)process.exit(1)})}
}
main()

2. 打包并上传成功后,通过IM通知相关测试/研发验证体验版小程序:

miniprogram-ci是从微信开发者工具中抽离的关于小程序/小游戏项目代码的编译模块。

使用前需要使用小程序管理员身份访问"微信公众平台-开发-开发设置"后下载代码上传密钥,并配置IP白名单,才能进行上传、预览操作。

miniprogram-ci从1.0.28开始支持第三方平台开发的上传和预览,调用方式与普通开发模式无异。

采用自动化发布的优势

  • 节省手动操作的时间和精力;
  • 集成到CI/CD流程:可以集成到持续集成/持续部署(CI/CD)流程中,实现自动化构建和部署;
  • 可编程性:可以通过脚本编程控制上传代码的过程,实现定制化的部署流程。

四、发布后的数据分析

想要对小程序产生的数据进行精确化分析,除了自建监控和埋点,还可以从微信官方提供的“We分析”数据分析平台入手,我们从研发比较关心的两点做介绍:稳定性监控、JS错误分析。

稳定性监控

  • “性能数据”面板,可以看到当前小程序性能综合表现,也可以看到更详细的“白屏分析”、“网络请求分析”等:

  • “实时日志”面板,可以根据关键词查找小程序运行中产生的日志,以此排查业务逻辑等:

JS错误分析

“JS分析”面板,这里可以通过版本、时间等多个维度筛选微信记录的JS错误,通过错误堆栈信息可以定位到代码中的bug进行修复。

同样可以配置微信告警群,群里会定时push错误量的趋势,能够让开发者及时观测到新发布版本的代码bug。

五、总结思考

在小程序发布之初,很多开发者都不看好小程序。从技术视角来看,小程序确实带着非常多的debuff:闭源、充满限制、原生IDE丑、bug多。然而,如今看来,不论开发者是否接受这种与Web精神相悖的技术理念,也不妨碍它已经成为一种新的技术标准——目前市场上很多App都已建设了自己的小程序生态,如支付宝小程序、飞书小程序等,它们无一例外都参考了微信的技术架构和API设计。

尽管小程序在技术上存在诸多限制和缺陷,但其所带来的便利和商业机会无疑是巨大的。未来,随着技术的不断进步和生态的逐渐完善,小程序有望成为移动应用开发的重要范式之一,为用户和开发者创造更多价值。

同时,小程序的成功也提醒我们开发者,要不断关注和学习新技术,不断调整自己的思维和方法,以适应技术和市场的变化。

引用:

https://developers.weixin.qq.com/miniprogram/introduction/

https://segmentfault.com/a/1190000019131399

https://juejin.cn/post/7087041847700226062

https://developers.weixin.qq.com/ebook?action=get_post_info&docid=0000286f908988db00866b85f5640a

https://developers.weixin.qq.com/miniprogram/dev/framework/runtime/skyline/introduction.html

https://uniapp.dcloud.net.cn/

https://docs.taro.zone/docs/

https://www.npmjs.com/package/miniprogram-ci

*文/Zyqy 航飞

本文属得物技术原创,更多精彩文章请看:得物技术

未经得物技术许可严禁转载,否则依法追究法律责任!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/29226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端取不到cookie的的原因】http-only

某条cookie有http-only属性时&#xff0c;下面两种方法都取不到&#xff0c;还是改需求吧&#xff0c;别取了 1、 npm install js-cookie --save import Cookies from js-cookie let cookieValue Cookies.get(name)2、document.cookie

IAST面面观 | IAST强化越权检测能力,提升系统安全性

什么是越权漏洞 越权漏洞是一种常见的逻辑安全漏洞。越权漏洞指的是攻击者利用系统中的漏洞&#xff0c;获得超过其正常权限的访问权限&#xff0c;执行未授权操作。 越权漏洞主要分为两种类型&#xff1a;水平越权&#xff08;横向越权&#xff09;和垂直越权&#xff08;纵…

刷代码随想录有感(107):动态规划——01背包/最后一块石头的重量||

题干&#xff1a; 代码&#xff1a; class Solution { public:int lastStoneWeightII(vector<int>& stones) {vector<int>dp(15001, 0);int sum 0;for(int i : stones){sum i;}int target sum / 2;for(int i 0; i < stones.size(); i){for(int j targ…

AI + 3D:用单个图像和文本提示创建可交互的3D世界

你是否曾经梦想过只需一张照片和一些简单的文字描述,就能立即进入一个生动的3D虚拟世界?今天,我们将介绍一个革命性的技术,它就像是一台神奇的3D场景制造机,能够根据你的想象快速构建出令人惊叹的虚拟空间。 一、技术概览 这项技术不仅仅是一个简单的图像到3D的转换工具…

【免费API推荐】:轻松集成,为您的应用增添更多价值(9)

开发者喜爱的免费API是他们在开发过程中最宝贵的伙伴。这些API提供了丰富的功能和数据&#xff0c;帮助开发者构建出令人惊叹的应用。无论是地图服务、社交媒体集成、数据分析还是人工智能&#xff0c;这些免费API为开发者提供了强大的工具和资源&#xff0c;让他们能够更轻松地…

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读&#xff1a;【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了&#xff0c;本身是从后端慢慢步入全栈&#xff0c;对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

为什么选择住宅代理?IPXProxy住宅代理的优势

​在数字化时代&#xff0c;隐私和数据安全成为了每个互联网用户的关注焦点。住宅代理作为一种有效保护隐私的工具&#xff0c;因其独特的优势备受推崇。本文将从用户的角度&#xff0c;探讨选择住宅代理的诸多优势。 什么是住宅代理&#xff1f; 简单来说&#xff0c;住宅代理…

06眼动识别系统-改版

06眼动识别系统-改版 原先的模块组成示意图优缺点 新模块设计优缺点 软件方面结语其他以下是废话 试验&#xff0c;本身就是一个摸索的过程&#xff0c;在上一阶段的试验中&#xff0c;我们发现硬件的连接模式&#xff0c;给试验造成了很多麻烦&#xff0c;所以决定对硬件的连接…

leaflet室内地图\平面图点线面绘制

需求&#xff1a; 用户自定义上传一张平面图&#xff0c;然后可以在平面图内标点、绘制面、并且能够弹出相对应点、面的信息&#xff0c;信息可编辑&#xff0c;类似下图&#xff1a; 相关实现技术&#xff1a;leaflet 中文网&#xff1a;Leaflet - 一个交互式地图 JavaScript…

游戏运营与发行:从入门到实践

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

在有限的分数有限下如何抉择?是选好专业还是选好学校

随着2024年高考的落幕&#xff0c;无数考生和家长站在了人生的重要十字路口。面对成绩单上的数字&#xff0c;一个难题摆在了面前&#xff1a;在分数限制下我们该如何平衡“心仪的专业”与“知名度更高的学校”之间的选择&#xff1f; 一、专业决定未来职业走向 选择一个好的专…

基于51单片机的脉搏测量仪—心率计

基于51单片机的脉搏测量仪 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本系统由STC89C51/52单片机LCD1602显示模块5mm红外接收管LM358运放电路按键模块等构成 1.手指放到红外对管中&#xff0c;2…

Paragon NTFS For Mac 15软件下载_Paragon NTFS For Mac 15官网最新版下载

Paragon NTFS For Mac 15是一款强大的Mac读写工具。paragon ​​ntfs for mac​​​中文版为您轻松解决Mac不能识别 Windows NTFS文件难题&#xff0c;简单自如读写NTFS外置存储文件。在Mac OS X下全读/写访问NTFS的任何分区&#xff0c;paragon ntfs for mac中文版实现在Windo…

PostgreSQL源码分析——pg_control

pg_control为什么会存在&#xff1f; 为啥会有pg_control这么个文件呢&#xff1f; pg_control是PostgreSQL中一个很重要的文件&#xff0c;我们之前讲到过PostgreSQL的启动过程&#xff0c;启动过程中很重要的一项工作就是故障恢复&#xff0c;启动startup进程&#xff0c;回…

OpenSearch 与 Elasticsearch主要差异

1. 什么是 Elasticsearch&#xff1f; Elasticsearch 是一个基于 Apache Lucene 构建的开源、RESTful、分布式搜索和分析引擎。它旨在处理大量数据&#xff0c;使其成为日志和事件数据管理的流行选择。 Elasticsearch 还以其实时功能而闻名&#xff0c;允许用户在数据模式发生…

GO RACE 测试在低版本GCC上报错误 exit status 0xc0000139

windows机器环境&#xff0c;go程序使用race定位时一运行就报错&#xff0c;写了个example如&#xff1a; 能看到加了race之后就不行了&#xff0c; 搜了一下&#xff0c;git上有个issue&#xff1a; runtime: Race detector causes exit status 0xc0000139 on Windows 11 wi…

酷开会员 | 酷开系统将艺术、回忆与浪漫融入生活

随着审美观念的改变以及技术的提升&#xff0c;消费者对家用电视的需求已不局限于单纯的功能性&#xff0c;外观设计带来的美感与视觉效果也愈发成为消费者关注的焦点。在画质和功能逐步完善的当下&#xff0c;电视中的壁纸模式&#xff0c;则能让其更好地融入家居环境&#xf…

基于WPF技术的换热站智能监控系统17--项目总结

1、项目颜值&#xff0c;你打几分&#xff1f; 基于WPF技术的换热站智能监控系统01--项目创建-CSDN博客 基于WPF技术的换热站智能监控系统02--标题栏实现-CSDN博客 基于WPF技术的换热站智能监控系统03--实现左侧加载动画_wpf控制系统-CSDN博客 基于WPF技术的换热站智能监…

船舶能源新纪元:智能管理引领绿色航运潮流

在蓝色的大海上&#xff0c;无数船只乘风破浪&#xff0c;为全球的贸易和文化交流贡献着力量。然而&#xff0c;随着环保意识的提升和可持续发展的要求&#xff0c;船舶的能源消耗和排放问题逐渐成为了人们关注的焦点。在这个关键时刻&#xff0c;船舶能源管理系统应运而生&…

台球灯控计费系统安装教程,佳易王桌球房计费系统的安装方法教程

台球灯控计费系统安装教程&#xff0c;佳易王桌球房计费系统的安装方法教程 一、软件操作教程 以下软件操作教程以&#xff0c;佳易王台球计时计费管理软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、点击计时开灯&#xff0c;相应的灯…