web Components

微信小程序

调试ide版本:v1.02.1907300
微信小程序 ide 使用 nw.js 开发,我们可以尝试打开它的控制台

document.getElementsByTagName('webview')[0].showDevTools(true,null)

我们拿到了微信小程序的渲染层页面,注意body中的标签 wx-viewwx-open-data,这看起来是一种类似 web Components的实现,这是一种浏览器原生支持的组件形式。

支付宝小程序

调试 ide 版本:2.1.9
支付宝小程序是使用 Electron 开发的,我们也可以打开它的控制台:

document.getElementsByTagName('webview')[1].openDevTools()

外部套着模拟器,内部是iframe,这里应该就是小程序本身代码,也就是 iframe 部分

这里并没有和小程序类采用了组件的形式,而是原生标签 + class的形式。尝试全局修改a-view的样式,竟然真的生效了。
进一步测试发现,标签选择器会被编译成.a-*的形式,不局限于已有的标签,如果是a标签也会这样编译。

分析

微信小程序的标签需要基础库去解析,支付宝这里似乎是没有的,他直接编译成了html,并且html没有做到样式隔离,能够被外部影响。如果无意中写了类似标签,还是非常难以排查的。

rpx

rpx 是小程序平台的响应式单位。

rpx(responsive pixel)可以根据屏幕宽度进行自适应,规定屏幕宽为 750rpx。以 Apple iPhone6 为例,屏幕宽度为 375px,共有 750 个物理像素,则 750 rpx = 375 px = 750 物理像素,1rpx = 0.5 px = 1 物理像素。

微信小程序

viewport 设置

<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1">

rpx 转换:

var BASE_DEVICE_WIDTH = 750;
var isIOS = navigator.userAgent.match('iPhone');
var deviceWidth = window.screen.width || 375;
var deviceDPR = window.devicePixelRatio || 2;
var checkDeviceWidth =
  window.__checkDeviceWidth__ ||
  function () &#123;
    var newDeviceWidth = window.screen.width || 375;
    var newDeviceDPR = window.devicePixelRatio || 2;
    var newDeviceHeight = window.screen.height || 375;
    if (window.screen.orientation && /^landscape/.test(window.screen.orientation.type || '')) newDeviceWidth = newDeviceHeight;
    if (newDeviceWidth !== deviceWidth || newDeviceDPR !== deviceDPR) &#123;
      deviceWidth = newDeviceWidth;
      deviceDPR = newDeviceDPR;
    &#125;
  &#125;;
checkDeviceWidth();
var eps = 1e-4;
var transformRPX =
  window.__transformRpx__ ||
  function (number, newDeviceWidth) &#123;
    if (number === 0) return 0;
    number = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
    number = Math.floor(number + eps);
    if (number === 0) &#123;
      if (deviceDPR === 1 || !isIOS) &#123;
        return 1;
      &#125; else &#123;
        return 0.5;
      &#125;
    &#125;
    return number;
  &#125;;

支付宝小程序

viewport 设置

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0, viewport-fit=cover">

根字体设置:

// af-appx.min.js
function Sy() &#123;
        _y = document.documentElement.clientWidth, xy = document.documentElement.clientHeight, wy = Math.min(_y, xy);
        var t = 100 * _y / 750 + "px";
        document.documentElement.style.fontSize !== t && (document.documentElement.style.fontSize = t)
    &#125;

编译之后的样式文件:

/*ACSSCompileContext:&#123;"atImports":[]&#125;*/var internal_style;

internal_style = ".title &#123;background:red;font-size:0.5rem&#125;.ttt &#123;font-size:0.5rem&#125;.hair &#123;height:1px&#125;.a-view &#123;background:orange&#125;.ttt .a-a &#123;font-size:100px!important&#125;#id &#123;font-size:1rem&#125;";
export default internal_style;

分析

微信小程序,rpx 被转换成了px。支付宝小程设置了根字体,rpx 最终被转换成了 rem。支付宝根字体的转换找到了代码,rpx 转 px 没有找到代码,猜测,应该是在编译过程中已经进行了转换,我分析的运行时部分没有这部分代码。

总结

貌似一样的众多小程序,仔细分析,发现还是有很多很多的不同,某些不同,还是基础架构层面的不同,深入分析,应该可以挖掘出更多有意思的东西。

参考