mipengine / mip2 Goto Github PK
View Code? Open in Web Editor NEWMIP (移动网页加速器)通过优化网页JS、控制资源加载顺序,达到加速网页的效果。
Home Page: https://www.mipengine.org/
License: MIT License
MIP (移动网页加速器)通过优化网页JS、控制资源加载顺序,达到加速网页的效果。
Home Page: https://www.mipengine.org/
License: MIT License
MIP2 执行关键路径时间点
引用: <script src="https://bos.nj.bpc.baidu.com/assets/mip/projects/mip.js"></script>
使用: MIP.viewer.open() 进行跳转会报错,但是不影响功能
本页刷新没有报错
背景:
目前mip-shell切换时,页面入场动画都是统一的从右往左滑动入场,但是在小说这个业务中,用户进行翻页操作时,大范围的页面入场,整体交互体验较差,希望可以自定义行业shell的loading入场动画。
诉求:
希望mip-shell能够暴露出来创建loading和页面入场动画的接口,行业shell可以根据需求自行定制。
<mip-data>
<script type="application/json">
{
"text": "aaaa"
}
</script>
</mip-data>
<span m-text="text"></span>
<button on="tap:MIP.setData({text: 'btn clicked'})">button</button>
<span m-text="aaa"></span>
<button on="tap:MIP.setData({aaa:'btn_clicked'})">button</button>
当前的 MIP2 核心代码 gzip 前为 328.73kb
, gzip 后为 95.8kb
。
现在基本总结出有以下优化点 (每一点还可以细化,但是现在还没有具体方案,具体方案和进展本 issue 同步):
src/polyfills
的合并当滚动条不是在 body 上而是在 body 上的 dom 容器的话,那 viewer 首屏机制就不会生效。
从具体表现上来看:
现在 /examples/wecoffee/index.html
这个 case 所有的图片都在第一次加载页面的时候全部加载进来,这不符合 mip-img 的预期,对性能会有很大的影响。
MIP.viewer.page.back() 执行返回页面无切换效果
头部返回正常
在进行页面切换时,会把当前的 <iframe>
进行隐藏/展现,使用 display: none
。
但是在 iOS 的 UC/手百 下,切换时会出现页面不响应,假死的现象,十分奇怪。
打开这个简单的 测试页面 /mip/examples/page/iframe/uc.html ,就可以复现,步骤如下:
<iframe>
嵌入一个测试页面 scroll.html
测试页面 scroll.html
包含一个菜单,使用了 iOS 弹性滚动。另外还包含以下测试:
m.baidu
,AMP 页面
都会出现这种情况。而 PC 百度,eleme H5 则不会出现。<iframe>
同样会出问题:visibility: hidden
opacity: 0
+ height: 0
+ width: 0
微信不存在这个问题,因为在 iOS 下使用了较新的 WKWebview。
而 UC/手百 使用的是 UIWebView。除了这个奇怪的问题,还有诸如 scroll 事件延迟 等其他滚动相关的问题,详见。
有问题的页面使用了弹性滚动 -webkit-overflow-scrolling: touch;
。
而一旦不使用这个属性,或者在隐藏 iframe 的同时由被嵌入的页面去掉这个属性,就不会出现问题。
// 需要在隐藏的同时去掉 -webkit-overflow-scrolling: touch;
iframe.contentDocument.querySelector('.menu').classList.remove('touch-scrolling')
第一种比较直接,就是判断处于 UC/手百 下,在页面切换时,就直接删除 iframe,而不是隐藏。
第二种就是在页面切换也就是隐藏 iframe 时,关闭掉所有组件的弹性滚动。
但是这样做的问题就是,内置的组件还好办,用户写的组件也会使用到弹性滚动,这就要求页面切换时需要通知所有的组件,让用户做这样的操作。
目前在根页面中以 iframe 方式打开多个子页面,各个子页面渲染各自的自定义组件。
有一种需求是类似登录框这样的组件,并不需要每个页面都渲染一遍,而是应该由根页面统一负责渲染。
例如目前的 <mip-shell>
,虽然每个页面都会写在各自的 HTML 中,但实际只会在根页面中运行。
更类似于一种全局性的配置文件。
而全局组件比 <mip-shell>
更加复杂,因为可能会与页面中其他组件交互。
在子页面中,在自定义组件注册之前,一旦识别到全局组件(加上特殊的 attribute),向根页面通过 postMessage
发送组件 DOM 结构(字符串形式),然后从 DOM 中删除避免触发 connectedCallback
。
根页面接收到事件,如果当前不存在这个全局唯一的组件,请求组件对应的 JS,插入 DOM 结构开始渲染。
可能存在的问题是和原子页面中其他组件的交互。不过如果统一使用全局的状态数据,似乎子页面其他组件也不用关心这个全局组件的具体渲染细节。
BUG 描述
on 事件触发执行 MIP.setData 时,如果数据表达式使用了括号,将无法执行
复现步骤
<mip-data>
<script type="application/json">
{
"value": 1
}
</script>
</mip-data>
<h1 m-text="value" on="tap:MIP.setData({value:(m.value+1)})"></h1>
把表达式中的括号去掉就可以正常执行了,已验证过与 setData 方法无关
期望结果
点击触发 setData,h2内容随着点击自增
环境及版本信息:
没有特定环境
MIP 2.0 支持在站点页面内无缝原生地切换页面。页面体验与之前 MIP1.0 在搜索结果页打开的体验对齐 (参考 MIP 官网的预览效果),即:点击任意链接后,马上出现一个新页面侧滑进入当前页面,并显示头部和 loading;加载完成后保留头部、取消 loading。
在搜索结果页 superframe 环境下打开时,我们依然沿用这一行为:MIP 站点的页面之间切换(内链),仍然由 MIP 2.0 的核心代码管理并组织;而在站点之间(外链)切换或者调起百度搜索相关服务(登录、支付等熊掌号能力)的时候,则交由 superframe 控制。
为了讨论简单起见,我们首先讨论内链的行为。
replaceState
而不是 pushState
修改 urlpushState
修改浏览器上的 url
BUG 描述
按代码命名规范在本地json
中书写驼峰属性,无法正常读取(根本没过来?)
复现步骤
<!-- html -->
<mip-json>
<script type="application/json">
{
"mipProps": "mipProps",
"mip-components": "mip-components"
}
</script>
</mip-json>
// components
export default {
props: {
mipProps: {
type: String,
default: ''
},
mipComponents: {
type: String,
default: ''
}
},
mounted () {
console.log(this.mipProps) // 空
console.log(this.mipComponents) // mip-components
}
}
驼峰属性无法打印,连字符正常
环境及版本信息:
如标题,所有IOS版本都有问题,调用router.open即可复现。
在这次方案重新设计之前,mip-script
方案是由组件核心来实现的,开发者在页面里编写如下代码就可直接运行,方案和组件的沙盒方案一样,采用的黑盒方案,可以看这个 issue 的第一段 #5
<script type="application/mip-script">
MIP.watch('var_name', function () {
});
</script>
同样,会有黑名单频繁需要更新,且无法达到足够安全的程度,因此,mip-script 方案也需要重新设计。
和 #5 一样,也采用白盒方案
mip-script
自定义标签mip-script
标签内置白名单列表mip-script
分析自定义 js 的语法树,找到使用的全局变量MIP.sandbox.
前缀,保证这些变量使用的是沙盒中的变量<div on="click:xiaoshuo-shell.showShellFooter" class="click-cursor">
.click-cursor {cursor: pointer}
如果站长用了on="click:
却没加on="click:
属性会导致click不生效,不能触发eventAction。建议在click绑定事件时,默认加上一个class或style="cursor: pointer", 不用开发者自己写
附MIP1.0当时信息:
issue:mipengine/mip#307
PR: https://github.com/mipengine/mip/pull/306/files
(掉坑里两次了)
RT,如果在子元素上绑定 touchstart 事件并 stopPropagation 阻止冒泡,而对 touchmove 之类的事件没有阻止外冒泡,会导致 js 报错
背景:
mip1中有部分通用工具函数但是目前没有被整理到mip2的文档中,
合作方开发的时候,阅读的是mip2.0的文档, 这部分会经常有疑惑,总是要找老版本的文档给他们看,这样会给他们带来一些开发上的困惑
这里建议把这部分通用工具方法的文档也写进mip2的开发文档里~
viewport.setScrollTop()
无效;
如图,无法设置scrolltop
值:
初步认为是这次提交导致的:ef1f7b4#diff-f955982bdc643d96b583cdc148889674
我们可以在组件文档平台中添加一些demo ,方便使用者查找组件
可参考下https://cinwell.com/vuep/#/ 这个文档平台,带有demo 在线实时编译的的文档,可以提升文档阅读者的体验
mip2组件缺少沙盒环境,FE及QA无法使用沙盒进行全流程测试
在这之前,我们确定的方案是 Context
方案,通过将组件的 script 包裹在我们的沙盒中,然后将全局的变量在这个沙盒中重新实现,达到屏蔽一些危险的变量和方法的目的,如下代码所示:
// sandbox.js
export let document = {
// 不包含 createElement 方法
};
// component-a.js
let document = MIP.sandbox.document; // 重写 document 对象,编译时注入
export default new Vue({
methods: {
created() {
let a = document.createElement('a') // 操作不被允许
}
}
});
后来发现这种方法很难控制, window 下的变量茫茫多,不仅有浏览器默认的变量,还有 MIP 里挂载到全局的变量,如:window._m, window.MIP_ROUTER
等等,这样的黑名单方案不可靠,经常需要升级,因此,我们将沙盒方案改为白盒方案,只允许组件使用 window 中的某些变量和函数
白盒方案分为两步:
如 #2 讨论,在百度搜索结果页环境下,我们需要在 MIP 中设计一个路由通信的 API,以实现路由的完整性。
在下文的讨论中,我将百度搜索结果页的 superframe 框架称为“外”框架,而 MIP 页面中负责路由机制的模块称为“内”框架。
路由通信是一个双方(有从内到外,也有从外到内)、单向(只发送通知,不处理返回)的通信机制,目前基于 iframe-shell 的 messenger 模块来做。以下是双方需要实现的事件:
事件名:pushState
事件参数:
url
:一个需要 push 的 url。注意这里采用带 origin 的绝对 url,如 http://localhost:8080/path/to/page.html
。事件名:historyNavigate
事件参数:
step
:前进后退的步数。必须 >0 或者 <0。如 -1
表示后退。事件名:close
事件参数:
无
事件名:changeState
事件参数:
url
:路由的目标 urlhistoryNavigateStep
:如果 state 是由 historyNavigate
触发,会将 step 传入;否则为 0。如果用户点击浏览器上的前进后退,该变量也为 0。UPDATE:移除了 state
参数;增加了 historyNavigateStep。
越来越多的官方组件和第三方组件提交,为了可维护性和代码统一,因此需要对组件提出一些规范的要求,需要遵守的规范包括:
<body>
<mip-data>
<script type="application/json">
{
"payConfig":{}
}
</script>
</mip-data>
<div>
<h2>First MIP page</h2>
<h2>Add MIP components here</h2>
<mip-example m-bind:pay-config="payConfig"></mip-example>
</div>
<script src="https://bos.nj.bpc.baidu.com/assets/mip/projects/mip.js"></script>
<script src="/mip-example/mip-example.js"></script>
</body>
export default {
props: {
payConfig: {
type: Object,
required: true
}
},
watch: {
payConfig (newVal, oldVal) {
// watch it
alert('new' + JSON.stringify(newVal))
alert('old' + JSON.stringify(oldVal))
}
},
mounted () {
alert(JSON.stringify(this.payConfig))
console.log('This is my first custom component !')
}
}
ios7下共弹出2次,两次是被更新后弹出的
MIP2 和 MIP1 大体上一样,但还是有一些点不太一样,需要在迁移内置组件的时候注意,并且遵循以下规范
以下规范还是 Draft,随时会更新
eslint-disable
mip-nav-slidedown
,作为一个浏览器的自定义标签,居然把事件代理到 document
,customElement 只能负责自己的逻辑,尽量不要越界isIframed
这个变量的含义改变了,判断是否在搜索结果页通过 MIP.standalone
来判断,代替具有歧义的 viewer.isIframed
变量let me = this
这样的语句,如遇到这种情况,请使用箭头函数目前根页面和各个子页面 <iframe>
通信使用 postMessage()
,传递的数据对象是不需要开发者自己序列化的。MDN
由于 MIP 页面里存在内置组件、公共组件、第三方组件,还有 mip-shell
和 MIP HTML,多数都有遮住全屏的 mask,因此 z-index
的管理就很有必要
mip-shell
:z-index >= 1000除 mip-shell 外,其他不设置最小值
iOS 开启弹性滚动后,容易滚动到下方容器。
可以在 iOS 下任意浏览器中访问 http://localhost:8080/examples/page/iframe/iframe.html
或者直接看这个 GIF:
scroll
事件,滚动到顶时强制设置滚动距离为 1
,即永远到不了最顶部。Google AMP 也是这么做的,在 iOS 上打开 AMP 页面,滚动到顶触发 iOS 的弹性滚动,仔细观察页面会有一个轻微的不易察觉的向上滚动。
需求描述:
mip-img 中存在一个popup属性,可以控制点击图片采用弹出的形式浏览大图。但是这种浏览能够实现单张浏览。现在希望在这个基础上,能够扩展这个功能,点击图片弹出大图浏览时,可以进行左右滑动切换,浏览页面上其他配置了popup属性的图片。
一个具体的yi应用case如下图所示:
https://mip.putibaby.com/master_card?mcode=x6f3adb702b5c7a530aee9f6a3e4bf78f
如题,在 chrome 浏览器上无效,查了下是浏览器 video 标签的bug,可通过下面方法修复
https://stackoverflow.com/questions/14111917/html5-video-muted-but-stilly-playing
有关mip-extensions中的issue,https://github.com/mipengine/mip-extensions/issues/1209,可能与mip2中template的支持的效果有关,辛苦帮忙排查下
MIP组件迁移2.0,不改变站长使用组件的方式。也就是说,站长使用xx组件从1.0升级到2.0,只需要把v1/mip-xxx/mip-xxx.js
改成 v2/mip-xxx/mip-xxx.js
, html部分不变
目前站长是这样使用组件的:
组件获取配置的数据(mip1中直接选择,mip2中用props),template内容(不需要直接获取, 传递包含template的element,mip1中会使用queryselector选择),渲染成html后插入页面。
由于不能改变组件用法,支持站长自己用mustache语法写template标签并渲染,需要mip2核心代码提供类似的templates供Mip2组件require.
目前组件在mip2 build过程中样式中的px并没有转换成rem,是否可以统一下转换规则,然后在打包过程中把这个功能添加上?
迁移 mip 选项卡组件
目前的最佳实现:<mip-vd-tabs/>
为选项卡容器,<vd-tab/>
为选项卡,根据站长的需求,数量不一定。期望的结构如下
<!-- 这是 HTML 文件,非 Vue 单文件 -->
<mip-vd-tabs>
<vd-tab name="标签1" :selected="true">
<h2> MIP 2.0 </h2>
<p> 内容11111 </p>
</vd-tab>
<vd-tab name="标签2">
<p> 内容222222 </p>
</vd-tab>
<vd-tab name="标签3">
<p> 内容333333 </p>
</vd-tab>
...
</mip-vd-tabs>
效果如图:
组件<mip-vd-tabs/>
导入<vd-tab/>
,可正常注册并使用。但在 HTML 中(即站长使用时),子组件(<vd-tab/>
)无法被解析。因为只导出了<mip-vd-tabs/>
组件,<vd-tab/>
是没有暴露出来的。
拿选项卡为例
<slot/>
插入 dom,然后在<mip-vd-tabs/>
组件内, 选中元素、属性、遍历、赋值……�<!-- 用 slot -->
<mip-vd-tabs>
<div name="标签1" class="active">
<h2>MIP 2.0</h2>
<p> 内容11111 </p>
</div>
<div name="标签2">
<p> 内容222222 </p>
</div>
<div name="标签3">
<p> 内容333333 </p>
</div>
...
</mip-vd-tabs>
json
数据
<!-- 用 json -->
<mip-vd-tabs>
<script type="application/json">
{
"items": [{
"name": "标签1",
"content": "<h2>MIP 2.0</h2><p>内容11111</p>"
},{
"name": "标签2",
"content": "<p>内容22222</p>"
},{
"name": "标签3",
"content": "<p>内容33333</p>"
},{
...
}
]
}
</script>
</mip-vd-tabs>
在 html 中任意插入子组件,升级成本低、结构直观、 子组件嵌套的内容自定义方便
选项卡
<mip-vd-tabs>
<vd-tab> </vd-tab>
<vd-tab> </vd-tab>
<vd-tab> </vd-tab>
...
</mip-vd-tabs>
焦点图
<mip-carousel>
<carousel-item> </carousel-item>
<carousel-item> </carousel-item>
<carousel-item> </carousel-item>
...
</mip-carousel>
...
因为MIP.setData 是先JSON.stringify再传,所以不支持function
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.