PS:本文是笔者对基于uniapp的一小程序项目进行分包后的复盘文档,不足之处请多多指教。html
本质上是改变项目的路由以及优化项目各个模块的启动时间的一种优化技术。vue
主包与分包的概念json
1). 主包:本项目中初始化时所必须的页面。小程序
项目在启动时,将从主包进入,分包在用户未进入时不会加载,只有在进入分包模块时才会加载。
tabbar页面以及模块间共有的页面,若是该项目有帐号限制(即非注册帐号不可进入主界面),也应将登陆页放置在主包内微信小程序
2). 分包:除主包外的全部页面都应放置在分包内,为避免读者混淆,本文会将该分包定义为子包数组
优化项目首次启动的下载时间;小程序默认就是整包(主包)下载,但这会致使整个项目只有在所有加载完毕后才会回显到用户眼前,这样虽然可使用加载动画进行优化,但也会有部分可能致使用户流失;微信
防止项目超出小程序官方对小程序项目打包后的大小限制;网络
若不分包,整个程序最大限制不能超过2M,分包后,整个项目(包含主包+子包)最大不能超过16M,单个包不能超过2M (这样就规避了项目最大不得超过2m的限制)app
PS: 因为笔者仅作了微信小程序分包,于是如下也仅对面向微信小程序的uniapp项目有效工具
PS: 笔者是tabbar页做为单模块划分子包,即每一个tabbar均做为一个子包模块
添加相关字段
// "mp-weixin" "optimization":{ "subPackages":true //是否启用分包优化 }
原则:pages内只容许存放tabbar页面路由,以及各个子包所共有的页面页面,若是有登陆页且不登陆没法进入主页面,该登陆页面路由也应放置在pages路由内
定义:单个模块内的除主包内文件的全部的文件,
好比: 假设一个tabbar模块内本来有index(tabbar页).vue,notice.vue,about.vue这三个页面,将index.vue这个页面路由放置pages.json中的pages数组内,对应的将index.vue放置在项目中的pages目录内
假设notice.vue与about.vue没有在别的tabbar模块中被使用,则应该将notice.vue和about.vue两个页面文件放置在subPackages中
若notice.vue与about.vue这两个页面中有被别的模块使用,则一样应该将其放置在pages主包内,为防止其与其余tabbar页面混淆,应该在pages目录内再单独开辟一个目录专门用于存放共有页
弄懂了以上原则,接下来即可以实践一下了
(pages.json)内新增subPackages字段,与pages同级,一样是数组格式,期内每个对象均对应tabbar内的每个模块,
(项目目录)每个对象都应在项目中生成每个目录,这个目录与pages目录同级
//pages.json "pages":[ //这里仅存放tabbar,以及公共页 ], "subPackages":[ //subPackages数组里的每个对象都表明了对应tabbar模块里的除tabbar中index.vue之外全部的页面,且该数组里每个对象都在项目目录中与pages目录平级 //举个栗子 这里是首页模块,index.vue因为是tabbar页面,故而被放置在了pages.json中,剩余两个文件并无被其余tabbar模块使用,于是被放置在了这里 { "root":"pages_Index", //这里表明根目录的映射,表示在项目中这个模块的根目录也就是上面说的与pages目录平级的目录名 "pages":[ // 这里的pages表示分包内的页面,凡在该子包的pages目录下,均不可被其余子包模块访问 //这里指的是本来从pages页中迁移来的,仅本模块专属的页面,其格式规范遵循tabbar所在pages数组规范 { // 网上有人说path路径必须由pages_Index根目录开始,可是在实践过程当中发现不从根目录开始也能够,缘由猜想是root自己已定义了根目录 // 原目录为: /pages_index/packet/notice path":"packet/notice", "style": { "navigationBarTitleText": "我是子包文件" } }, ] } ]
目录结构以下:
pages.json以下:
这样便完成了配置的第二步
笔者以前一直强调的分包越早越好的缘由就在于此,一但项目到了微信2m限制,则会直接致使项目没法在开发者工具中运行,虽然分包能够在整个项目周期任一进度进行,可是需花费的时间是与项目进度是成正比的,即项目进度越到尾期,则分包须要花费的时间也就越长,笔者对此深有体会(流眼泪.jpg)
若是在项目中末期才进行分包,此时须要开发者站在整个项目角度上,对每一个模块,每一个页面,每一个网络请求都要了然于胸,能够借助于思惟导图工具,将项目全部模块全部页面都列出来,剔除tabbar页面和模块间共有页面,而后将剩余页面填充至指定子包目录下,并在subPackages目录下声明该页面路径,而且,开发者必需要从新定义路由跳转路径以及组件引入方式,这一点极为繁琐,且极易出错形成损失,于是建议开发者在走这一步前预先作好备份。
导入组件路径建议直接更换成以@开头的绝对路径来替换省略号开头的相对路径,防止之后可能再次发生的变动
跳转路由也应换成绝对路径,(路由更换后跳转失败? 请点击这里)
在本过程当中,可能会出现各类引用错误或者没法跳转的问题,此时须要开发者心态平缓,并必定要谨慎检查
若是在开发者工具中运行整个项目显示没有报错信息,则能够在真机调试,若是有短时弹框 “ 加载模块中 ”,则表示分包成功
那么问题来了:我不想用户看到这几个丑陋的字,该怎么作?
出现这几个字的缘由是因为用户刚进入的界面一定是主包,而在用户进入分包的时候,因为分包资源还未下载,因此微信官方便贴心的提示用户正在加载分包资源
笔者:微信我谢谢你呀!(超大声哔哔)
那么接下来要说的,就是关于这类问题的解决办法: 分包预加载
定义:在用户进入某个页面时,同时静默下载跟该页面有关的子包文件
与subPackages平级添加preloadRule对象,
该对象内部的key指的是某个页面路径,也就是当用户进入某个页面时,须要预加载的页面路径,
value
//pages.json //以子包pages_index为例 "subPackages":[ //分包模块 { "root" : "pages_index", "pages" : [ { "path" : "packet/notice", "style" : { "navigationBarTitleText": "我是子包页面"} } ] } ], "preloadRule" :{ "pages/index/index":{ //要进行预加载时用户要进入的页面路径 "network":"all", // 什么网络下支持容许预加载,默认wifi: wifi/all "packages":["pages_Index"] // 要进行预加载的子包名 }, }
一点提示:笔者我的认为这一项有好有坏,由于当开启这一项时,表明着要占用当前页的加载资源速度来换取用户可能要加载的加载页速度,这与使用分包来下降白屏时间的原则格格不入,于是这一点须要开发者根据需求仔细考虑是否值得
若是配置成功,开发者console控制台会输出如下信息:
- 主包能够引用分包内文件,分包仅可引用自身目录内的文件,分包与分包间文件没法互相引用,
- 要清楚的是分包是一种不得已而为之的手段,确保在分包前项目中静态资源已优化完毕,且没有大量注释或无用代码也是一种手段
-------------------------伪装这是一条分割线----------------------------------------------------------
这篇文章是笔者在复盘项目时的心得,不足之处欢迎在评论区指教,不胜感激
以上。