kbone icon indicating copy to clipboard operation
kbone copied to clipboard

【讨论】安卓打开新页面延迟太久有没有什么解决办法

Open xmsz opened this issue 4 years ago • 15 comments

从A => B,小程序原生基本就是200ms然后看到窗口进来,iOS秒开就不用讨论 然后使用框架,从A => B,快的500ms,慢的几乎就是1000ms的差距。

设想这部分时间,是由于加载tab页,同时加载了vue和框架文件,这部分会特别卡,所以窗口出现的也特别慢。

这种有什么解决或者优化的方案,因为太影响体验了,有点蛋疼

xmsz avatar Jul 30 '20 02:07 xmsz

初始渲染的内容大概是多复杂的树?

JuneAndGreen avatar Jul 30 '20 02:07 JuneAndGreen

初始渲染的内容大概是多复杂的树?

试过一个空白模板也是有点慢。

<template>
  <div id="app">
    <h1 class="text">{{ title.name }}</h1>
  </div>
</template>

<script lang="ts">
import { reactive, defineComponent } from 'vue';

export default defineComponent({
  name: 'App',
  setup() {
    const title = reactive<{ name: string }>({
      name: 'kgkh',
    });

    return { title };
  },
});
</script>
<style>
.app {
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.text {
  color: red;
}
</style>


然后尝试构建出来的init函数,延迟执行就会是正常速度。

function init(window, document) {
   require('xxxx');
  setTimeout(() => {
      require('../../common/message.js')(window, document); // 主要是这个文件的延迟加载,其他的都不影响
  }, 300);
}
// common/message.js
vue + vue应用

所以我觉得就是因为加载vue本身所以导致卡。

理想中的一个解决方案就是,延迟一小会在去加载vue,即只要满足点击的时候先出现窗口,内容慢慢加载倒没事

本来还尝试过先跳原生页面,然后在redirect到真实页面,但是这个行为在安卓上各种乱七八糟的情况出现,所以放弃了

xmsz avatar Jul 30 '20 03:07 xmsz

如果你是按照我的 demo 来搭建配置的话,vue 的代码应该在 vendor 里,这里应该是只有业务代码的,这里面可能会存在什么耗时逻辑么?

JuneAndGreen avatar Jul 30 '20 03:07 JuneAndGreen

如果你是按照我的 demo 来搭建配置的话,vue 的代码应该在 vendor 里,这里应该是只有业务代码的,这里面可能会存在什么耗时逻辑么?

我看错了,message的文件内容是

module.exports = function(e, t) {
	e.HTMLElement, e.Element, e.Node, e.localStorage, e.sessionStorage, e.navigator, e.history, e.location, e.performance, e.Image, e.CustomEvent, e.Event, e.requestAnimationFrame, e.cancelAnimationFrame, e.getComputedStyle, e.XMLHttpRequest;
	e.createApp = function(t) {
			function n(e) {
				for (var n, o, u = e[0], i = e[1], p = e[2], l = 0, f = []; l < u.length; l++) o = u[l], Object.prototype.hasOwnProperty.call(a, o) && a[o] && f.push(a[o][0]), a[o] = 0;
				for (n in i) Object.prototype.hasOwnProperty.call(i, n) && (t[n] = i[n]);
				for (s && s(e); f.length;) f.shift()();
				return c.push.apply(c, p || []), r()
			}

			function r() {
				for (var e, t = 0; t < c.length; t++) {
					for (var n = c[t], r = !0, o = 1; o < n.length; o++) {
						var i = n[o];
						0 !== a[i] && (r = !1)
					}
					r && (c.splice(t--, 1), e = u(u.s = n[0]))
				}
				return e
			}
			var o = {},
				a = {
					24: 0
				},
				c = [];

			function u(e) {
				if (o[e]) return o[e].exports;
				var n = o[e] = {
					i: e,
					l: !1,
					exports: {}
				};
				return t[e].call(n.exports, n, n.exports, u), n.l = !0, n.exports
			}
			u.m = t, u.c = o, u.d = function(e, t, n) {
				u.o(e, t) || Object.defineProperty(e, t, {
					enumerable: !0,
					get: n
				})
			}, u.r = function(e) {
				"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
					value: "Module"
				}), Object.defineProperty(e, "__esModule", {
					value: !0
				})
			}, u.t = function(e, t) {
				if (1 & t && (e = u(e)), 8 & t) return e;
				if (4 & t && "object" == typeof e && e && e.__esModule) return e;
				var n = Object.create(null);
				if (u.r(n), Object.defineProperty(n, "default", {
					enumerable: !0,
					value: e
				}), 2 & t && "string" != typeof e)
					for (var r in e) u.d(n, r, function(t) {
						return e[t]
					}.bind(null, r));
				return n
			}, u.n = function(e) {
				var t = e && e.__esModule ? function() {
					return e.default
				} : function() {
					return e
				};
				return u.d(t, "a", t), t
			}, u.o = function(e, t) {
				return Object.prototype.hasOwnProperty.call(e, t)
			}, u.p = "";
			var i = e.webpackJsonpcreateApp = e.webpackJsonpcreateApp || [],
				p = i.push.bind(i);
			i.push = n, i = i.slice();
			for (var l = 0; l < i.length; l++) n(i[l]);
			var s = p;
			return c.push([207, 1, 3, 0, 2]), r()
		}({
			199: function(e, t, n) {
				"use strict";
				n(69)
			},
			207: function(e, t, n) {
				"use strict";
				n.r(t);
				var r = n(0);
				const o = {
					class: "abc"
				};
				var a = {
						components: {
							App: n(29)
								.a
						},
						render: function(e, t) {
							const n = Object(r.resolveComponent)("App");
							return Object(r.openBlock)(), Object(r.createBlock)("div", o, [Object(r.createVNode)(n, {
								"init-video-ad": "",
								"init-interstitial-ad": ""
							})])
						}
					},
					c = a,
					u = n(14);
				const i = {
						id: "app"
					},
					p = {
						class: "text"
					};
				var l = Object(r.defineComponent)({
					name: "App",
					setup: function() {
						return {
							title: Object(r.reactive)({
								name: "kgkh"
							})
						}
					}
				});
				n(199);
				l.render = function(e, t) {
					return Object(r.openBlock)(), Object(r.createBlock)("div", i, [Object(r.createVNode)("h1", p, Object(r.toDisplayString)(e.title.name), 1)])
				};
				var s = l,
					f = n(28);
				u.a.addRoute({
					path: "/message",
					name: "Message",
					meta: {
						noNeedAuth: !0
					},
					component: s
				}), u.a.addRoute({
					path: "/:catchAll(.*)",
					redirect: {
						name: "Message"
					}
				});
				var d = Object(f.a)(c, u.a);
				t.default = function() {
					return d
				}
			},
			69: function(e, t, n) {}
		})
		.default
};

