uni-app 2.2发布,大幅优化H5端性能体验

2023-11-06

背景

uni-app发布以来,已经服务了几十万开发者。让我们意外,或者说惊喜的是,有大量开发者用uni-app只编写H5版,并没有多端发布(可参考案例)。

这其实也符合uni-app的初衷,uni-app的定位并不是需要多端发布时才用uni-appuni-app是一个使用vue.js开发所有前端应用的统一框架。对于一个前端工程师来说,使用uni-app做多端效率更高,做单一端也没问题,并在各端有不少出彩的地方。

过去的版本迭代中,uni-app已经成为了更好的小程序开发框架,比使用原生微信开发更有优势。(见评测

uni-app2.2的新版中,我们大幅优化了H5版的性能,让使用uni-app开发的H5,性能体验和直接使用vue.js开发H5拉齐。

可能不少开发者有某种误解:多端框架要适配多端,所以性能肯定不如原生。我们想纠正一下:

  1. 切忌想当然,多看数据评测。还不信就自己动手实验
  2. 请问使用vue.js开发的web性能好,还是使用原生js开发web性能好?答案是:使用vue.js框架。为什么?因为它在底层会自动优化数据同步、虚拟dom,比大多数开发手动写的代码要更高效。同样的,使用uni-app也如此,框架底层的优化处理比大多数开发者手动写setdata或dom操作更高效。
  3. 多端适配很多是在编译时做的,并不影响运行时的性能

优化难点

想优化H5端的性能,并不是一件容易的事。

“功能全面”和“小巧极速”,这是一对最难调和的冤家。

为了保障多端的一致性,uni-app实现了一套小程序的H5版Runtime,支持各种小程序的组件、API、配置。所以uni-app的H5版拥有比其他框架更好的跨端一致性。

但这也造成了老版的uni-app,输出H5端时,包体积过大(框架未压缩前有500k,部署gzip后162k)。

这确实是一个非常大的runtime,包含了几十个内置组件,数百个API。而且这些API仍然在快速增加中。

不能像其他框架一样因为功能少,所以体积小。我们不会用功能换性能,我们需要更好的方案。

优化方法

uni-app包含几十个内置组件、数百个API,是个“大而全”的框架;但开发者在开发具体应用时,未必能使用到所有的组件及API。若能根据项目具体情况,删掉没用到的组件及API,保留对项目有用的组件及API,便可精简框架、减少体积,这即是“摇树优化”的思路。

摇树优化(Tree-Shaking),顾名思义,摇晃树干,将枯死无用的枝条摇掉,仅保留有用的树枝。对应到框架层面理解,就是一个框架的众多组件和API,可以按需使用,把未引用的框架部分裁剪掉。Tree-Shaking 最早由 Rollup 提出,属于死码删除的一种形式。

常见的前端框架摇树,一般是基于明确的import引用关系。比如引用某UI库时,在A页面使用该UI库的search组件,此时需要写js代码import这个search组件,那么摇树分析就很容易。

uni-app和小程序一样,内置组件和API是不需要import的,这提升了开发的易用性,但此时却加大了摇树的难度,依靠简单的import分析无法实现摇树了。

幸好对DCloud团队而言,AST语法分析是看家本事,多年来HBuilder以js和vue语法提示著称。通过AST分析,uni-app新版可以精准判定这个项目使用了哪些组件和API。

不过这还不够,分析工程源码使用了什么组件和API之后,还得考虑框架各组件和API之间可能存在依赖和耦合关系,这需要进一步的计算和关系梳理,具体而言:

  • 组件:通过vue-template-compiler分析出来的AST,映射生成项目中使用到的组件清单,然后再基于Webpack插件将使用到的组件打包构建
  • API:编译器维护一个 api 依赖关系的 json 文件,该 json 文件描述每个 api 可能依赖的文件,然后 babel 查找到对应的 api 后,根据api 的依赖关系自动导入,重新编译

在工程师持续的加班奋战后,uni-app终于推出了全新的2.2版本,解决了这些难题,大幅降低了发行包体积,gzip后的框架体积,从162k降低到92k,仅相当于你在工程中引用了vue.jsvue-router、以及部分es6 polyfill库。(后续有详细比较)

除了大幅降低发行包体积,新版还调整了预载策略,可以进一步加快页面的渲染速度。

优化结果

搭建环境

我们使用vue-cli创建uni-app默认模板

vue create -p dcloudio/uni-preset-vue my-project

项目创建后,编译生成H5端的发行目录

npm run build:h5

然后配置nginx服务器,指定root目录并启用gzip压缩,示例如下:

server {
    ...
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_comp_level 4;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    ...
}

runtime 动态裁剪

然后通过 Chrome DevTools 的 Network 面板,查看优化前的首页网络请求包大小,结果如下:

然后启用H5平台的优化开关,重新查看首页的网络请求包大小,结果如下:

可以看到框架主库(chunk-vendors.js)从162k变为92.8k,体积压缩43%!

实际上,框架主库主要分为三个部分:

  • vue/vue-router基础库
  • es6 polyfill库
  • uni-app runtime(组件&API实现)

如果对这三个部分再拆开对比,我们会看到uni-app组件库优化比例更高:

vue/vue-router es6 polyfill库 uni-app runtime 累计
优化前 38k 43k 81k 162k
优化后 38k 26k 28.8k 92.8k

Tips:

  • uni-app runtime从81k瘦身为28.8k,裁剪比例达到64%
  • 新编译器对es6的使用也做了动态扫描,项目中用到的es6语法(包括uni-app runtime用到的es6语法),才会打包对应的polyfill实现,故es6 polyfill库从43k瘦身为26k

脚本执行时间

然后,我们再通过Chrome DevTools 的 Performance 面板,查看优化前后的性能数据,对比结果如下:

可以看出,最耗时的脚本执行时间,从227ms提升为154ms,时间提升达到32%。

如何使用

虽然内部实现比较复杂,但uni-app对外暴漏了简单的配置,开发者只需在配置文件中打开一个开关即可。具体在 manifest.json 中h5节点配置如下选项:

"h5" : {
    "optimization":{
        "treeShaking":{
            "enable":true //启用摇树优化
        }
    }
}

2.2版的其他优化

uni-app2.2版中,还开放了package.jsonvue-config.js的自定义,开发者可以自由的配置编译策略。

现在可以自定义支持所有小程序平台,包括钉钉小程序、高德小程序、抖音小程序…等。这样除了标准的8大平台(iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序),这些生态的子生态也可以分版本条件编译。

同样,也支持对H5端进行多子端编译,比如微信里的内嵌的H5、App里内嵌的H5…都可以分开条件编译。

如此灵活的条件编译,对于一套工程的多端发布、共享复用、同步升级,有莫大的好处。即便是仅开发H5版,uni-app的多端条件编译也提供了更灵活和强大的工程化能力。

2.2版本还可以设置各种静态资源、js、小程序自定义组件的编译和拷贝策略。如果你之前的h5项目或小程序项目想转换至uni-app下,又不想挪动某些目录结构,那么在vue-config.js里配置策略即可。

使用uni-app开发H5和直接开发H5相比的优势

在与直接开发h5拉齐性能的基础之上,uni-app给开发者提供了更多优势:

  1. 开发效率
    uni-app提供了大量适合手机页面的基础组件(其实就是小程序组件)。还提供了扩展组件uni ui。插件市场更有600多款插件。

无论开发者想找一个电商的模板,还是找一个图表组件,都可以手到擒来。开发效率更胜以往。

  1. 多端编译
    我们开发H5时,经常需要给浏览器输出一份、给微信等超级App输出一份、给自家的App输出一份。甚至不同地域、不同用户画像,都会输出不同版本。以前,开发者只能对js部分进行条件编译,甚至不得不建多个仓库进行多版维护。

uni-app解决了这些烦恼,它的条件编译非常灵活强大:

  • 不管是组件、js还是css,都可以按平台编译输出
  • 还可以多个平台进行“与和或”的运算编译
  • 除了文件中的代码,整个文件、甚至整个目录,都可以条件编译

例如微信、QQ等在支持x5内核的内置浏览器中,使用x5的视频同层渲染;或者在微信服务号中调用微信卡劵,这段代码只有build到 dist/h5-weixin 这个目录下的版本才会被编译进去,其他平台不会有这段代码

// #ifdef H5-WEIXIN
wx.openCard({
    cardList: [{
        cardId: '',
        code: ''
    }]// 需要打开的卡券列表
});
// #endif

后续计划

接下来,uni-app在H5端将提供服务端渲染机制(SSR)和PC宽屏界面适配优化,在追求性能极致和大一统的道路上继续前进!

相关代码全部托管在 github,欢迎大家 star 或提交 pr!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uni-app 2.2发布,大幅优化H5端性能体验 的相关文章

  • Google Guava

    转载自并发编程网 ifeve com 本文链接地址 Google Guava官方教程 中文版 中文文档 http ifeve com google guava 开源地址 https github com google guava 今天偶然发
  • swagger3或者swagger报nullpointexception

    很简单这个问题就是版本不匹配 就是2 6 0以上版本的springbootmvc扫描方法和老版本不同 在springboot配置 application yml 里面加上如果是properties则是加上 spring mvc pathma
  • 配置Spark on YARN集群内存

    在这里插入代码片 运行文件有几个G大 默认的spark的内存设置就不行了 需要重新设置 还没有看Spark源码 只能先搜搜相关的博客解决问题 按照Spark应用程序中的driver分布方式不同 Spark on YARN有两种模式 yarn

随机推荐

  • 利用CNN进行人脸年龄预测

    很久之前做的东西了 最近做了一个人脸相似度检测 里面用到了这里的一个模型 所以抽个空把人脸年龄检测的思路总结一下 与其他CNN分类问题类似 人脸年龄预测无非就是将人脸分为多个类别 然后训练卷积神经网络 最后利用训练好的卷积神经网络进行分类即
  • 数据结构: 线性表(无哨兵位单链表实现)

    文章目录 1 线性表的链式表示 链表 1 1 顺序表的优缺点 1 2 链表的概念 1 3 链表的优缺点 1 4 链表的结构 2 单链表的定义 2 1 单链表的结构体 2 2 接口函数 3 接口函数的实现 3 1 动态申请一个结点 BuySL
  • SparkStreaming与Kafka010之05之02 Consumer的offset 自定义设置offset

    package Kafka010 import Kafka010 Utils MyKafkaUtils import org apache kafka clients consumer ConsumerRecord import org a
  • IDEA创建Springboot项目提示`Initialization failed for ‘https://start.spring.io‘ Please check URL`

    1 1 settings gt http proxy 2 check connection 在其中输入 https start spring io 3 开始创建 4 导入springweb的一个依赖 5 创建成功 选中的3个为maven环境
  • CSS样式——旋转工具箱

    目录 基础模板 工具箱样式 加号按钮样式 工具按钮样式 旋转效果 CSS样式 旋转工具箱 效果如下所示 基础模板 首先我们准备基础模板 模板代码如下图所示
  • 盘点12个Python数据可视化库

    大家好 我是小z 这篇文章是关于一本很奈斯的可视化书籍的介绍 老规矩 文末小z简单粗暴的抽奖送出1本 在数据可视化的研究热潮中 如何让数据生动呈现 成了一个具有挑战性的任务 随之也出现了大量的可视化软件 相对于其他商业可视化软件 Pytho
  • C#多线程之BackgroundWorker

    一 BackgroundWorker介绍 我们有时要执行耗时的操作 在该操作未完成之前操作用户界面 会导致用户界面停止响应 解决的方法就是新开一个线程 把耗时的操作放到线程中执行 这样就可以在用户界面上进行其它操作 新建线程可以用 Thre
  • jvm垃圾回收机制

    如何判定一个对象是不是垃圾对象 1 引用计数法 2 根可达性算法 引用计数法 2 可达性分析算法 垃圾回收算法 1 标记清除算法 位置不连续 会产生磁盘碎片 2 复制算法 没有碎片 浪费空间 3 标记整理 没有碎片 效率偏低
  • 算法训练营第十七天(7.29)

    目录 LeeCode513 Find Bottom Left Tree Value LeeCode112 Path Sum LeeCode113 Path Sum ll LeeCode106 Construct Binary Tree fr
  • [C语言]---操作符

    1 算术操作符 的两个操作数必须为整数 3 2 1 3 0 2 1 5 2 移位操作符 左移 lt lt num lt lt 1 num值不变 右移 gt gt 分两种 逻辑移位 左边用0填充 右边丢弃 算术移位 左边用原该值的符号位填充
  • VMware下Ubuntu与宿主Windows共享文件夹

    概述 1 安装VMware Tool 2 设置共享 步骤 开始安装VMware Tool 显示如下画面 如果宿主无法访问外网 可能会出现一个更新失败 可以无视之 通过下列命令解压 执行 分别是下面的tar和sudo的两行 下面是已有vmwa
  • AcWing 372. 棋盘覆盖(二分图&&匈牙利算法)

    输入样例 8 0 输出样例 32 解析 n为100 状压肯定爆 将每个骨牌看成二分图的一个匹配 即查找二分图的一个最大匹配 匈牙利算法 include
  • C# 数据类型_摘自菜鸟教程

    数据类型 值类型 Value types 引用类型 Reference types 对象 Object 类型 动态 Dynamic 类型 字符串 String 类型 指针类型 Pointer types 值类型 Value types 值类
  • CAP的分区容错性

    一直没有理解CAP 中P的分区容错性是什么意思 系统部分节点出现故障后 连接正常节点还可以使用系统提供的服务
  • VS项目中引入dll的方法

    引入dll的方法 方法1 配置属性 gt 调试 gt 环境 输入path 包含dll文件的文件夹路径 方法2 1 将dll文件拷贝到生成的 exe所在的文件夹中 2 项目右键 添加引用 选择dll文件 我用的第二种
  • 【华为OD机试真题】字符串通配符(200分)

    目录 题目 输入描述 输出描述 示例1 示例2 示例3 个人解法 总结 系列文章目录 题目 时间限制 C C 1秒 其他语言2秒 空间限制 C C 32M 其他语言64M 在计算机中 通配符是一种特殊语法 广泛应用于文件搜索 数据库 正则表
  • 挖槽,Sharding-JDBC强制走主库,一不留神就报错了

    点击关注强哥 查看更多精彩文章呀 今天项目中突然告警报错 打出了多条相似的错误日志 查看了下 具体报错内容如下 HintManagerHolder has previous value please clear first 从错误日志我们可
  • 半监督

    半监督学习 transductive learning unlabeled data is the testing data inductive learning unlabeled data is not the testing data
  • ARGB色彩空间模型:ARGB_8888、ARGB_4444、RGB_565、ALPHA_8、ARGB1555

    ARGB是一种色彩空间模式 由RGB色彩空间和Alpha通道组成 RGB即红 Red 绿 Green 蓝 Blue Alpha为透明度参数 数值为0 完全透明 无法被看见 数值为100 表示像素完全不透明 ARGB后跟的数字一般为字面意思
  • uni-app 2.2发布,大幅优化H5端性能体验

    背景 uni app发布以来 已经服务了几十万开发者 让我们意外 或者说惊喜的是 有大量开发者用uni app只编写H5版 并没有多端发布 可参考案例 这其实也符合uni app的初衷 uni app的定位并不是需要多端发布时才用uni a