关于h5页面:IOS系统下开启键盘后顶部输入框掉下来了

通过初步排查,发现几个景象: 1 只在页面总长度超过屏幕长度时产生。2 只在开启键盘时产生。3 只在固定定位的页面顶部输入框获取焦点(focus)时产生。4 只在屏幕有滚动时产生。缺点有两个景象: 1 顶部DOM掉下来了,在大概屏幕两头的地位。2 此时如果持续滚动屏幕,顶部DOM不会再维持以后地位。也就是说,它“进入”了页面的文档流。咱们初步判断是顶部DOM失去了固定定位,起因未知。怎么解决呢? 咱们决定绕过这个问题,只有看起来是失常的就行。 当点击顶部DOM输入框、调出键盘的时候: 1 页面滚回到顶部;2 屏幕滚动时,敞开IOS输出面板。要害代码如下: $("#search_value").on("focus", function() { $(window).scrollTop(0) }) window.ontouchmove = function() { $('input').blur(); };

September 1, 2023 · 1 min · jiezi

关于h5页面:H5开屏从龟速到闪电企微是如何做到的

导读|H5开屏龟速常是令开发者头疼的问题。腾讯企业微信团队对该景象进行剖析优化,最终H5开屏耗时130ms,达到秒开成果!企微前端开发工程师陈智仁将分享可用可扩大的Hybird H5秒开计划。该团队应用离线包解决了资源申请耗时的问题,在这个根底上通过耗时剖析找到瓶颈环节,进一步采纳“预热”进行优化提速以解决了WebView初始化、数据预拉取、js执行(app初始化)耗时的问题。心愿这些通用办法对你有帮忙。 背景 服务端渲染(SSR)是Web支流的性能优化伎俩。SSR直出相比传统的SPA利用加载渲染躲避了首屏拉取数据和资源申请的网络往返耗时。团队针对Web开发也曾经反对了SSR能力。近期出于动态化经营的思考,咱们抉择了Web开发,同时咱们也接到了晋升体验的诉求。 以企业微信要开发的页面为例:采纳SSR计划,从用户点击到首屏渲染的耗时均值约600ms,白屏工夫的存在是能够感知到的。为了尽可能打消白屏达到秒开成果,咱们尝试做更多摸索。 计划思路 1) 计划选型如何实现页面秒开呢?从最直观的渲染链路来动手剖析。下图列出了从用户点击到看到首屏渲染可交互,一个SPA利用次要环节的加载流程。咱们调研了业内相干计划,从渲染链路的视角来看下常见计划的优化思路。 传统离线包在加载渲染过程中,网络IO是很显著的一个耗时瓶颈。传统的离线包计划思路很间接,如果网络耗时那就将资源离线,很好地解决了资源申请的耗时。用Service Worker也能达到离线包的成果,同时也是Web规范。首次渲染优化个别须要联合客户端配置预启动脚本来达到缓存资源的成果。 SSRSSR则从另外的角度登程,在申请页面的时候就进行服务端数据拉取和页面直出,首屏得以在一个网络往返就能够展现,无效地躲避了后续须要期待css/js资源加载、数据拉取的工夫。性能体验有比拟大的晋升,在BFF遍及的状况下开发模式简略,很受欢迎。 公司内相干工作思考到WebView的初始化(冷启动/ 二次启动)、页面网络申请、首屏数据接口的耗时,白屏工夫还是可感知地存在的。以咱们要开发的页面为例采纳SSR首屏耗时均值~600ms,可交互工夫均值~1100ms。如何进一步打消白屏?这里为各位介绍公司内外针对h5首屏性能优化的优良计划。 手Q团队的VasSonic是集大成者,次要思路是采纳WebView和数据预拉取并行的形式。这套计划须要客户端和服务端采纳指定协定革新接入,开发时也有肯定的革新工作。 微信游戏团队次要思路是利用jsCore做客户端预渲染,用户点击后间接上屏。这个办法也达到了很好的成果,首屏FCP工夫从1664ms升高到了411ms。 咱们做了一个简要的计划比照,能够看到每个计划都针对渲染链路的某个或多个环节做了优化,其中VasSonic的成果比较显著。不过联合企业微信业务理论状况,咱们列出了如下几点思考: 首先,接入对客户端和服务端有肯定的革新老本,业务开发也有肯定的革新工作。其次,咱们曾经有一套的对立公布平台,心愿能复用这套公布能力。最初,性能上有没有进一步优化的空间呢?业务需要对体验上的要求是心愿达到更好的性能成果或者说尽可能齐全地打消白屏 基于以上思考,咱们在上述计划的根底上做了进一步的实际摸索,以冀望达到更好的性能成果。 2)计划架构 为了达到尽可能齐全打消白屏,咱们还是从初始问题登程,联合渲染链路进行剖析,思路上针对每个环节采取对应的优化办法。 每个环节的优化在具体落地时会存在着计划的利弊取舍。比方预拉取数据个别的思路是交给客户端来做,然而存在着客户端申请和h5申请两套机制(鉴权、申请通道等方面)如何协调的问题。在渲染链路剖析时,如果业务的js执行也奉献了不少耗时,有没有可能从通用根底计划的角度来解决这个问题,同时也能缩小业务对性能优化的关注?这是个值得各位思考摸索的问题。具体的内容会在前面开展来说。 如图展现了计划的优化思路和主流程。计划应用离线包解决了资源申请耗时的问题,在这个根底上通过耗时剖析找到瓶颈环节,进一步采纳预热的思路进行优化提速,解决了WebView初始化、数据预拉取、js执行(app初始化)耗时的问题,最终达到了现实的性能体验。 图1 上屏流程 图2 计划架构 上面咱们具体介绍下计划,包含:离线包技术、预热提速和进一步的优化工作。 离线包减速 为了躲避资源申请耗时,咱们应用了离线包技术。离线包技术是比拟成熟的计划,相干打包、公布拉取的计划这里不多说了,次要说下计划中一些设计上的考量。 1)加载流程 咱们通过offid作为离线包利用的标识,fallback机制保障离线资源不可达时用户也能够失常拜访页面,通过离线包预拉取和异步检测更新机制进步了离线包命中率,尽可能打消了网络资源加载的耗时。 2)fallback机制因为用户网络情况的不确定性,离线包加载可能存在失败的状况。为了保障可用性,咱们确定了离线包加载不阻塞渲染的思路。当用户点击入口url,对应offid离线包在本地不存在时,会fallback申请现网页面,同时异步加载离线包。所以咱们针对离线包的打包构造,依照现网URL path来组织资源门路。这样客户端申请拦挡解决也会比拟不便,不须要了解映射规定。当发现离线包不匹配资源时,放过申请透到现网即可。如图展现了咱们的离线包构造示例。 3. 离线包生命周期为了进步离线包命中率,咱们会配置一些机会(e.g.入口曝光)来预拉取离线包。 离线包的更新机制:客户端加载时依据offid检测到本地离线包的存在,则间接应用拉起,同时启动异步版本检测和更新。如果新包版本号大于本地版本号则更新缓存,同时公布平台也反对辨别测试环境、正式环境以及按条件灰度。 上了离线包后,能够看到页面的首屏耗时均值从基准无优化的1340ms降到了963ms,离线包的预拉取和更新策略则使离线包命中率达到了95%。首屏耗时失去了肯定的升高,但也还有比拟大的优化空间,须要更一步的剖析优化。 预热提速 通过离线包的减速,咱们解决了资源申请耗时的问题,不过从整个渲染链路来看还有很大的优化空间,咱们做了具体的耗时剖析,找出耗时瓶颈,针对耗时环节做了进一步的优化提速。 1)耗时剖析离线包技术躲避了资源申请耗时,然而从整个渲染链路来看还有很大的优化空间,咱们做了耗时剖析如下。 Hybird利用中,WebView初始化是比拟耗时的环节,这里咱们针对iOS WebView做了测试。 数据拉取方面,不同入口页面的耗时不一,某些入口页面比拟重的接口耗时超过了1s。 此外,咱们发现js执行也奉献了不少耗时。以某入口页面为例,框架初始化工夫~10ms,app初始化工夫~440ms。 2)渲染链路预热提速预热流程咱们的指标是打消白屏,这里现实的计划是找到一种和业务无关的通用解法。计划的次要思路是预热,把能提前做的都做了。预热是不是就是把WebView提前创立进去就好了呢?不是的,这里的预热波及到多个渲染环节的优化组合。如图展现了预热的整体流程,上面一个个来解。 2)WebView预创立为了打消WebView的耗时,咱们采取了全局的预创立WebView,机会为配置入口曝光。不过全局复用预热WebView不可避免地会引入可能的业务内存泄露问题,下文会介绍对应的躲避计划。 数据预拉取数据拉取是页面渲染的一个耗时环节。为了打消数据预拉取耗时,在预创立WebView阶段咱们同时进行了数据预拉取。 数据预拉取常见的思路是交给客户端来做,然而存在着客户端申请和h5申请两套机制如何协调的问题,以申请鉴权为例,存在以下的问题: 第一,Web团队本身有一层node BFF,实现了相应的数据拉取业务逻辑,而客户端则走的公有协定通道申请C++后盾,二者是不同的鉴权机制。 第二,如果交给客户端来做,能够接入HTTP申请这套机制,革新老本比拟大,如果复用原有通道,则一份数据业务逻辑须要两套实现。 如何设计一套通用可扩大的计划?咱们心愿做到客户端只关注容器的能力(预热、资源拦挡等),屏蔽掉更深刻的对Web的感知,这样的解耦能够无效管制计划的复杂度。因而,这里咱们针对离线包配置项减少了preUrl字段,使客户端保护更通用的能力,数据预拉取交给业务团队来做,具体如下: 第一,客户端:拉取某个离线包配置项时会读取该字段,同时针对以后曝光的入口url可能存在多个有着不同的数据需要,这里会进行收集,将曝光url中的业务key参数拼接到preUrl来初始化WebView,这些作为通用能力。 第二,业务:preUrl页面在加载时会拉取相应的业务数据存到localStorage,理论的数据预拉取申请放到业务方发动,也能够很好地兼容已有的技术栈。 JS预执行很靠近指标了,最初js执行的耗时能不能打消呢?首先来看下440ms的耗时具体在哪里,通过剖析看到,框架初始化仅须要不到10ms的工夫,而真正的大头在业务代码的执行,其中代码编译耗时~80ms,其余的都是业务app初始化执行工夫,这个是业务自身复杂度造成的。 咱们首先思考了创立两个WebView的计划,一个负责加载preUrl预拉取数据,另一个负责loadUrl上屏,这样设计上比拟简洁强壮,不过实际下来发现成果不现实,如图展现了该计划的成果,渲染不稳固能够感知到白屏的存在。在曾经有了预拉取数据和离线资源的状况下,实践上用户点击后须要期待的就只有渲染这块的耗时,理论咱们发现在简单利用初始化时存在js执行耗时较大的问题。 ...

