- 请问小程序怎么实现分片上传视频?
使用chooseVideo获取到的只有临时路径,有什么办法能使用slice分割吗?File api貌似小程序也不支持
2023-07-07 - 微信小程序大文件上传,1G以上的文件,能分片吗?
如题 需要上传大的视频文件,直接上传到七牛云或者自己的服务器,接口文档没有分片的相关说明
2020-01-08 - miniprogram-file-uploader 可以选择视频进行上传吗?
https://developers.weixin.qq.com/miniprogram/dev/extended/component-plus/uploader.htmlminiprogram-file-uploader 该组件可以选择视频上传吗?我用开发工具调用该组件,只能进入相册选择图片
2020-10-19 - miniprogram-file-uploader组件秒传验证的使用方式?
miniprogram-file-uploader组件秒传验证的使用方式及达成的效果是秒速上传吗?
2023-02-28 - miniprogram-file-uploader 上传?
miniprogram-file-uploader 上传 uploadUrl 请求虽然是 post, 但参数都是在url上拼接的,data里面是一个 ArrayBuffer(), 这个后端要怎么接受?后端想要一个文件流,可以通过base64转吗?
2023-07-05 - 用miniprogram-file-uploader上传需要分片的文件卡在start upload?
使用miniprogram-file-uploader上传需要分片的文件卡在 start upload chunks,上传一个不需要分片的文件倒是可以上传成功。 这种情况只在真机调试的时候出现,在模拟器上上传完全没问题。 文件代码基本拷贝miniprogram-file-uploader代码仓库中的例子。 [图片] 这是真机调试的控制台信息截图 最开始的部分是使用这个控件进行图片上传,成功了,第二个部分是使用wx.upload上传一个9M多的视频也成功了,最后一个部分是使用这个控件进行视频上传,卡在这里不动了,并且右侧连接信息下面出现连接错误。 上传页面js代码 // pages/upload/upload.js // 文件上传 参考 https://github.com/wechat-miniprogram/miniprogram-file-uploader/tree/0c69766a4c5c4a2a6194c4f80479aabe39121c5e import Uploader from '../../miniprogram_npm/miniprogram-file-uploader/index' const app = getApp() const MB = 1024 * 1024 const HOST_IP = '192.168.31.27' const MERGE_URL = `http://${HOST_IP}:5001/Plugin/WeAppApi/upload/merge` const VERIFY_URL = `http://${HOST_IP}:5001/Plugin/WeAppApi/upload/verify` const UPLOAD_URL = `http://${HOST_IP}:5001/Plugin/WeAppApi/upload/upload` Page({ /** * 页面的初始数据 */ data: { progress: 0, uploadedSize: 0, averageSpeed: 0, timeRemaining: Number.POSITIVE_INFINITY, testChunks: false, url: `http://${HOST_IP}:5001/upload/211206161410.mp4` }, /** * 生命周期函数--监听页面加载 */ onLoad() { this.chunkSize = 5 * MB }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, onTestChunksChange(e) { const value = e.detail.value this.data.testChunks = value }, async chooseVideo() { this.reset() const { tempFilePath, size, } = await wx.chooseVideo({ sourceType: ['album','camera'], compressed: false }) console.log(tempFilePath) if (!Uploader.isSupport()) { wx.showToast({ title: '分片上传在 2.10.0 版本以上支持', icon: 'none', duration: 3000 }) return } const uploader = new Uploader({ tempFilePath, totalSize: size, fileName: tempFilePath, verifyUrl: VERIFY_URL, uploadUrl: UPLOAD_URL, mergeUrl: MERGE_URL, testChunks: this.data.testChunks, verbose: true }) uploader.on('retry', (res) => { console.log('retry', res.url) }) uploader.on('complete', (res) => { console.log('upload complete', res) }) uploader.on('success', (res) => { console.log('upload success', res) this.setData({ url: `http://${HOST_IP}:5001/${res.url}` }) }) uploader.on('fail', (res) => { console.log('upload fail', res) }) uploader.on('progress', (res) => { this.setData({ progress: res.progress, uploadedSize: parseInt(res.uploadedSize / 1024), averageSpeed: parseInt(res.averageSpeed / 1024), timeRemaining: res.timeRemaining }) }) uploader.upload() this.uploader = uploader }, reset() { this.setData({ progress: 0, uploadedSize: 0, averageSpeed: 0, timeRemaining: Number.POSITIVE_INFINITY, }) }, handleUpload() { this.uploader && this.uploader.upload() }, handlePause() { this.uploader && this.uploader.pause() }, handleResume() { this.uploader && this.uploader.resume() }, handleCancel() { this.uploader && this.uploader.cancel() } })
2021-12-13 - 生成微信太阳码填写RGB颜色生成出来的不是正确颜色太阳码
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.htmlhttps://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html line_color填写各类字段均无法正常生成黑色之外其他颜色的太阳码,产出太阳码均为橙色 希望知道生成其他颜色太阳码的参数应该怎么填写
2023-03-14 - 【记录】小程序地理位置获取:百度地图逆地理编码
近期学习小程序考虑到很多类型需要用到获取用户地理位置相关信息部分,在这里记录一下。 小程序开发文档有获取地理位置的api [图片] 只是这里获取到的是用户所在地区的经纬度,还需要再做进一步的改善,这里我使用的是百度地图开放平台的api 贴上链接地址:https://lbsyun.baidu.com 要使用百度地图的api需要经过以下流程: [图片] 获得ak才能使用百度地图api的相关服务,然后可以根据自己需要新建一个应用(可以选择小程序或web端),最终得到如下图所示: [图片] [图片] 只不过现在百度地图api文档有所变化,查找不到请求地址(估计版本有所变化),参考了一下csdn博客 https://blog.csdn.net/qq_30109365/article/details/98082346?ops_request_misc=&request_id=&biz_id=102&utm_term=%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BEapi%E9%80%86%E5%9C%B0%E7%90%86%E7%BC%96%E7%A0%81&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-98082346.nonecase&spm=1018.2226.3001.4187 附上小程序获取经纬度以及百度地图获取城市地址的代码 我在这里封装了一个函数,页面设计了一个按钮添加点击事件,点击即可获取地址信息 [图片] 随后可在控制台查看得到的结果: [图片] 还只是个初学小白,如果相关错误请多多指正😉
2021-11-23 - 百度地图的API在微信小程序体验版不显示,请问各路大神遇到过这样的问题嘞?
真机调试的时候没问题 [图片] 体验版就出了问题,一直不显示 [图片] 在体验版打开调试模式没问题 [图片]
2019-10-31 - 微信小程序原生map-地图定位
一、新建wxml文件-基础布局;(注意最好map标签外层再嵌套一层view) //eg:maplist.wxml //eg: maplist.js Page({ data: { latitude: '0', //首次加载维度 longitude: '0', //首次加载的经度 scale:16, mapName: "", //选点的位置 key:'地图key',//地图key address:'',//任务地址 authentication:'认证' }, 初始化经纬度为0时会加载不出来地图,页面会显示空白;为了预览一下地图效果咱们先打开百度搜索"腾讯地图API"; [图片] 打开服务端api; [图片] [图片] 拿到经度和纬度后先静态复制给小程序map的经纬度;这样在咱们就可以看到自己输入的位置了; [图片] 二、添加放大缩小按钮 + - wxss样式编写 /* pages/user/mapList/mapList.wxss */ map{ position: relative; } .telescoping-box{ width: 60rpx; height: 120rpx; text-align: center; background-color: #fff; -moz-box-shadow:2rpx 2rpx 20rpx #999; -webkit-box-shadow:2rpx 2rpx 20rpx #999; box-shadow:2rpx 2rpx 20rpx #999; position: absolute; left: 30rpx; bottom: 120rpx; border-radius: 10rpx; } .telescoping-box view{ margin-top: 10rpx; font-size: 35rpx; color: #999; } 添加点击事件 //按钮放大地图 scaleAdd(){ let scale = this.data.scale; if(this.data.scale>=20){ this.setData({ scale:20 }) }else{ scale++; this.setData({ scale:scale }) } }, //按钮缩小地图 scaleReduce(){ let scale = this.data.scale; if(this.data.scale<=3){ this.setData({ scale:3 }) }else{ scale--; this.setData({ scale:scale }) } }, scale缩放范围为:3-20 [图片] 三、点击标点按钮返回到当前位置 +- wxss样式编写 .cover-view{ width: 60rpx; height: 60rpx; position: absolute; right: 40rpx; bottom: 60rpx; } 添返回位置点击事件 controltap(e) { // 创建 map 上下文 MapContext 对象。建议使用 wx.createSelectorQuery 获取 context 对象 // 获取地图,map要与wxml页面的id名一致。注意:不需要#符号 let mpCtx = wx.createMapContext('myMap') // 将地图中心移置当前定位点,此时需设置地图组件 show-location 为true。'2.8.0' 起支持将地图中心移动到指定位置。 mpCtx.moveToLocation(); // 将地图缩放值改为初始值 this.setData({ scale: 16 }) }, regionChange(e) { // 获取地图 let mpCtx = wx.createMapContext('myMap') let that = this; // 判断是缩放,打印一下e,就能看到缩放值。注意:需真机测试 if (e.type == "end" && e.causedBy == "scale") { // 如果是缩放,获取房钱缩放值,并修改data中的scale属性(此处很关键) mpCtx.getScale({ success: function(res){ if (res.scale != this.data.scale) { // 如果缩放了 = 现在的缩放值和初始值不一样时,修改data中的scale值 that.setData({ scale: res.scale }) } } }) } }, [图片] 四、定位功能 申请腾讯接口key,注册登录后先点击控制台,其次点击应用管理,到我的应用菜单。如下图: [图片] [图片] 这步操作主要是调腾讯接口api逆地址解析,获取到经度和纬度后解析为坐标位置描述; [图片] [图片] /逆地址解析 getattrChange(){ let that = this; console.log(that.data.latitude); console.log(that.data.longitude); wx.request({ url: 'https://apis.map.qq.com/ws/geocoder/v1/?location='+that.data.latitude+','+that.data.longitude+'&key='+that.data.key+'&get_poi=1', header: { 'content-type': 'application/json' // 默认值 }, success (res) { console.log(res.data.result) if(res.data.result.formatted_addresses.recommend){ that.setData({ address:res.data.result.formatted_addresses.recommend }) }else{ that.setData({ address:res.data.result.address }) } } }) }, 重点来了,那咱们如何知道当前位置的经度和纬度呢?[图片] 1.申请wx.getLocation接口,这个接口精准度是最高的; [图片] 但这个接口不容易审核通过[图片],审核了十几次没通过我放弃了。。。 2.申请wx.getFuzzyLocation; 申请了一下wx.getFuzzyLocation模糊地理位置查询接口很顺利的审核通过,但误差不是一般的大[图片],也就放弃了; [图片] 3.百度地图api里面找找?[图片] [图片] 4.在高德地图api里面找找?[图片] 果然找到了,MMP[图片] [图片] 创建应用---生成秘钥key,生产环境建议用企业开发者申请; [图片] [图片] [图片] var amapFile = require('./amap-wx.130');//如:../../libs/amap-wx.js Page({ data: { longitude: '116.321175', //首次加载的经度 latitude: '39.993446', //首次加载维度 scale:16, } onLoad: function (options) { let that = this; //that.requestLocation(); var myAmapFun = new amapFile.AMapWX({key:this.data.gaokey}); myAmapFun.getRegeo({ success: function(data){ //成功回调 console.log(data) that.setData({ latitude: data[0].latitude, longitude: data[0].longitude, }) that.getattrChange(); }, fail: function(info){ //失败回调 console.log(info) } }) }, }) //app.json "requiredPrivateInfos":[ "getLocation" ], "permission": { "scope.userLocation": { "desc": "您的位置信息仅在小程序位置展示" }, "scope.userFuzzyLocation": { "desc": "您的位置信息仅在小程序位置展示" } }, 完美解决![图片]
2022-10-26 - 小程序性能优化实践
小程序性能优化课程基于实际开发场景,由资深开发者分享小程序性能优化的各项能力及应用实践,提升小程序性能表现,满足用户体验。
10-09 - Sentry 小程序 SDK
希望对你有所帮助和启发
2019-06-12 - 为何微信开发者工具会自动挂起?
[图片][图片] 这两个星期碰上好几次了,每次都只能关了重开。
2021-06-16 - 小程序用户头像昵称获取规则调整公告
更新时间:2022年11月9日由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称。 更新时间:2022年9月28日考虑到近期开发者对小程序用户头像昵称获取规则调整的相关反馈,平台将接口回收的截止时间由2022年10月25日延期至2022年11月8日24时。 调整背景在小程序内,开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录,支持开发者在多个小程序或其它应用间匿名关联同一用户。 同时,为了满足部分小程序业务中需要创建用户的昵称与头像的诉求,平台提供了 wx.getUserProfile 接口,支持在用户授权的前提下,快速使用自己的微信昵称头像。 但实践中发现有部分小程序,在用户刚打开小程序时就要求收集用户的微信昵称头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能。在已经获取用户的 openId 与 unionId 信息情况下,用户的微信昵称与头像并不是用户使用小程序的必要条件。为减少此类不合理的强迫授权情况,作出如下调整。 调整说明自 2022 年 10 月 25 日 24 时后(以下统称 “生效期” ),用户头像昵称获取规则将进行如下调整: 自生效期起,小程序 wx.getUserProfile 接口将被收回:生效期后发布的小程序新版本,通过 wx.getUserProfile 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。自生效期起,插件通过 wx.getUserInfo 接口获取用户昵称头像将被收回:生效期后发布的插件新版本,通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的插件版本不受影响,但如果要进行版本更新则需要进行适配。通过 wx.login 与 wx.getUserInfo 接口获取 openId、unionId 能力不受影响。「头像昵称填写能力」支持获取用户头像昵称:如业务需获取用户头像昵称,可以使用「头像昵称填写能力」(基础库 2.21.2 版本开始支持,覆盖iOS与安卓微信 8.0.16 以上版本),具体实践可见下方《最佳实践》。小程序 wx.getUserProfile 与插件 wx.getUserInfo 接口兼容基础库 2.27.1 以下版本的头像昵称获取需求:对于来自低版本的基础库与微信客户端的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称,开发者可继续使用以上能力做向下兼容。对于上述 3,wx.getUserProfile 接口、wx.getUserInfo 接口、头像昵称填写能力的基础库版本支持能力详细对比见下表: [图片] *针对低版本基础库,兼容处理可参考 兼容文档 请已使用 wx.getUserProfile 接口的小程序开发者和已使用 wx.getUserInfo 接口的插件开发者尽快适配。小游戏不受本次调整影响。 最佳实践小程序可在个人中心或设置等页面使用头像昵称填写能力让用户完善个人资料: [图片] 微信团队 2022年5月9日
2023-09-26 - 地理位置接口新增与相关流程调整
一、地理位置接口新增说明 由于精确地理位置接口只允许部分类目的小程序申请使用,为了满足开发者在更多场景使用地理位置接口,自 2022 年 7 月 14 日起,新增获取模糊地理位置接口(wx.getFuzzyLocation)。同时为保障用户合法权益,该接口调用前需进行准入开通申请,该接口准入规则与 wx.chooseLocation 一致。 wx.getFuzzyLocation 接口说明: 1、该接口返回的是经过模糊处理的经纬度坐标; 2、该接口支持返回 wgs84 或 gcj02 两种类型的坐标; 3、该接口需要用户授权 scope.userFuzzyLocation。 二、app.json 的配置指引 为了开发者能够正常使用获取模糊地理位置等接口,以及后续对于代码提审环节的优化(见「三、地理位置接口使用流程」),自 2022 年 7 月 14 日起,开发者在使用地理位置相关接口时(共计 8 个,见表1),需要提前在 app.json 中进行配置。 1、需配置的接口列表 [图片] 表1 2、配置规则 1)在代码中使用的地理位置相关接口(共计 8 个,见表1),开发者均需要在 app.json 中 requiredPrivateInfos 配置项中声明,代码格式如下: [图片] 2)表1中模糊位置信息(序号1)和精确位置信息(序号2-5)是互斥的,即声明了模糊位置信息就无法声明精确位置信息。若同时声明模糊位置信息和精确位置信息,则在编译代码时出现错误; 3)注意:自 2022 年 7 月 14 日后发布的小程序,如果未在 app.json 中声明表1中的相关接口,则小程序调用这些接口(表1)时会出现错误,在 2022 年 7 月 14 日之前发布的小程序不受影响; 4)对于第三方开发者,需要在上传代码时通过参数在 ext.json 中声明其需调用的地理位置相关接口,配置规则和普通小程序的配置规则相同。 三、地理位置接口使用流程 自 2022 年 7 月 14 日起,开发者如需在最新版本发布后使用地理位置相关接口,除需完成接口权限开通外,还需在 app.json(或ext.json)配置环节,具体如下: 1、接口权限开通 以下 8 个接口需完成准入开通流程:wx.getFuzzylocation、wx.getLocation、wx.onLocationChange、wx.chooseAddress、wx.choosePoi、wx.chooseLocation、wx.startLocationUpdate、wx.startLocationUpdateBackground 1)普通开发者:需要在 “小程序管理后台 -「开发」-「开发管理」-「接口设置」” 中完成权限申请; 2)第三方开发者:可通过 apply_privacy_interface 接口完成权限申请。 2、app.json(或 ext.json)配置 1)普通开发者:需在 app.json 中声明其需调用的地理位置相关接口,具体配置流程见「二、app.json 的配置指引」; 2)第三方开发者:需要在上传代码时通过参数在 ext.json 中声明其需调用的地理位置相关接口(配置方式:可通过 commit 接口配置)。 同时,为了提升开发者体验,平台在代码提审环节会协助开发者对地理位置接口进行检测,如检测出代码中包含未完成准入开通的地理位置接口,平台将再次提醒开发者确认是否需使用相关接口。 1)普通开发者:若无需使用,开发者可在提审时确认不使用该接口,即可正常进行代码提审。小程序审核通过且新版本发布完成后,平台将对小程序确认不使用的接口关闭使用权限; 2)第三方开发者:若无需使用,可在提审时通过参数声明不使用该接口(声明方式:可通过 submit_audit 接口配置),即可正常进行代码提审,审核通过后发布上线,将对其声明不使用的接口关闭使用权限。 以上调整将仅对所有小程序生效。 微信团队 2022年6月1日
2023-09-26 - 【实战记录】关于生成体验版小程序码在使用中容易遇到的问题
背景: 最近在社区中,发现一些帖子关于使用wxacode.getUnlimited时,不能生成体验版小程序码的,也有一些同学在下面回复说:“页面要发布到线上,才能设置体验版”类似这样的话,故在此想再关于生成体验版小程序码,再说明一下 操作说明: 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html 1、首先设置env_version 为 trial [图片] 2、若需生成的小程序码对应的路径,不存在线上版本的话,需要设置check_path为false [图片] 小结: 在该功能还没面世以前,测试过程中,有些需要扫码进入的场景,则必须在线上验证,有bug修改的话,则必须反复发版审核,比较耗时;该功能极大程度提升上线效率。这里也希望同步一下广大同学,可以放心的使用wxacode.getUnlimited来生成体验版小程序码,也没有什么需要页面发布到线上这么一说,撸就完了,有问题先仔细阅读下文档哦~
2022-06-22 - 【转】可以生成体验版小程序码啦
最近突然发现wxacode.getUnlimited可以生成体验版的小程序码了,设置env_version为trial即可,详细可见https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html,扫码进入小程序的场景再也不用等到线上再去验证了~
2022-05-06 - “小程序二维码”功能介绍与生成方式
产品简介:通过生成小程序二维码(又称太阳码或葵花码,后文简称小程序码),并将印有小程序码的物料铺设在线下场景,或通过线上分享等方式,引导用户扫码或长按识别二维码进入小程序,实现小程序引流;并可通过配置带参数的小程序码,监控各来源渠道的转化效果。 优势:低成本,易生成,易推广;用户习惯养成,扫码、识别码易用。 接入方式:普通小程序二维码无须开发,可在后台直接生成;带参数小程序码须开发。 关键词:小程序引流,数据跟踪与分析。 01 应用场景 在时尚零售行业,品牌可基于不同的业务场景,将小程序码印在商品、包装、宣传物料、门店展架等等,引导用户通过扫码快速进入小程序。 1)线下场景如: 将小程序码印在宣传物料上,引导用户扫码进入小程序; 将小程序码印到商品瓶身、包装、货架上,引导用户扫描进入小程序,享受扫码购服务; 将小程序码印在亚克力牌上,放置在店内如收银台等位置,引导用户扫描进入小程序,快速创建会员、填写服务问卷等。 2)线上场景如: 在小程序内提供个性化分享卡片的生成功能,用户可将卡片自主转发给好友,好友可长按识别卡片进入小程序,体验小程序内的商品购买、预约等服务。 02 生成方式 小程序码的生成有两种方式,分别为通过小程序后台生成链接统一的普通小程序码,以及通过开发生成带参数的小程序码。 1)普通小程序码: 我们推荐你通过小程序后台(mp.weixin.com)-设置-基本设置-小程序码及线下物料下载,完成小程序码的下载。 下载完成后,你可以将其打印并铺设到线下场景,或者直接附于海报中用于线上传播。 2)带参小程序码: 如须生成带参数的小程序码,为每个宣传物料配上独一无二的小程序码,智能跟踪来源于不同渠道的明细数据,可通过后台接口生成不限数量且永久有效的带参数小程序码。 开发指引内容较长,建议使用电脑详细查阅。点击打开文档 3)兼容普通二维码: 我们还提供了扫描普通二维码跳转小程序的能力。如线下已铺设有二维码,无须更换二维码,即可通过该能力在线下推广小程序。 开发指引内容较长,建议使用电脑详细查阅。点击打开文档 03 进阶应用-带参数码详细介绍 通过带参数二维码的灵活应用,可以监控各个渠道的用户来源、活动转化,调配资源提升营销运营效果,它的应用场景有: 1) 大数据营销: 在不同渠道投放不同参数的小程序码,可以精准记录客户来源,为营销决策提供依据。 2)线下助销: 通过给每个销售人员、每个店铺分配带有参数的小程序码进行佣金统计、计算销售奖励等。 3)一物一码: 让每个产品都拥有一个独一无二的小程序码,实现产品的差异化控制。
2020-01-14 - 微信小程序开发调用了微信支持的组件,开发扫描身份证功能,可以上架过审吗?
企业开发的微信小程序,用于公众服务。依据上级政府主管部门的要求,需要对用户身份证扫描登记。上架可以过审核吗?
2021-12-28 - JS代码的分包异步化
[视频] 你好,我是李艺。 上节课我们主要学习了主页中使用占位组件以及封面化的优化技巧,这节课我们学习JS代码的一个分包异步化。 首先我们看一下问题,小程序提供的分包异步化能力不仅针对组件代码,插件也可以异步化一言以蔽之,另一个分包内的一切,只要我们想使用,都可以通过异步加载的方式拿过来使用。 接下来我们看项目实践一 异步加载另一个代码包里面的JS。 在目前我们的index_addons分包里面可以创建一个get_nav_list.js这样的一个文件,将这个文件作为一个模块,提供getNavList这样的一个方法,稍后我们将调用这个方法获取导航的列表数据,在主页的JS文件里面,在周期函数onReady这个函数里面可以使用require.async方法异步加载,get_nav_list.js这个文件里面的代码,并且在加载完成以后去使用它,主页位于index代码包里面,而get_nav_list.js这个文件位于index_addons代码包里面,这是在一个代码包里面加载并使用另一个代码包里面的JS代码。 接下来我们看实践一的代码演示。 为了测试,首先我们要在一个代码包里面去创建一个JS文件,这个文件我们需要导出一个方法,就是getNavList,这个方法会给我们提供我们一个页面里面所需要的导航信息全部都是静态内容,不需要去后端然后加载接口,这个文件然后准备好了以后,接下来我们还需要在另外的一个文件里面,就是在index主页所在的代码包里面去加载我们的新添加的文件,并且去调用里面的导出的方法,这是我们要做的一个事情。 这是现在的项目所在的一个状态,刚才我们看到那个是最终的一个源码,现在我们先确认一下在我们当前的这个项目里面,刚才所说的文件它是不是存在,这个地方还没有,没有没关系,我们进行一个创建,这是名称,这个名字我们复制一下直接放在index_addons的目录的一个下面,将这个代码拷贝过来,接下来我们再看它的一个调用代码,查看一下在首页里面对它的一个调用。 在这个地方有一个测试分包中JS代码的异步化加载与执行,这个代码我们要放在这个onReady的最后面进行调用,代码已经放进来了,这个里边有两种方式,第一种方式,这是我们使用本身小程序它已经提供的一种方法就是require.async,然后给它一个相对地址,这个地址是我们在这个位置能访问到的,我们刚才创建的这样的一个文件,这个文件里面其实已经有了,在这个里面已经有这个文件了,我们把外边这个文件给它去掉,里边这已经有了,在components子目录下面去加载这个文件,加载完成以后,拿到以后,因为我们这个地方会有一个await,这个地方有一个async,拿到这个结果以后,这个地方有一个解构命名,把它命名为getNavList,因为在我们的文件里面用的语法是ESModule,就ES6的模块规范,它会有一个default导出,所以我们在这个地方要有一个结构命名,将default命名为getNavList。 这一步走完以后,接下来我们会调用它拿到NavList,拿到以后,将列表赋值给我们的data,data里面就这样的一个对象,赋值给它,代码已经搞完了 现在我们单击编译测试一下,已经显示了,在调试区我们可以看到分包异步化拿到了本地导航数据,其实就是在我们刚才这个代码里面的一个打印,说明它已经走到这一步了,我们navs因为不止在一个地方有设置,另外还有一个对后端接口的调用设置,所以即使我们后面不成功的话,前面它也是可以将导航信息进行设置的,这个代码演示就到这里。 下面我们看实践二 定义使用绝对路径的require和requireAsync方法。 分包异步化在用的时候,用到了require和require.async方法,它们的参数都不支持绝对路径,只支持相对路径,这个相对路径它不方便我们拷贝代码,如果我们在这个页面A里面写了一段模块引入的代码,想拷贝到页面B里面去使用,由于这两个页面它路径的深度可能是不一样的,我们直接拷贝这个代码,路径可能就会报错,使用绝对路径就没有这个问题了,为了解决这个问题,可以在这个项目的主代码文件,也就是app.js这个文件里面定义两个支持绝对路径的方法,代替默认的require以及require.async这两个方法,代替它们加载分包异步化的模块或者是普通模块。 有了这两个方法以后,在主页面的JS文件里面就可以使用另外的一种绝对路径加载另一个代码包里面的模块了,修改以后这个代码可以看到它们的作用是相同的,区别就是这个路径不太一样,但是这个地方有个问题我们需要注意一下,在使用require关键字的时候,有时候我们不能使用变量作为路径,很重要,有时候我们使用变量作为路径,可能会导致我们这个代码不能正常运行,而且这种情况下也没有任何的提示,所以这种错误很难发现。这个时候我们就需要老实一点,该使用相对路径就改用这个相对路径就可以了。 接下来我们看实践二的代码演示。 这两个方法我们需要写在我们程序的主文件里面,也就是app.js里面,为什么要写在这个地方,因为只有在这个文件下面取路径的时候才可以以绝对路径去取我们项目下的文件,因为本身这个文件就是在我们这个项目的根目录下,同时这个文件它也是我们小程序的一个入口文件,也是首先执行的,如果是你要做一些hack 一些劫持,最好放在这个文件下,这个地方有我们之前已经写好的代码,将这个代码可以反注释一下,一共是两个,一个是require,另外一个是requireAsync,在这个地方我们可以注意到,里面有关于path路径的一个设置,这个设置不要也可以 ,如果有的话可以让我们在这个路径里边以斜杠作为开头,如果你不用的话,那就是不要斜杠,去掉就可以了,这个方法现在已经有了。 接下来我们测试前面已经写的JS异步化的代码,找到我们这个代码,这个地方,然后将下面这个代码给它注掉,把上面这个代码给它打开,可以看到它们的区别,前面是一样的,await也是一样的,这个地方我们用getApp然后取到程序实例的一个引用调用它的requireAsync,就是异步去加载,这,可以加一个斜杠,用这个绝对地址,这个地址就是一个绝对地址,这种写法我们放在另外的一个文件里面其实也是适用的,因为它没有这种相对路径的一种烦恼,这个代码已经改完了,我们单击编译看一下它的运行效果。看到没有,分包异步化拿到了本地导航数据,说明我们已经执行完成了,但是刚才我们提到了,因为我们在这个方法的定义和使用过程当中是将它本身要用到的path以变量的形式提供了,这种方式可能会让我们的代码产生一些未知问题,所以为了保险起见,这两个方法我们暂时还是不用为好,你知道有这种用法就可以了。但有些项目的时候其实它还是可以使用的,有些不行,我们代码演示就到这里。 下面我们看实践三,项目插件化。 下面我们准备实现插件的里边的JS代码的一个分包异步化加载,在此之前我们需要在本地添加一个插件目录并且将我们这个项目改造为插件的开发模式,普通小程序项目像插件开发模式改造很简单,只需要创建一个plugin目录,然后修改这个项目的配置文件,将这个编译类型由原来的miniprogram改为plugin就可以了,完成以后我们还要记得重启项目,因为你如果不重启的话,这个项目配置文件可能会不生效。 有一点在这里我们需要注意,这个项目模式改变以后,在私有的项目配置文件,这个地方是私有的项目配置文件,不是我们前面的项目配置文件,它的名字是project.private.config.json,里边多了一个private,原来自定义的编译模式没有了。实际上它也不是没有,只是换了一个地方,由原来的condition/miniprogram这个节点移到了condition/plugin这个节点下面,它里面的配置信息其实是一样的,如果是我们想复用原来的那些编译模式的话,可以直接将这些设置信息拷贝过去就可以复用了。 除了可以在工具栏里面通过手动操作添加这些编译模式,直接修改私有的项目配置文件,前面我们提到的一样,重启项目也是可以达到同样的一个目的。在小程序这个项目里边一共有三个配置文件需要理清一下,第一个就是app.json,它是运行时的项目配置文件;第二个project.config.json,它属于开发配置;第三个project.private.config.json,它属于私有的项目开发配置,我们可以把它看作是我们前面的项目配置文件的一个补充,这三个文件里面只有app.json文件,会打包在我们最终的代码包里边,另外的两个项目配置文件则不会,修改完成以后重新导入项目,小程序就可以正常的运行了,下面我们看代码演示。 现在我们开始实践三的代码演示。 先明确一下我们目前的项目它的一个编译模式,打开项目配置文件可以看到这个地方有一个compileType等于miniprogram,现在我们将这个文件,将这个项目先关掉,因为如果我们不关掉的话,可能会影响它,这个地方也可以修改,比如说我们将这个直接改成插件模式,改完以后我们可以看到这个地方已经变化了,compileType等于plugin了,但是我们现在plugin的这个目录还没有,需要创建一个目录,在最终的源码里面,这个地方是有一个plugin目录,这是我们要使用的一个代码,我们将这个代码给它拷贝一下,当然我们在VSCode里面也可以直接拷贝,拷贝以后到我们这个目录里面去,这个是我们的一个现在正在使用的一个目录,然后放在这个地方,而这个文件其实就刚才我们在微信开发者工具里面看到的一个配置文件,其实它俩是一样的,这样已经有了。 如果要使用这个插件的话,还有一步就是我们需要一个引入,这个引入有全局引入还有代码包,某一个代码包的引入,两种方法都是可以的,接下来是为了测试这个插件的分包异步化,所以我们要把它放在某一个代码包里边,我们看一下最终的项目配置,这个里面还没有,我们需要的关于plugin的一个配置信息是不是没有,在这个index_addons里面,有这个信息,我们需要将这个信息放在我们的app.json,找到我们目前的index_addons代码包,然后放在这个地方,这个名字是自定义的,稍后我们会用到它,你换到另外的一个名字也是可以的,然后版本是dev代表的是开发模式,这个是我们当前的小程序账号,这个是我们导出的一个文件index.js,这个文件在我们plugin这个目录下面也是存在的,其实是这样的一个文件,这里面有一个getPluginVersion这样的一个方法,稍后我们会调用这个方法,这就完成了我们项目的一个插件化了。 现在我们重启一下,pluginRoot不能为空,我们看一下,出现了一个错误,它提示也太强了,就这样、保存、覆盖以后,我们要把我们这个项目重启一下,重新打开一下我们这个项目,让它可以再次读取我们这个项目配置文件,已经重新启动了,现在还在启动中,现在我们这个项目已经是插件的一个开发模式了,这个地方我们需要注意一下,这个地方在编译模式这个地方可以点开看一下,我们原来所有的那些自定义的编译模式都没有了,跑到哪里去了为什么没有了,它其实不是没有了是换了一个地方,就是我们这个地方,我们原来配置它这个节点,在miniprogram这个下面,这是我们定义的对不对,现在它这个节点变成了一个plugin,可以把这个给它改成这个 加一个这样 然后将这个里面 它不让我直接加,我就把这个项目关掉以后可以在VSCode里面直接修改,找到我们的当前的项目目录,在这个地方修改,然后把这个改一下将我们的list,所有的这些自定义的数据拷贝到这个地方,完成以后再打开我们微信开发者工具,再次打开我们这个项目,又启动了,看一下我们配置文件,添加的配置是不是还在,没关系还在。 看一下编译模式,这些编译信息又回来了,在我们改成这个插件模式以后,这些配置信息它只是换了一个地方,并没有本质上丢失,但是在这个地方我们有一个问题,稍后我们也会看到这个代码依赖分析,这个地方只有一个主包了,其他的分包信息都没了,而且主包大小也不对,显示358B,这个大小肯定是不对的,因为实际上我们现在这个项目里面有很多的代码分包都是存在的,这个代码演示就到这里。 下面我们看实践四,插件中JS代码的分包异步化。 我们将这个插件代码放入到plugin目录以后,这个目录下有一个主文件就是index.js,这个文件里面特意有一个导出的代码,它导出了一个名称为getPluginVersion的方法,这个方法是为我们下一步测试用的,在这个测试开始之前还需要在app.json配置文件里面,也就是在分包index_addons这个节点里面添加插件的引入信息,插件的引入可以全局的引入,也可以在某个代码包里面进行引入,在这里我们为了测试这个插件里面JS代码的分包异步化,所以要将它放在index_addons这个代码包里面,这是我们为了完成我们测试的需要,在配置完成以后接下来就可以在我们这个页面代码里面实现插件代码的一个分包异步化的一个加载了,本质上这种分包异步化跟我们前面的JS代码的分包异步化很像,它只是我们调用的这个方法不太一样,前面我们调用那个方法是require还有require.async,插件这个地方我们调用的是requirePlugin以及requirePlugin.async,它这个名称不太一样,另外它第一个参数也不一样,前面我们使用的是相对地址,在这个地方我们将要使用在配置文件里面自定义的插件的名称myPlugin,这个地方我们要注意一下,关于插件异步加载的这两个方法requirePlugin和requirePlugin.async,因为它们使用的是配置文件里边,我们已经定义好的插件名称,使用的不是路径,所以也没有必要再进行重写了,下面我们看代码演示。 现在我们开始实践四的代码演示。 首先现在我们要确认一下我们要使用的要加载的插件里面的代码,它位于plugin index.js这个文件里面,这个就是最终我们要调用那个方法,这个方法很简单,它只是返回一个版本号 接下来这个有了以后还需要确认在这个项目的配置文件里边,在这个代码包里面已经对它有了一个引入,对这个插件有了引入,同时插件名称也具备了 叫myPlugin,再往下就是我们要写测试代码,在主页的JS文件里边,在这个地方我们要加测试代码,看一下我们最终的代码,在主页的JS文件里面 在onReady下面这个地方,测试插件中JS代码的分包异步化,将这段代码拷贝一下放在这个地方。 这个地方我们注意其实这是两种调用方式,第一种是用回调的方式,将一个回调函数然后作为参数传递给它,然后第二种这个是另外的一种就是async这样的一种调用方式,当然这种方式我们还可以再进一步地再改变一下,比如说我们这个地方用立即执行函数,为什么要用立即执行函数稍后我们会细讲,因为我们现在这个测试代码位于我们小程序启动流程的一个主线上,为了不阻碍我们主线的一个执行,所以如果我们在这个上面去使用async关键字的话,必须把它放在一个安全的地方,相对安全的地方,这个地方我们就可以获取它的一个结果了,结果我们还可以做一个什么,它只是导出对吧,其实它这个地方是没有default的,等于它后面这个结果可以拿出来,放在下面,这个就可以去掉,但为了安全起见可以加一个catch,这种写法也是可以的。 上面这是另外一种写法,我们实现的功能是类似的,代码已经写完了,现在我们单击编译看一下它的运行效果,我这台电脑的配置不太可以,如果你们可以尽量要用高配置的电脑,因为我这个电脑在开了录屏以后明显感觉到开发者工具就比较卡,有时候风扇狂转,这个地方我们看到插件版本1,插件版本2 它都有一个版本的打印对不对,后面那个是我们通过这个方法调用取到的结果,这两种方式目前在我们这个地方都已经全部调用成功了,代码演示就到这里。 下面我们看实践五,去插件化解决静态依赖分析不显示的问题。 将项目改为插件模式以后影响的不仅是配置文件的内容,像我们前面看到关于编译模式配置,它节点信息就已经发生变化了,原来可以运行的静态分析,依赖分析这个工具也不太好用了,解决这个问题的关键就是我们可以去插件化,将我们这个项目重设为小程序的一个开发模式,如果这个项目里边真正的用到的这个插件的话,我们可以使用这个插件的非开发模式,也就是引用线上已经发布的一个公开插件,下面我们看代码演示。 下面看实践五的代码演示。 去插件化最保险的一个问题,就是我们要第一步先把我们微信开发者工具先给它关了,关了以后打开我们VSCode,VSCode里面plugin这个目录我们可以保留,只要我们不使用它就可以了,项目配置文件把编译类型给它改成miniprogram,改一下,这个不需要了,另外还有一个是我们关于插件的一个引入,插件的引入是在index_addons 在这个地方,这个也不需要了 删掉,还有一个我们页面里面主页JS文件里面,测试代码,在这个地方,测试代码为了方便你后续做测试,我们只是将它注释掉,你使用的时候只需要将它反注释就可以了,这个已经改完了,接下来我们再重新打开我们小程序项目,这个地方既然没有自动切换,我们手动把它给它切换过来,项目已经启动了。首先看一下编译模式,这些都还在又回来了,接下来我们再看一下文档管理器里面的静态依赖分析,现在我们看到这里面我们所有的分包也已经回来了,而且静态依赖分析这个文件现在也可以正常工作了,代码演示我们就说到这里。 最后我们总结一下,分包异步化既可以实现组件的异步加载也可以实现JS代码,插件中JS代码的一个异步加载,有了分包我们可以尽最大的努力将主包尽可能的缩小,将主包的加载时间降到最低,有了分包异步化,我们又可以在主包里面使用拆分至分包里面的这些组件JS代码以及插件里面的JS代码。这节课我们就讲到这里,现在我们屏幕上显示的是我们这节课涉及到的文档地址。 点击查看开放文档: 分包异步化 这节课我们主要学习了代码的分包异步化以及插件代码的分包异步化,下节课我们学习如何使用WebAssembly技术优化代码性能。 最后我们看一下思考题,这里有个问题请你思考一下,JS这门语言的解析执行效率一直被人诟病,在小程序开发里面,有没有可能用Go语言或者是其他的C C++等这些编译性语言编写某些逻辑代码,这个问题先留给你思考一下,下节课我们一起来深入探讨一下这个问题。
2022-07-14 - 小程序登录、用户信息相关接口调整说明
公告更新时间:2021年04月15日考虑到近期开发者对小程序登录、用户信息相关接口调整的相关反馈,为优化开发者调整接口的体验,回收wx.getUserInfo接口可获取用户授权的个人信息能力的截止时间由2021年4月13日调整至2021年4月28日24时。为优化用户的使用体验,平台将进行以下调整: 2021年2月23日起,若小程序已在微信开放平台进行绑定,则通过wx.login接口获取的登录凭证可直接换取unionID2021年4月28日24时后发布的小程序新版本,无法通过wx.getUserInfo与<button open-type="getUserInfo"/>获取用户个人信息(头像、昵称、性别与地区),将直接获取匿名数据(包括userInfo与encryptedData中的用户个人信息),获取加密后的openID与unionID数据的能力不做调整。此前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。新增getUserProfile接口(基础库2.10.4版本开始支持),可获取用户头像、昵称、性别及地区信息,开发者每次通过该接口获取用户个人信息均需用户确认。具体接口文档:《getUserProfile接口文档》由于getUserProfile接口从2.10.4版本基础库开始支持(覆盖微信7.0.9以上版本),考虑到开发者在低版本中有获取用户头像昵称的诉求,对于未支持getUserProfile的情况下,开发者可继续使用getUserInfo能力。开发者可参考getUserProfile接口文档中的示例代码进行适配。请使用了wx.getUserInfo接口或<button open-type="getUserInfo"/>的开发者尽快适配。开发者工具1.05.2103022版本开始支持getUserProfile接口调试,开发者可下载该版本进行改造。 小游戏不受本次调整影响。 一、调整背景很多开发者在打开小程序时就通过组件方式唤起getUserInfo弹窗,如果用户点击拒绝,无法使用小程序,这种做法打断了用户正常使用小程序的流程,同时也不利于小程序获取新用户。 二、调整说明通过wx.login接口获取的登录凭证可直接换取unionID 若小程序已在微信开放平台进行绑定,原wx.login接口获取的登录凭证若需换取unionID需满足以下条件: 如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用2月23日后,开发者调用wx.login获取的登录凭证可以直接换取unionID,无需满足以上条件。 回收wx.getUserInfo接口可获取用户个人信息能力 4月28日24时后发布的新版本小程序,开发者调用wx.getUserInfo或<button open-type="getUserInfo"/>将不再弹出弹窗,直接返回匿名的用户个人信息,获取加密后的openID、unionID数据的能力不做调整。 具体变化如下表: [图片] 即wx.getUserInfo接口的返回参数不变,但开发者获取的userInfo为匿名信息。 [图片] 此外,针对scope.userInfo将做如下调整: 若开发者调用wx.authorize接口请求scope.userInfo授权,用户侧不会触发授权弹框,直接返回授权成功若开发者调用wx.getSetting接口请求用户的授权状态,会直接读取到scope.userInfo为true新增getUserProfile接口 若开发者需要获取用户的个人信息(头像、昵称、性别与地区),可以通过wx.getUserProfile接口进行获取,该接口从基础库2.10.4版本开始支持,该接口只返回用户个人信息,不包含用户身份标识符。该接口中desc属性(声明获取用户个人信息后的用途)后续会展示在弹窗中,请开发者谨慎填写。开发者每次通过该接口获取用户个人信息均需用户确认,请开发者妥善保管用户快速填写的头像昵称,避免重复弹窗。 插件用户信息功能页 插件申请获取用户头像昵称与用户身份标识符仍保留功能页的形式,不作调整。用户在用户信息功能页中授权之后,插件就可以直接调用 wx.login 和 wx.getUserInfo 。 三、最佳实践调整后,开发者如需获取用户身份标识符只需要调用wx.login接口即可。 开发者若需要在界面中展示用户的头像昵称信息,可以通过<open-data>组件进行渲染,该组件无需用户确认,可以在界面中直接展示。 在部分场景(如社交类小程序)中,开发者需要在获取用户的头像昵称信息,可调用wx.getUserProfile接口,开发者每次通过该接口均需用户确认,请开发者妥善处理调用接口的时机,避免过度弹出弹窗骚扰用户。 微信团队 2021年4月15日
2021-04-15 - (21)独立分包与分包预下载
在「小程序 · 小故事」的第一期,我们曾和大家一起分享过「分包加载」的故事。随着小程序功能越来越多样,页面也越来越多,但不同页面的访问频率是有一定差异的。 分包加载允许开发者将小程序划分为主包和若干个分包,将较少用到的页面或功能划分到若干个分包中,主包内只保留最频繁使用的页面和公共的代码。小程序启动时默认只加载主包,再按需加载分包。这一机制保证了在小程序包大小增加的情况下,依然能保持良好的启动速度。 为满足小程序承载的功能不断丰富的需要,小程序的代码包大小上限已提高到 8M。随着小程序应用场景和使用范围的扩大,在实践中,我们发现分包加载仍有一定的局限性。尤其是越来越多的 H5 服务迁移到小程序后,对于小程序的启动速度有更高要求。为了更好的提升小程序的加载速度和使用体验,小程序近期开放了「独立分包」和「分包预下载」两个新的能力,进一步丰富了分包加载的功能和使用场景。 01独立分包 1 技术背景 由于技术实现的差异,小程序首次启动时需要进行代码包的下载,因此在启动性能上与网页相比有一定劣势。通过对小程序启动耗时的分析,我们发现代码包大小对小程序启动速度是有最直接的影响。 一方面,代码包越大,下载时间就越长; 另一方面,代码包越大,通常意味着小程序页面结构和代码逻辑复杂,启动时代码注入执行的时间越长。 采用分包加载一定程度上解决了代码包下载耗时过长的问题。但小程序中的某些场景(如广告页、活动页、支付页等),通常功能不是很复杂且相对独立,对启动性能有很高的要求。在现有方案中,启动这一页面需要依赖整个主包的下载,如果页面在分包中,还需等待分包的下载,启动性能有严重的瓶颈。此时如果依赖开发者进行代码重构,重新分包,不仅工作量大,而且会影响其他分包的使用体验。为了解决这一问题,我们提出了「独立分包」方案。 2 功能简介 独立分包是小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。 开发者可以将部分对启动性能要求很高的页面放到特殊的独立分包中。当小程序从独立分包页面启动时,只需要下载分包就可以直接运行,可以很大程度上提高分包页面的启动速度,实现小程序的秒开。 [图片] 由于小游戏中没有页面的概念,也没有小程序中多种入口的使用场景,因此小游戏目前没有支持独立分包。 3 配置方法 独立分包的配置方法十分简单,只需要在原有分包配置的基础上定义 independent 字段,即可将一个分包设置为独立分包,例如: [图片] 4 使用限制 独立分包虽然属于分包的一种,但其不依赖主包独立使用,因此在加载流程和运行环境上与普通分包相比有一些差异。除了分包本身的限制外,独立分包还有以下限制: ● 独立分包中不能依赖主包和其他分包中的内容,包括 js 文件、模板、wxss、自定义组件等; ● App 只能在主包内定义,独立分包中不能定义 App,会造成无法预期的行为; ● 独立分包中暂时不支持使用插件。 为了小程序有更好的使用体验,我们不建议开发者把过多的小程序逻辑放置到独立分包中,也不建议在小程序中过度的使用独立分包,例如把每个页面都放到一个独立分包中。 关于独立分包的详细内容请参见 独立分包 · 小程序 02 分包预下载 1 技术背景 在使用「分包加载」后,虽然能够显著提升小程序的启动速度,但是当用户在使用小程序过程中跳转到分包内页面时,需要等待分包下载完成后才能进入页面,造成页面切换的延迟,影响小程序的使用体验。分包预下载便是为了解决首次进入分包页面时的延迟问题而设计的。如果能够在用户进入分包页面之前就预先将分包下载完毕,那么进入分包页面的延迟就能够尽可能降低。 此前,小游戏中已经提供了「基于API」的分包预下载能力。在设计小程序分包预下载能力时,我们设计了「基于配置」和「基于API」两种分包预下载形式,「基于配置」的方式使用简单,且便于对预下载的使用情况进行控制,防止开发者滥用;「基于API」的方式使用起来更灵活,能够动态的调整预下载策略。综合考虑用户的使用感受和内测阶段第三方开发者的反馈后,我们最终决定首先推出「基于配置」的分包预下载能力。 2 功能简介 开发者可以预先配置某个页面可能会跳转到的分包(对于独立分包,也可以预下载主包),在进入小程序某个页面时,由基础库在后台自动预下载可能需要的分包。用户在进行页面跳转时,分包通常已经下载完成,不需要额外等待,可以有效提升进入后续分包页面时的启动速度。此外,考虑到用户的流量和存储空间,小程序也会对预下载的大小和网络进行一定的限制。 [图片] 3 配置方法 开发者可以通过在 app.json 中增加 preloadRule 字段,控制进入某个页面时进行预下载的分包,并设置触发预下载的网络环境。 [图片] [图片] 4 使用限制 对于手机用户而言,数据流量和存储空间是非常重要的资源。一方面,分包预下载能够提升小程序用户的使用体验;另一方面,过度的预下载也会破坏分包按需使用的原则,过度的占用用户的存储空间,消耗数据流量。如果开发者每次启动小程序时都将所有分包进行下载,会消耗很多不必要的流量和存储空间。 为了在分包预下载的效果和对用户资源的消耗上取得平衡,我们限制了同一个分包中的页面预下载总大小不得超过2M,并鼓励开发者按需设置分包预下载的网络条件。 关于独分包预下载详细内容请参见 分包预下载 · 小程序 03 小结 独立分包与分包预下载进一步丰富了分包加载的功能,大大拓展了分包加载的使用场景。同时,独立分包和分包预下载是相辅相成的,配合使用可以获得更好的效果。 例如,开发者可以将一个活动推广页放到一个独立分包中,利用独立分包的特性能够提升活动页面的加载速度,提升转化率。在页面中开发者可以引导有需要的用户跳转到小程序其他页面,使用小程序的更丰富的功能。在这一过程中,可以利用分包预下载能力,将主包或相关分包进行预下载,降低页面跳转的延迟,留住更多用户。 开发者在使用这两个新能力的过程中,如果遇到问题或者有什么建议,欢迎在微信开放社区(https://developers.weixin.qq.com)进行反馈,我们会根据开发者的反馈,不断的优化和丰富分包加载功能,减少功能限制,提升小程序的加载性能和使用体验。
2018-10-14 - 小程序内用户帐号登录规范调整和优化建议
为更好地保护用户隐私信息,优化用户体验,平台将会对小程序内的帐号登录功能进行规范。本公告所称“帐号登录功能”是指开发者在小程序内提供帐号登录功能,包括但不限于进行的手机号登录,getuserinfo形式登录、邮箱登录等形式。具体规范要求如下: 1.服务范围开放的小程序 对于用户注册流程是对外开放、无需验证特定范围用户,且注册后即可提供线上服务的小程序,不得在用户清楚知悉、了解小程序的功能之前,要求用户进行帐号登录。 包括但不限于打开小程序后立即跳转提示登录或打开小程序后立即强制弹窗要求登录,都属于违反上述要求的情况; 以下反面示例,在用户打开小程序后立刻弹出授权登录页; [图片] 建议修改为如下正面示例形式:在体验小程序功能后,用户主动点击登录按钮后触发登录流程,且为用户提供暂不登录选项。 [图片] 2.服务范围特定的小程序 对于客观上服务范围特定、未完全开放用户注册,需通过更多方式完成身份验证后才能提供服务的小程序,可以直接引导用户进行帐号登录。例如为学校系统、员工系统、社保卡信息系统等提供服务的小程序; 下图案例为正面示例:校友管理系统,符合规范要求。 [图片] 3.仅提供注册功能小程序 对于线上仅提供注册功能,其他服务均需以其他方式提供的小程序,可在说明要求使用帐号登录功能的原因后,引导用户进行帐号注册或帐号登录。如ETC注册申请、信用卡申请; 如下反面示例,用户在进入时未获取任何信息,首页直接强制弹框要求登录注册ETC,这是不符合规范的。 [图片] 建议修改为如下正面示例所示形式:允许在首页说明注册功能后,提供登录或注册按钮供用户主动选择点击登录。 [图片] 4.提供可取消或拒绝登录选项 任何小程序调用帐号登录功能,应当为用户清晰提供可取消或拒绝的选项按钮,不得以任何方式强制用户进行帐号登录。 如下图所示反面示例,到需要登录环节直接跳转登录页面,用户只能选择点击登录或退出小程序,这不符合登录规范要求。 [图片] 建议修改为下图正面示例形式,在需帐号登录的环节,为用户主动点击登录,并提供可取消按钮,不强制登录。 [图片] 针对以上登录规范要求,平台希望开发者们能相应地调整小程序的帐号登录功能。如未满足登录规范要求,从2019年9月1日开始,平台将会在后续的代码审核环节进行规则提示和修改要求反馈。
2019-07-20 - 小程序帐号登录规范要求与修改指引
为更好地保护用户隐私信息,优化用户体验,平台对小程序内的帐号登录功能进行规范。“帐号登录功能”是指开发者在小程序内提供帐号登录功能,包括但不限于进行的手机号登录,getuserinfo形式登录、邮箱登录等形式。一、登录规范规则,你需要了解:[图片] 一、「体验范围开放」与「体验范围特定」区分与对应整改建议:1、“体验范围开放”定义:①直接打开即可体验 ②有账号限制,但有注册流程是对外开放 整改建议: ①授权个人信息功能后置,给与用户充分了解、体验功能服务后,再由用户主动点击进一步功能触发登录授权 ②授权同时,亦同时支持给与用户取消登录的权利 案例解析: ①范围开放-登录规范违规案例解析 违规点:服务范围开放,首页打开即要求授权登录,用户未体验功能服务强制要求授权登录,登录规范不合规。 [图片] ②范围开放-登录环节无取消/拒绝登录按钮案例解析 违规点:体验范围开放,用户体验功能服务后自主触发登录,提供取消/拒绝登录按钮,但点击取消/拒绝登录按钮无响应,仍强制要求登录,无法取消/拒绝登录。 [图片] 2、体验范围特定 定义: 体验范围提供给特定人员使用、对外无开放注册流程,例如为学校系统、员工系统、社保卡信息系统等提供特定服务的小程序 整改建议: ①首页有明显的使用范围(特定范围)说明 ②首页即要求授权来拉取身份鉴定类,需要为用户提供暂不登录/取消登录选项按钮 案例解析: ①特定范围-登录违规案例解析 违规点:打开首页即要求授权登录,无任何说明,不符合登录规范要求 [图片] 这是一份动态更新的文档,辅助开发者了解登录规范要求,避免开发者因登录规范问题审核失败导致无法按期发布上线,开发者如有其他疑问,可以通过目前开放的咨询渠道反馈: 1、微信开放社区-交流专区-小程序发帖咨询-提出问题-运营相关问题 2、驳回站内信通知-客服咨询入口(MP代码审核客服入口正处于灰度开放中,若未获得灰度测试入口,开发者可前往社区发帖咨询) 我们会根据新出现的问题、相关法律法规更新或产品运营的需要及时对其内容进行修改并更新,制定新的规则,保证微信用户的体验。建议开发者反复查看以便获得最新信息,定期了解更新情况。
2020-12-24 - wx.getUserProfile不能和wx.login一起使用?
mac 模拟器1.05.2102010 基础库2.16.0 调用wx.login获取code后,再调用wx.getUserProfile,可能会失败,触发fail函数,error msg: ''getUserProfile:fail can only be invoked by user TAP gesture"。 如果不能同时使用,那如何校验用户信息的准确性或者解密encryptedData呢?
2021-04-08 - 微信小程序三种授权登录的方式
经过一段时间对微信小程序的研发后 总结出以下三种授权登录的方式,我给他们命名为‘一次性授权’‘永久授权’‘不授权’ 1.一次性授权 常规写法,需要获取用户公开信息(头像,昵称等)时,判断调取授权登录接口,但是此方法如果不经处理的话 用户如果拒绝授权或者删除该微信小程序后 需要重新调取并获取用户公开信息(头像,昵称等),此方法用户体验较差,不建议使用; 2.永久授权 在不必要使用用户公开信息(头像,昵称等)时,不调取授权登录接口,只有在必要的时候再去判断调取授权登录接口并把获取到的用户公开信息存入数据库,这样在每次登录时直接先运行指定函数从数据库索取需要的用户公开信息(头像,昵称等)即可,此方法在删除小程序后不用再次去授权登录(因为在用户第一次授权登录时已经把用户的公开信息存入数据库了以后直接向数据库索取即可),建议使用; 3.不授权 不需要授权登录获取用户公开信息(头像,昵称等),使用wx.login获取用户code并传入后台,后台可以通过用户的code值向微信要一个值(具体需要问后台,我只是个小前端,后台的东西不是很懂,只是知道一些逻辑而且也已经成功实现)然后通过这个用code换取的值就可以识别到指定用户,如果需要的话,前端要显示的头像、昵称等这些信息可以使用自定义可编辑的功能,当然,也可以通过<open-data type=“userAvatarUrl”></open-data><open-data type=“userNickName”></open-data>小程序提供的这个组件显示用户的头像及昵称(不过这个组件只有显示功能),用户如果想直接使用自己的头像昵称,也可以自行授权(比如添加个引导按钮什么之类的),建议使用; [图片][图片] 文中使用的微信自带接口、组件及函数: <open-data type=“userAvatarUrl”></open-data> <open-data type=“userNickName”></open-data> wx.login({ success(res){ console.log(res.code) } }) 微信授权登录 以上三种方式可以灵活运用,也可以把需要的结合到一起,并不冲突; 当然,大佬很多,我也只是个小前端而已,第一次发表技术方面的帖子,希望互相学习,互相指导,如有说的不对的地方还望大佬们及时指出!!! 谢谢
2019-04-18 - 获取用户信息方案介绍
背景 小程序一个比较重要的能力就是获取用户信息,也就是使用 [代码]wx.getUserInfo[代码] 接口。我们发现几乎所有的小程序都会调用这个接口。虽然我们在设计文档上有提出最好的设计是在真正要用户信息的情况下才去获取用户信息,不过很多开发者并没有按照我们的期望去做,导致用户在使用的时候有很多困扰。 归结起来有几点: 开发者在首页直接调用 [代码]wx.getUserInfo[代码] 进行授权,弹框有会使得一部分用户放弃小程序的使用。 开发者没有处理用户拒绝弹框的情况,有部分小程序强制要求用户授权头像昵称等信息才能继续使用小程序。 用户没有很好的方式重新授权,虽然在前几个版本我们增加了[代码]设置[代码]页面可以让用户选择重新授权,但是操作还是不够便捷。 开发者希望进到首页就获取到用户的[代码]unionId[代码],以便和之前已经关注了公众号的用户画像关联起来。 开发者默认将 [代码]wx.login[代码] 和 [代码]wx.getUserInfo[代码] 绑定使用,这个是由于我们一开始的设计缺陷和实例代码导致: [代码]getUserInfo[代码]必须通过[代码]wx.login[代码] 在后台生成[代码]session_key[代码] 后才能调用。 为了解决以上几点,我们更新了三个能力: 使用组件来获取用户信息,用户拒绝授权后也可以重新弹窗再次授权 若用户满足一定条件(下文有详细介绍),则可以用[代码]wx.login[代码] 获取到的code直接换到[代码]unionId[代码] [代码]wx.getUserInfo[代码] 不依赖 [代码]wx.login[代码] 就能调用得到数据。 获取用户信息组件介绍[代码][代码] 组件变化: [代码]open-type[代码] 属性增加 [代码]getUserInfo[代码] :用户点击时候会触发 [代码]bindgetuserinfo[代码] 事件。 新增事件 [代码]bindgetuserinfo[代码] :当 [代码]open-type[代码] 为 [代码]getUserInfo[代码] 时,用户点击会触发。可以从事件返回参数的[代码]detail[代码]字段中获取到和[代码]wx.getUserInfo[代码] 返回参数相同的数据。 示例: [代码]<[代码][代码]button[代码] [代码]open-type[代码][代码]=[代码][代码]"getUserInfo"[代码] [代码]bindgetuserinfo[代码][代码]=[代码][代码]"userInfoHandler"[代码][代码]> Click me </[代码][代码]button[代码][代码]>[代码]和 [代码]wx.getUserInfo[代码] 不同之处在于: API [代码]wx.getUserInfo[代码] 只会弹一次框,用户拒绝授权之后,再次调用将不会弹框 组件 [代码][代码][代码][代码] 由于是用户主动触发,不受弹框次数限制,只要用户没有授权,都会再次弹框 直接获取unionId考虑很多场景下,业务方申请userinfo授权主要为了获取unionid。我们鼓励开发者在不骚扰用户的情况下合理获得unionid,而仅在必要时才向用户弹窗申请使用昵称头像。为此,凡使用“获取用户信息组件”获取用户昵称头像的小程序,在满足以下全部条件时,将可以静默获得unionid。 在微信开放平台下存在同主体的App、公众号、小程序。 用户关注了某个相同主体公众号,或曾经在某个相同主体App、公众号上进行过微信登录授权。 getUserInfo 和 login很多开发者会把login和getUserInfo捆绑调用当成登录使用,其实login已经可以完成登录,可以建立账号体系了,getUserInfo只是获取额外的用户信息。 在login获取到code,然后发送到开发者后端,开发者后端再通过接口去微信后端换取到openid和sessionKey(并且现在会将unionid也一并返回)之后,然后把3rd_session返回给前端,就已经完成登录行为。而login行为是静默,不必授权的,不会对用户造成骚扰。 getUserInfo只是为了提供更优质的服务而存在,比如展示头像昵称,判断性别,通过unionId和其他公众号上已有的用户画像结合起来提供历史数据。所以不必在刚刚进入小程序的时候就强制要求授权。 推荐使用方法调用[代码]wx.login[代码] 获取[代码]code[代码],然后从微信后端换取到[代码]sessionKey[代码],用于解密[代码]getUserInfo[代码]返回的敏感数据。 使用[代码]wx.getSetting[代码] 获取用户的授权情况 如果用户已经授权,直接调用 API [代码]wx.getUserInfo[代码] 获取用户最新的信息 用户未授权,在界面中显示一个按钮提示用户登入,当用户点击并授权后就获取到用户的最新信息。 获取到用户数据后可以进行展示或者发送给自己的后端。 文档中的quickStart已经更新 特别注意为了给用户提供更好的小程序环境,我们约定在一段时间后(具体时间会做通知),若还出现以下情况(包括但不限于),将无法通过审核 初次打开小程序就弹框授权用户信息 未处理用户拒绝授权的情况 强制要求用户授权 已经上线的小程序不会受到影响。 FAQ Q: 除了 UserInfo 呢,比如说位置信息 --- ’风の诺言 . A: 其他授权信息不像用户信息那么高频繁,也基本是在使用时候才申请授权,所以没有同 UserInfo 一起给出。我们会先看看 UserInfo 的使用情况再结合具体场景我们会给出相应的方案 Q: 后台要维护用户信息 --- Azleal 我们的小程序业务是功能都需要授权才能使用的(也就是必须拿到unionid获取用户信息) --- elemeNT 我在小程序与服务号的数据需要互通,通过unionId来确定用户的唯一性,如果在用户进入小程序后不强制他授权,单凭一个openid来存储他的用户数据,在用户下次从服务号进入时。不就会产生重复数据吗?就没做到数据互通了 --- ﺭ并向你吐了趴口水ﺭ五年. 另外看到官方提到 要强制推行,我想说我们目前所有用户是通过unionid注册的。那么这些用户就不得不使用 openid重新登录 、注册一遍。更重要的是,之前他们的相关数据都会对应不上(因为你们也不允许强制用户登录授权) --- 羊毛 现在这种方案,不能满足我们的需求,我们的小程序,必须一进入就要获取他的信息,然后加载他的数据; --- 韩文 A: 调用`wx.login`已经可以获取到用户的登录态,已经可以做用户账号的管理。 UserInfo 中带的 UnionId 是额外的信息,没有它完全可以完成登录 对于需要和开发平台绑定的业务进行数据互通的情况,一个新用户进来没有互通数据的情况下也是可以体验到所有业务,那么对于没有授权unionId的用户,可以将其当成是新用户,当真正授权unionId之后再做绑定完全是可以的 Q: 我需要确保用户的唯一性,这样就必须取unionID,否则用户删除了小程序,或者换了设备, 下次再进来这个小程序,该用什么来区分是上次来过的用户呢?? --- WEI+ A: 如果你本身没有其他公众号、App、小程序,那么也就没必要拿到unionid,因为unionid是打通你在开放平台下所有应用的标识 如果只有一个小程序,用 openid 足以, openid 是一个用户对于一个小程序的标识,永远不变 Q: wx.getUserInfo 是网络请求,如果使用了 open-type = "getUserInfo",是否每次点击都会调接口? --- SouthernBox A: 是的,open-type="getUserInfo" 的作用以及内部实现基本和 wx.getUserInfo 一样 区别是一个开发者主动(拒绝一次不再弹窗),一个是用户主动(拒绝任意次都可以重新弹窗) Q: 比如有一个创建按钮,用户点击一次授权了,我已经获取到用户信息,再次点击就没必要再调用 getUserInfo 去网络请求了。 --- SouthernBox A: 可以参考文中 quickStart 的做法,如果已经授权了,那就可以把按钮隐藏,之后的授权直接用API wx.getUserInfo 调用(因为已经授权,所以也不会弹窗),用户也不会再点了 Q: 小程序是不是必须要用微信自带的授权才可以登录 ,能否不使用授权方式登录,用自己系统的api接口数据实现?这个会不会涉及到审核不过的问题??麻烦解答一下 谢谢了。 --- WEI+ A: 自己做登录不会涉及到审核问题。 不过不建议在没有原有账号体系的情况下让用户在小程序内注册,过重的行为会损失用户。 Q: 在小程序中有一个"我的"页面,这是属于会员页,如果用户要进入这个页面就必须授权。交互方式就是在用户未授权情况下整个页面只显示一个授权获取用户信息的button 按钮,这个需要用户自己去触发,算不算强制授权? --- ﺭ并向你吐了趴口水ﺭ五年. A: 强制授权是说如果用户如果不授权基本信息,连最基础的浏览功能都不提供(当然这个也是要分具体的业务场景,不会限制得太死板) 可以有更好的交互,参考下主流App,在未登录的时候点击【我的】页面,也不会直接要求登录,而是展示了一定的页面结构,同时给一个登录按钮(例如【携程】【京东】等),之后再在这个页面做操作的话可以弹一个登录页面或按钮提示用户登录是完全可以的。 上述所说的登录只是用户感知上的登录,从业务逻辑上用户其实在 wx.login 的时候已经完成登录了。 Q: 看了很多评论,有些人还是不知道为什么官方要这样做,我作为一个商家角度来说下。 --- Mr.J 1. 比如我们要做一些户外推广的二唯码,用户只看到了你的图片宣传单,扫描二唯码一打开就提示“需要获取你的个人信息,您是否允许”,你不要当自己是开发者当自己是一个正常人,看到这个提示我相信很多人的第一反应就是拒绝。如果第一步已经把你拒之门外,谈何营销? 2. 没有小程序之前,我们在公众号有很多用户,都绑定了unionid,有小程序之后我们考虑怎么让用户接受小程序,可以静默登录我觉得非常好,从公众号过来的用户可以直接就登录了,没有任何提示,完美的对接,这是一个很好的体验。 A: 说得很好,我们的这些改造不仅是为了开发者,同时也是为了这个生态下的用户考虑。希望开发者们也能站在用户的角度去思考怎么做一个产品。 Q: 我不明白为什么login 给多个unionid 为什么不行? unionid也不能算是个人信息吧,给多个unionid可以更方便开发者,而且很多情况下就不用调用getUserInfo了 --- candyTong 我们提个建议,能否直接开放unionid呢?这样也许会有许多小程序不需要再弹窗了。既一定程度保障了用户体验,也照顾到了我们开发者的体验。 --- 羊毛 A: 如果直接开放了unionid,就会出现这种情况:当你作为一个用户进入一个小程序,这个小程序并没要求你授权就直接把你的头像昵称显示出来(它之前把unionId对应的头像昵称都存了下来),但是这个小程序主体(open平台主体和公众平台主体并不相同)相关的任何一个应用你从来没用过,你会不会觉得很奇怪并且很不舒服,觉得自己在微信内的用户信息没有丝毫的保障? Q: 那有推荐的比较好的例子么?对于必须使用用户头像、昵称这些信息的小程序而言 --- 亚里士朱德 A: 首先,没有什么逻辑是一定要使用用户的头像、昵称才能work的。对于这个case,完全可以先用默认头像、匿名昵称先做替代,用户点击默认头像后就可以弹出授权信息,非常的水到渠成。 Q: 之前看了这个帖子一直在思考,如果是一进去需要回去用户的地理位置信息显示到地图上的呢?这样算不算是一进去就弹窗授权获取用户信息? --- 吴俊绩🤔 A: 地图的情况和获取用户信息不同,我们目前还没对地图的授权请求有所调整。当前不受上述策略的影响 Q: 对于开发者而言,小程序与公众号是同级的,只是不同的入口 但是这样的设计,公众号与小程序成了主从关系咯 --- log琥珀① A: 并无什么主从关系,只是多一个渠道让开发者可以更方便的获取到已经是该主体下用户的unionId
2017-08-07 - IOS应用程序打开小程序出现奇怪问题,怎么解决?
APP打开小程序,安卓的没有问题,IOS出现“由于应用universal link”校验不通过。 奇怪的是,如果APP先调用分享功能后,打开小程序没有问题 打开小程序代码 WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object]; launchMiniProgramReq.userName = self.adInfoXML.AdSAppId; //拉起的小程序的username launchMiniProgramReq.path = self.adInfoXML.AdSAppUrl; //拉起小程序页面的可带参路径,不填默认拉起小程序首页,对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"。 launchMiniProgramReq.miniProgramType = 0; //拉起小程序的类型 [WXApi sendReq:launchMiniProgramReq completion:nil];
2021-11-13 - 微信开放平台App iOS端接入新版本SDK 常见问题自查指引
整理iOS开发者在接入新版本(1.8.6.1及以上版本)SDK经常遇到的几个问题及解决方案,方便开发者正确接入能力: App更新微信1.8.6.1版本SDK后出现“正在连接”的提示?Universal Link校验不通过/接入新SDK,跳到微信后再回跳App,流程就中止?
2020-03-05 - 小程序奇技淫巧之 -- 日志能力
日志与反馈 前端开发在进行某个问题定位的时候,日志是很重要的。因为机器兼容性问题、环境问题等,我们常常无法复现用户的一些bug。而微信官方也提供了较完整的日志能力,我们一起来看一下。 用户反馈 小程序官方提供了用户反馈携带日志的能力,大概流程是: 开发中日志打印,使用日志管理器实例 LogManager。 用户在使用过程中,可以在小程序的 profile 页面(【右上角胶囊】-【关于xxxx】),点击【投诉与反馈】-【功能异常】(旧版本还需要勾选上传日志),则可以上传日志。 在小程序管理后台,【管理】-【反馈管理】,就可以查看上传的日志(还包括了很详细的用户和机型版本等信息)。 这个入口可能对于用户来说过于深入(是的,官方也发现这个问题了,所以后面有了实时日志),我们小程序也可以通过[代码]button[代码]组件,设置[代码]openType[代码]为[代码]feedback[代码],然后用户点击按钮就可以直接拉起意见反馈页面了。利用这个能力,我们可以监听用户截屏的操作,然后弹出浮层引导用户主动进行反馈。 [代码]<view class="dialog" wx:if="{{isFeedbackShow}}"> <view>是否遇到问题?</view> <button open-type="feedback">点击反馈</button> </view> wx.onUserCaptureScreen(() => { // 设置弹窗出现 this.setData({isFeedbackShow: true}) }); [代码] LogManager 关于小程序的 LogManager,大概是非常实用又特别低调的一个能力了。它的使用方式其实和 console 很相似,提供了 log、info、debug、warn 等日志方式。 [代码]const logger = wx.getLogManager() logger.log({str: 'hello world'}, 'basic log', 100, [1, 2, 3]) logger.info({str: 'hello world'}, 'info log', 100, [1, 2, 3]) logger.debug({str: 'hello world'}, 'debug log', 100, [1, 2, 3]) logger.warn({str: 'hello world'}, 'warn log', 100, [1, 2, 3]) [代码] 打印的日志,从管理后台下载下来之后,也是很好懂: [代码]2019-6-25 22:11:6 [log] wx.setStorageSync api invoke 2019-6-25 22:11:6 [log] wx.setStorageSync return 2019-6-25 22:11:6 [log] wx.setStorageSync api invoke 2019-6-25 22:11:6 [log] wx.setStorageSync return 2019-6-25 22:11:6 [log] [v1.1.0] request begin 2019-6-25 22:11:6 [log] wx.request api invoke with seq 0 2019-6-25 22:11:6 [log] wx.request success callback with msg request:ok with seq 0 2019-6-25 22:11:6 [log] [v1.1.0] request done 2019-6-25 22:11:7 [log] wx.navigateTo api invoke 2019-6-25 22:11:7 [log] page packquery/pages/index/index onHide have been invoked 2019-6-25 22:11:7 [log] page packquery/pages/logs/logs onLoad have been invoked 2019-6-25 22:11:7 [log] [v1.1.0] logs | onShow | | [] 2019-6-25 22:11:7 [log] wx.setStorageSync api invoke 2019-6-25 22:11:7 [log] wx.setStorageSync return 2019-6-25 22:11:7 [log] wx.reportMonitor api invoke 2019-6-25 22:11:7 [log] page packquery/pages/logs/logs onShow have been invoked 2019-6-25 22:11:7 [log] wx.navigateTo success callback with msg navigateTo:ok [代码] LogManager 最多保存 5M 的日志内容,超过5M后,旧的日志内容会被删除。基础库默认会把 App、Page 的生命周期函数和 wx 命名空间下的函数调用写入日志,基础库的日志帮助我们定位具体哪些地方出了问题。 实时日志 小程序的 LogManager 有一个很大的痛点,就是必须依赖用户上报,入口又是右上角胶囊-【关于xxxx】-【投诉与反馈】-【功能异常】这么长的路径,甚至用户的反馈过程也会经常丢失日志,导致无法查问题。 为帮助小程序开发者快捷地排查小程序漏洞、定位问题,微信推出了实时日志功能。从基础库 2.7.1 开始,开发者可通过提供的接口打印日志,日志汇聚并实时上报到小程序后台。 使用方式如下: 使用 wx.getRealtimeLogManager 在代码⾥⾯打⽇志。 可从小程序管理后台【开发】-【运维中心】-【实时日志】进入日志查询页面,查看开发者打印的日志信息。 开发者可通过设置时间、微信号/OpenID、页面链接、FilterMsg内容(基础库2.7.3及以上支持setFilterMsg)等筛选条件查询指定用户的日志信息: [图片] 由于后台资源限制,实时日志使用规则如下: 为了定位问题方便,日志是按页面划分的,某一个页面,在onShow到onHide(切换到其它页面、右上角圆点退到后台)之间打的日志,会聚合成一条日志上报,并且在小程序管理后台上可以根据页面路径搜索出该条日志。 每个小程序账号每天限制500万条日志,日志会保留7天,建议遇到问题及时定位。 一条日志的上限是5KB,最多包含200次打印日志函数调用(info、warn、error调用都算),所以要谨慎打日志,避免在循环里面调用打日志接口,避免直接重写console.log的方式打日志。 意见反馈里面的日志,可根据OpenID搜索日志。 setFilterMsg 可以设置过滤的 Msg。这个接口的目的是提供某个场景的过滤能力,例如[代码]setFilterMsg('scene1')[代码],则在 MP 上可输入 scene1 查询得到该条日志。比如上线过程中,某个监控有问题,可以根据 FilterMsg 过滤这个场景下的具体的用户日志。FilterMsg 仅支持大小写字母。如果需要添加多个关键字,建议使用 addFilterMsg 替代 setFilterMsg。 日志开发技巧 既然官方提供了 LogManager 和实时日志,我们当然是两个都要用啦。 log.js 我们将所有日志的能力都封装在一起,暴露一个通用的接口给调用方使用: [代码]// log.js const VERSION = "0.0.1"; // 业务代码版本号,用户灰度过程中观察问题 const canIUseLogManage = wx.canIUse("getLogManager"); const logger = canIUseLogManage ? wx.getLogManager({level: 0}) : null; var realtimeLogger = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null; /** * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function DEBUG(file, ...args) { console.debug(file, " | ", ...args); if (canIUseLogManage) { logger!.debug(`[${VERSION}]`, file, " | ", ...args); } realtimeLogger && realtimeLogger.info(`[${VERSION}]`, file, " | ", ...args); } /** * * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function RUN(file, ...args) { console.log(file, " | ", ...args); if (canIUseLogManage) { logger!.log(`[${VERSION}]`, file, " | ", ...args); } realtimeLogger && realtimeLogger.info(`[${VERSION}]`, file, " | ", ...args); } /** * * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function ERROR(file, ...args) { console.error(file, " | ", ...args); if (canIUseLogManage) { logger!.warn(`[${VERSION}]`, file, " | ", ...args); } if (realtimeLogger) { realtimeLogger.error(`[${VERSION}]`, file, " | ", ...args); // 判断是否支持设置模糊搜索 // 错误的信息可记录到 FilterMsg,方便搜索定位 if (realtimeLogger.addFilterMsg) { try { realtimeLogger.addFilterMsg( `[${VERSION}] ${file} ${JSON.stringify(args)}` ); } catch (e) { realtimeLogger.addFilterMsg(`[${VERSION}] ${file}`); } } } } // 方便将页面名字自动打印 export function getLogger(fileName: string) { return { DEBUG: function(...args) { DEBUG(fileName, ...args); }, RUN: function(...args) { RUN(fileName, ...args); }, ERROR: function(...args) { ERROR(fileName, ...args); } }; } [代码] 通过这样的方式,我们在一个页面中使用日志的时候,可以这么使用: [代码]import { getLogger } from "./log"; const PAGE_MANE = "page_name"; const logger = getLogger(PAGE_MANE); [代码] autolog-behavior 现在有了日志组件,我们需要在足够多的地方记录日志,才能在问题出现的时候及时进行定位。一般来说,我们需要在每个方法在被调用的时候都打印一个日志,所以这里封装了一个 autolog-behavior 的方式,每个页面(需要是 Component 方式)中只需要引入这个 behavior,就可以在每个方法调用的时候,打印日志: [代码]// autolog-behavior.js import * as Log from "../utils/log"; /** * 本 Behavior 会在小程序 methods 中每个方法调用前添加一个 Log 说明 * 需要在 Component 的 data 属性中添加 PAGE_NAME,用于描述当前页面 */ export default Behavior({ definitionFilter(defFields) { // 获取定义的方法 Object.keys(defFields.methods || {}).forEach(methodName => { const originMethod = defFields.methods![methodName]; // 遍历更新每个方法 defFields.methods![methodName] = function(ev, ...args) { if (ev && ev.target && ev.currentTarget && ev.currentTarget.dataset) { // 如果是事件类型,则只需要记录 dataset 数据 Log.RUN(defFields.data.PAGE_NAME, `${methodName} invoke, event dataset = `, ev.currentTarget.dataset, "params = ", ...args); } else { // 其他情况下,则都记录日志 Log.RUN( defFields.data.PAGE_NAME, `${methodName} invoke, params = `, ev, ...args); } // 触发原有的方法 originMethod.call(this, ev, ...args); }; }); } }); [代码] 我们能看到,日志打印依赖了页面中定义了一个[代码]PAGE_NAME[代码]的 data 数据,所以我们在使用的时候可以这么处理: [代码]import { getLogger } from "../../utils/log"; import autologBehavior from "../../behaviors/autolog-behavior"; const PAGE_NAME = "page_name"; const logger = getLogger(PAGE_NAME); Component({ behaviors: [autologBehavior], data: { PAGE_NAME, // 其他数据 }, methods: { // 定义的方法会在调用的时候自动打印日志 } }); [代码] 页面如何使用 Behavior 看看官方文档:事实上,小程序的页面也可以视为自定义组件。因而,页面也可以使用[代码]Component[代码]构造器构造,拥有与普通组件一样的定义段与实例方法。但此时要求对应[代码]json[代码]文件中包含[代码]usingComponents[代码]定义段。 完整的项目可以参考wxapp-typescript-demo。 参考 LogManager 实时日志 Component构造器 behaviors 结束语 使用自定义组件的方式来写页面,有特别多好用的技巧,behavior 就是其中一个比较重要的能力,大家可以发挥自己的想象力来实现很多奇妙的功能。
2019-12-10 - 为什么用微信开发者工具“真机调试”没问题,但是发布后就不正常?
为什么用微信开发者工具“真机调试”没问题,但是发布后就不正常? 真机调试是可以访问后台的,后台已经改为https协议并测试过没问题。另外在代码发布的时候提示:以下文件体积超过500KB,已经跳过压缩以及ES6转ES5处理,如在该文件有使用到ES6特性,请使用其他工具转换成ES5或压缩,否则可能会在低版本上设备运行有风险:utils/encoding-indexes.js
2020-04-28