然后我只延迟1000ms mount app的话,打开页面还是卡。说明不是vue应用的问题

xmsz avatar Jul 30 '20 03:07 xmsz

总结当前情况就是

  • 如果我大概延迟200ms及以上去require(''./../common/message.js'),那打开窗口的速度就是正常
  • message页面仅仅是空白模板
  • vue2 vue3都是差不多表现
  • iOS不影响
  • 安卓打开很明显的慢

xmsz avatar Jul 30 '20 03:07 xmsz

安卓是什么机型呢?我看看能不能复现一下。

JuneAndGreen avatar Jul 30 '20 03:07 JuneAndGreen

安卓是什么机型呢?我看看能不能复现一下。

我们公司的安卓机都会有卡的现象 线上可以用qq搜索「匹配CP」,在消息或者我的页面里点击跳转到其他页面,就可以

然后我试了一下延迟base.js里init()的执行

      setTimeout(() => {
        setTimeout(() => {
          init(this.window, this.document);
          this.app = this.window.createApp();
          this.window.$$trigger('load');
          this.window.$$trigger('wxload', { event: query });
        }, 0);
      }, 0);

需要两次nextTick才可以保证不卡

然后init这个执行时间在正常iOS或者开发者工具下基本就是50ms(忽略不计)。在安卓上基本要200ms。 然后2次nextTick的时间差不多也是200ms左右,所以总的加起来就是400ms在安卓上才能加载完页面

当然这样体验变成了,点击 => 打开了窗口 => 进入窗口白屏200ms,才慢慢加载

xmsz avatar Jul 30 '20 04:07 xmsz

qq 里面也是么?

这个问题看来像是安卓卡帧了。安卓端本身确实可能存在这个问题,先前原生微信小程序上有过类似 case,在某些场景下会卡帧,这种的可能要待客户端那边解决才能从根源上来处理,我这边只能看看能否尽量改善这类 case 的体验了。

JuneAndGreen avatar Jul 30 '20 06:07 JuneAndGreen

qq 里面也是么?

这个问题看来像是安卓卡帧了。安卓端本身确实可能存在这个问题,先前原生微信小程序上有过类似 case,在某些场景下会卡帧,这种的可能要待客户端那边解决才能从根源上来处理,我这边只能看看能否尽量改善这类 case 的体验了。

ok 辛苦了

xmsz avatar Jul 30 '20 07:07 xmsz

我使用了华为 meta 20 试了下 demo18(vue2 多页)和 demo26(vue3 多页)的跳页和新开页面,都没有复现出明显卡顿/空白屏的感觉。你那边能否提供一下具体的问题机型、微信/基础库版本、问题录屏和问题 demo 呢?脱敏后发到 [email protected] 即可。

另外也可以检查下在安卓上打开调试和不打开调试是否会有明显的差异?

JuneAndGreen avatar Jul 31 '20 06:07 JuneAndGreen

那这个得找时间搞了

xmsz avatar Aug 03 '20 06:08 xmsz

@xmsz 拿稍低端的安卓机跑了下 demo,也没有明显的问题,感觉也可能和代码层面相关。

JuneAndGreen avatar Aug 04 '20 06:08 JuneAndGreen

嗯,这个是在完整项目下会有这个情况。包含一些例如路由拦截器然后+接口请求+读取本地storage(安卓下操作localStorage都是随随便便100ms以上)。

不过这部分由于没有完全的进行测试,所以不知道影响打不打,因为即使我延迟创建app,也是同样结果。

所以看看大家有没有遇到,还有什么优化体验的方法

我现在是临时做法,将base.js里 this.init 放在 onReady执行,这个时间刚刚好大概就是两次nextTick。但是问题就变成,窗口进来了,但是页面要白将近400ms。

然后再打补丁,搞了个骨架屏的图片放在mp_dist/pages/页面.wxml里。 这样体验只好了一点点,可是很胶水

xmsz avatar Aug 05 '20 09:08 xmsz

main.mp.js 是否有业务代码呢?

@xmsz

TomVista avatar Aug 07 '20 09:08 TomVista

@xmsz 我解决了一个类似的问题,

开始表现为,在iphone 6p上打开页面白屏,大概有1200毫秒, android上只有一个自定义header的闪烁

因为引入了[email protected]这个包 🐶

可以查一下外部包是否有问题

TomVista avatar Aug 13 '20 05:08 TomVista