December 19, 2022 · 1 min · jiezi

关于h5页面:公众号项目报错xxxfail-the-permission-value-is-offline-verifying

获取地位信息时报错:公众号我的项目中应用微信JS-SDK,获取地位信息时,在微信开发者工具中调试时报以下谬误:getLocation:fail, the permission value is offline verifying 尽管在线上环境中没有问题,但开发环境还是受影像的。 解决办法在开发者工具地址栏拜访以下地址: https://www.weixinsxy.com/jssdk/ 拜访后果如图所示: 受权 点击须要的权限,点击受权,而后再拜访本地的开发地址进行测试,会提醒受权,点击确认解决问题。

August 9, 2022 · 1 min · jiezi

关于h5页面:利用canvas绘制时钟

window.onload = function () { var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 绘制圆盘 function clock() { //绘制圆盘 context.beginPath(); context.arc(300, 300, 200, 0, Math.PI * 2); context.fillStyle = 'pink'; context.fill(); context.closePath(); //绘制时刻度 for (i = 0; i < 12; i++) { context.save(); context.lineWidth = 4; context.beginPath(); //将原点平移300,300 context.translate(300, 300); context.rotate(i * (Math.PI / 6)); context.moveTo(0, -180); context.lineTo(0, -200); context.stroke(); context.fillStyle = 'black'; context.rotate(Math.PI / 6); context.fillText(i + 1, -8, -220); context.closePath(); context.restore(); } //绘制分刻度 for (i = 0; i < 60; i++) { context.save(); context.lineWidth = 1; context.beginPath(); //将原点平移300,300 context.translate(300, 300); context.rotate(i * (Math.PI / 30)); context.moveTo(0, -190); context.lineTo(0, -200); context.stroke(); context.closePath(); context.restore(); } // 获取以后工夫 var today = new Date(); var hour = today.getHours(); var min = today.getMinutes(); var sec = today.getSeconds(); // hour = hour + min / 60; // 绘制时针 context.lineWidth = 3 context.save(); context.translate(300, 300); context.rotate(hour * Math.PI / 6); context.beginPath(); context.moveTo(0, 10) context.lineTo(0, -80); context.stroke() context.closePath(); context.restore(); // 绘制分针 context.lineWidth = 2; context.save(); context.translate(300, 300); context.rotate(min * (Math.PI / 30)); context.beginPath(); context.moveTo(0, 10); context.lineTo(0, -100); context.stroke() context.closePath(); context.restore(); // 绘制秒针 context.lineWidth = 1; context.save(); context.translate(300, 300); context.rotate(sec * Math.PI / 30); context.beginPath(); context.moveTo(0, 10); context.lineTo(0, -120); context.strokeStyle = 'red'; context.stroke() context.closePath(); context.restore(); // 绘制交叉处 // context.lineWidth=1 context.save(); context.translate(300, 300); context.beginPath(); context.arc(0, 0, 5, 0, Math.PI * 2); context.fill(); context.fillStyle = '#ccc' context.strokeStyle = 'red' context.stroke() context.closePath(); context.restore(); setInterval(clock, 1000)//超时模仿间歇 } clock(); }效果图如下: ...

September 15, 2021 · 2 min · jiezi

关于h5页面:移动端开发手册

挪动端设施适配挪动端适配计划 postcss px->vwremamfe-flexible rem挪动端罕用知识点横竖屏探讨判断横竖屏的最佳实现 ✳️ @media 媒体查问window.matchMedia / matcheswindow.innerHeight >= window.innerWidthwindow.orientation(旋转角度:0/90/-90/180)screen.width / screen.height挪动端兼容挪动端疑难杂症视频问题

August 26, 2021 · 1 min · jiezi

关于h5页面:移动端适配

计划介绍挪动端设计稿: 375*768 【基准】通常有两种计划,对立的思维就是 设计稿基准值*设施宽度比 375px=100% 宽度   也就是说1px = 100/375 %在375下1px,则在750px下 750/375 * 100/375 =  200/375 %; 计划一:px 转vwvw: 页面总宽度为100vw。能够配置转换时的设施宽度是375,会在不同设施宽度上进行适配。能够设置在横屏时持续应用设施宽坐基准值。 'postcss-px-to-viewport': { unitToConvert: 'px', //须要转换的单位,默认为"px" viewportWidth: 375, // 视窗的宽度,对应的是咱们设计稿的宽度 viewportHeight: 667,//视窗的高度,依据375设施的宽度来指定,个别指定667,也能够不配置 unitPrecision: 13, // 指定`px`转换为视窗单位值的小数位数(很多时候无奈整除) propList: ['*'], // 能转化为vw的属性列表 viewportUnit: 'vw', // 指定须要转换成的视窗单位,倡议应用vw fontViewportUnit: 'vw', //字体应用的视口单位 selectorBlackList: ['.ignore-', '.hairlines'], //指定不转换为视窗单位的类,能够自定义,能够有限增加,倡议定义一至两个通用的类名 minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也能够设置为你想要的值 mediaQuery: false, // 容许在媒体查问中转换`px` replace: true, //是否间接更换属性值,而不增加备用属性 exclude: [], //疏忽某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件 landscape: true, //是否增加依据 landscapeWidth 生成的媒体查问条件 @media (orientation: landscape) landscapeUnit: 'vh', //横屏时应用的单位 landscapeWidth: 375 //横屏时应用的视口宽度 }计划二: rem把基准值设置为rem, 在款式里都是依照rem来写 ...

August 26, 2021 · 1 min · jiezi

关于h5页面:H5唤醒app

url scheme形式 var downloader, scheme = ":lklk" //须要关上的app scheme地址 iosDownload = "jjjj",//如果关上scheme生效的app下载地址 anDownload = "http://xxx.com" var u = navigator.userAgent var isAndroid = u.indexOf("Android")>-1 || u.indexOf("Linux")>-1 //g var isIos = !!u.match(/\(i[^;]+;(u;)?CPU.+Mac OS X/);//ios终端 // 给id为openBtn的按钮增加点击事件处理函数 document.getElementById("openBtn").onclick = function(){ window.location.href = scheme //尝试关上scheme //设置3秒的定时下载工作 3秒之后下载app downloader = setTimeout(function(){ if(isAndroid){ window.location.href = anDownload } if(isIos){ windwo.location.href = iosDownload } },3000) }, document.addEventListener('visibilitychange webkitvisibilitychange',function(){ //如果页面暗藏 揣测关上scheme胜利 革除下载工作 if(docuemnt.hidden || docuemnt.webkitHidden){ clearInterval(downloader) } }) window.addEventListener('pagehide',function(){ clearInterval(downloader) })

March 14, 2021 · 1 min · jiezi