1.Expo 搭建 React-native 项目代码目录分析
2.React Native UI界面还原,原生源码N源组件布局与动画效果
3.Flutter 地图在携程的原生源码N源最佳实践
4.ReactNative资源更新增量包的优化实践
Expo 搭建 React-native 项目代码目录分析
创建React-native项目时,Expo提供了多种工具简化开发过程。原生源码N源根据项目需求,原生源码N源选择不同的原生源码N源模板:空白模板(blank)适合演示、组件预览和个人项目;带有底部tab菜单的原生源码N源源码.apk模板(tabs);需要直接控制原生代码时选择(minimal);遇到未知问题则选择RN方式。[1] React Native的原生源码N源典型目录结构包括以下几个部分:[2]src:存放组件源代码,是原生源码N源项目开发的核心目录。
test:用于编写和运行组件的原生源码N源测试用例。
demo:包含一个独立的原生源码N源Expo项目,App.js是原生源码N源核心文件,通过引用src中的原生源码N源组件进行展示和开发。
其他文件如.eslintrc.js,原生源码N源 babel.config.js, README.md, .gitignore, package.json等,分别负责代码风格规范、原生源码N源编译配置、原生源码N源项目介绍和版本管理。
引入Expo时,需注意src目录与demo目录的配置协调,以确保metro(打包工具)能够正确处理。首先安装Expo CLI,然后创建项目,通过yarn start预览组件。配置metro时,重点在于新版本的metro.config.js,用于添加providesModuleNodeModules,解决src目录依赖的解析问题。[3] 总结起来,开发过程中App.js是关键,负责组件的集成和展示。app.json和package.json分别用于设置应用配置和依赖管理。assets存放资源文件,babel.config.js用于代码转换,index.js是应用入口,metro.config.js负责项目打包,而yarn.lock则保证了依赖版本的一致性。eas.json则提供了EAS平台的云构建和部署选项。每个文件都有其特定的功能,共同构建React-native项目的开发流程。[4]React Native UI界面还原,组件布局与动画效果
React Native UI和写Android XML布局布局在本质上相似,个人感觉差异不大。
在《ReactJS到React-Native,架构原理概述》中提到,在web环境中,React框架,JSX源码通过React框架最终渲染到了浏览器的真实DOM中。而在React Native框架中,JSX源码通过React Native框架编译后,通过对应平台的Bridge实现了与原生框架的通信。如果在程序中调用了React Native提供的API,那么React Native框架就通过Bridge调用原生框架中的方法。底层为React框架,UI层变更映射为虚拟DOM进行diff算法,diff算法计算出变动后的JSON映射文件,最终由Native层将此JSON文件映射渲染到原生App的页面元素上,实现了通过控制state和props的变更引起iOS与Android平台UI的变更。编写的React Native代码最终会打包生成一个main.bundle.js文件供App加载,此文件可以在App设备本地,也可以存放于服务器上供App下载更新。Yoga是一个使用C语言实现的CSS3/Flexbox的跨平台布局引擎,旨在打造一个兼容iOS、Android、钓鱼源码邮箱接口Windows平台在内的布局引擎,让界面布局更加简单。Yoga通过实现许多设计师熟悉的API并对外开放。利用Yoga,目前已经被用于React Native和Weex等开源项目中,虽然只实现了W3C标准的一个子集,但在样式方面也有一定的应用。
核心组件和API在React Native中可以通过reactnative.cn/docs/components/查找。为了给React-Native组件加上样式,需要在JavaScript中添加样式表。Flexbox是构建响应式App的最佳选择,虽然CSS在React Native中的表现不太一致,且React Native并不是为web元素设计的,不能像web应用在html中使用CSS。但Weex在这方面具有优势。React和宿主平台之间的桥接包含了一个缩减版CSS子集的实现,主要通过flexbox进行布局。使用内联样式,通过JavaScript对象进行样式组织,这也是React团队先前在Web环境中推荐的。对于复杂的样式,建议使用StyleSheet.create来集中定义组件的样式,这可以弥补编写复杂样式时不能使用CSS的不便。
RN中的宽高可以直接通过style指定,尺寸是无单位的,表示与设备像素无关的逻辑像素点。在组件样式中使用flex可以使组件在可利用的空间中动态地扩张或收缩。与Android LinearLayout的layout_weight类似,值越大,组件获取剩余空间的比例越多,但RN的优先级高于width。使用flex布局,可以与Android类似地调整组件的优先级。
在动画方面,React Native提供了两个互补的动画系统:用于创建精细交互控制的Animated和用于全局布局动画的LayoutAnimation。Animated旨在以声明的形式定义动画的输入与输出,建立一个可配置的变化函数,通过start/stop方法控制动画的执行顺序。配置动画具有高度灵活性,包括自定义或预定义的easing函数、延迟、持续时间、衰减系数、弹性常数等。配置动画时,可以通过parallel、sequence、stagger和delay组合使用多个动画。默认情况下,如果任何一个动画停止或中断,组内所有其他动画也会停止,但可以设置stopTogether属性禁用自动停止。合成动画值可以通过加减乘除以及取余等运算来创建新的动画值。插值可以在动画属性中设置值变化区间,如在接近特定值时改变动画行为。跟踪动态值可以通过设置toValue来实现,同时跟踪多个值。通过启用原生驱动,动画可以在启动前将所有配置信息发送到原生端,利用原生代码在UI线程执行动画,而无需在两端间频繁沟通,自助下单网页源码从而避免了JS线程被卡住时影响动画的问题。
LayoutAnimation允许在全局范围内创建和更新动画,这些动画会在下一次渲染或布局周期运行,特别适用于更新flexbox布局。使用LayoutAnimation时,注意它对动画本身的控制不如Animated或其它动画库方便,因此在使用时应谨慎考虑。如果要在Android上使用LayoutAnimation,需要在UIManager中启用。
Flutter 地图在携程的最佳实践
随着技术的快速发展,项目设计从单一的 Native 应用扩展到 Native+RN,再到如今的 Native+RN+Flutter。在携程,我们的业务主要基于 Flutter,这就需要在 Flutter 项目中嵌套使用地图。目前,实现这一目标的主要方法有两种:
1. 采用官方 Flutter 地图插件,但可能面临维护成本和定制需求的权衡。为了更好地定制 API 和快速修复问题,我们选择源码集成,主要在 flutter-boost 的混合工程中实践,以单引擎模式接入插件。
源码集成主要分为两个步骤:首先,从官方 demo 中获取插件源码,然后分别在 Flutter 和 Native(iOS/Android)端进行导入。Flutter 端执行 `flutter pub get`,导入插件源码,iOS 与 Android 则导入对应目录的代码。
地图插件的实现基础是 PlatformView,它允许原生组件嵌入 Flutter 页面。插件通过 MethodChannel 与 Native 通信,以 Map 为例,平台View 将 Native 地图嵌入 Flutter,并通过指定 viewId 初始化 BMFMapViewController,处理地图操作和事件传递。
在混合项目中,集成 PlatformView 需要处理不同平台的生命周期同步问题。例如,IOS 页面切换时可能会出现白屏,这是由于 Flutter A 页面跳转到 B 页面时,平台View 的生命周期与预期不符。为解决这个问题,可以在适当的地方调用 `surfaceUpdated` 方法,以确保同步。
Android 地图使用中也遇到过卡死和内存溢出问题。这些通常是由于生命周期管理不当导致的,如 context 对象回收。通过设置 `shouldAttachEngineToActivity` 为 `false`,使 Flutter 引擎独立于 Activity,避免了这些问题。
自定义地图中的 BitMap Marker 时,推荐利用地图插件提供的 iconData 参数,将文本和绘制后传递给 Native。在 Flutter 3 中,要注意 toImage 方法可能在 debug 环境下因为弱引用指针检查而被终止,但在 release 环境下正常工作。
在展示 Marker 时,可能需要调整地图的可见范围,这涉及 iOS 和 Android 的不同计算方式。随着业务需求的迭代,还需考虑地图大小与列表的漳州麻将app源码配合,确保动画流畅。
总的来说,Flutter 地图插件在携程的最佳实践主要围绕如何在混合项目中集成、处理 PlatformView 的生命周期问题、自定义 Marker 和优化地图显示效果展开。通过解决这些问题,我们实现了高效、稳定的地图功能集成。
ReactNative资源更新增量包的优化实践
本文首发于微信公众号“Shopee技术团队”。1.背景Shopee的许多手机应用是原生与ReactNative(下文简称“RN”)的混合(hybrid)应用。在用户打开App时,客户端会发起请求查看是否有新版RN资源。若有,则后台静默下载最新资源,重新加载RN,以实现RN更新。这样的更新过程免却了用户去GooglePlay/AppStore重新下载App的麻烦,也能迅速把最新资源推送给所有用户。
另一方面,RN资源虽会更新迭代,但新旧版的差异其实只占小部分,让用户下载全量资源不仅浪费用户流量,也影响用户对App的使用体验(因为后台静默更新仍然会挤占带宽资源)。
自然而然,我们会想到“增量(差量)更新”,客户端仅下载新旧RN资源的差异部分。这个差异部分汇总到一个文件里,这个文件被称之为增量包(或补丁包)。下载完成并验证补丁包的合法性后,方可与旧版本合并为新版本,以此节约流量。
考虑到Shopee主要市场的网络条件,数据流量的节约尤为重要。但这个增量包应该是怎样的呢?本文会以循序渐进的思路分析各种方案的优缺点,包括Shopee公司内的探索实践过程所产生的方案,以及业界提供的方案,最后提出FolderBsdp算法,对直接资源进行差分,实现增量更新。
2.增量包实践方案进化之路2.1直接传输差异的(原始)文件RN资源包括转译后的JavaScript代码、各语言翻译JSON文件、等媒体资源、配置文件。我们把这些资源称为“直接资源”。它们是RN打包的直接产物,也是日常供客户端调用的存在形式。如果这些“直接资源(原始文件)”在CDN上,保留新旧资源的文件目录,即可对应下载新增的和修改的文件。
其缺点主要有两方面:
1)分散传输易出错如果有新增和修改翻译文件等修改,需要发起多次HTTP请求到CDN下载文件,这样会复杂化更新的异常处理情况,比如部分文件下载过程中断的恢复问题。
2)传输量大费流量和翻译JSON文件用原始文件传输浪费数据流量,因为这些资源本可以被压缩。翻译文件体积较大,但每个版本的修改一般是细微新增若干行,没有必要直传整个文件。因此,所谓传输“差异”的部分,文件级别的随机网名生成源码“差异”颗粒度还是太大了。
2.2文件间的差分算法BSDiff为了避免2.1中的问题,我们引入了差分算法,以实现增量更新。
2.2.1差分算法文件间的差分算法是一种实现增量更新的方法。差分算法的入参是新旧两个文件,其输出是两个文件的差异部分,称为Patch,即补丁包(也称增量包)。
一个差分算法还有与之配套的打补丁算法,其入参是旧文件和Patch,输出是新文件。不同的差分算法各有优劣,体现在差分和打补丁操作的时空复杂度、Patch体积、Patch内容可读性等。
2.2.2Bsdp(BSDiff&BSPatch)算法BSDiff算法是一个非常流行的差分算法,它专注于得到尽可能小的Patch体积(适用于Patch要通过网络传输的更新方式),被GoogleChrome等软件广泛使用,非常适合代码升级这种具有局域性的稀疏的改动。
BSDiff算法开源且免费,用C语言写成,源代码可以在服务端、Android/iOS端执行。BSDiff算法所搭配的打补丁算法BSPatch可以将旧文件和Patch结合,恢复出新文件。BSDiff和BSPatch算法并称Bsdp算法。
2.2.3直接使用BSDiff算法的优缺点对比于“2.1直接传输差异的(原始)文件”,如果只传输BSDiff所生成的差异Patch,的确能够减少传输的数据流量,加快下载过程。但是,它没有解决频繁发起多次HTTP请求去下载各个文件的问题。我们需要一个方法把资源合并起来,一起下载。
2.3压缩资源的BSDiff考虑到各个资源文件分散传输(2.1与2.2)的缺点,改进方式是在编译时把RN各直接资源文件放在一个文件夹里,然后用ZIP工具压缩为一个文件,采用ZIP压缩资源全量包以及压缩资源的Patch来实现初始安装和后续更新。
具体说来,RN打包的直接产物包含了一定目录结构的JS代码、翻译JSON、、配置文件。所有这些文件压缩为一个ZIP压缩包。在App初始安装时,里面有这个ZIP包,以及其解压的RN资源。
在用户使用App的过程中,若有新版RN资源,则会下载对应Patch文件,运用BSPatch算法与先前的ZIP压缩包(客户端打包时并不删除当时RN资源的ZIP压缩包)结合,即可得到新版本的ZIP压缩包,这个新版本的ZIP压缩包保留在用户手机里,以便下一次生成新ZIP包,如此反复,持续更新。ZIP压缩包解压后得到直接资源,即可被使用。
从时间线上来看,这样的更新也就是版本迭代,形成如下图所示的更新关系,称为“RN更新链”。
此方案的优点是克服了分列文件方案的缺点。通过ZIP压缩文件,多个文件合为一体,资源形式变得简单,HTTP请求数也减少了。对于全量包来说,它减少了总体积。Shopee某业务包未压缩时所有资源一共有MB,压缩后约为4MB。
但是,此方案隐藏了一个难以发现的缺陷,使得这一方案存在很大的改进空间。这一缺陷就是ZIP压缩过程影响了文件的样貌,使得新旧文件的差异扩大,由此,ZIP压缩包之间的Patch体积也过大。以下详细解释这一缺陷。
2.3.1BSDiff生成Patch的过程BSDiff属于“区块移动”算法。为了记录新旧文件的差异以便恢复出来,它使用了动态规划算法——最长公共子序列。
对于新文件的内容,它尝试从旧文件找到匹配的最长公共子序列,并记录了新文件的内容相对于旧文件的位置变化,站在新文件面向旧文件的视角,尽可能地用旧文件的内容拼装成新文件。
而对于额外的差异,它记录了差异内容以及其在新文件的位置。这些记录的内容和位置信息经过bzip2压缩后即得到Patch文件。Patch文件包含的复制和插入信息,在运行BSPatch时可以把旧文件变成新文件。
简单的示意图如上。蓝色和绿色区块是相同的内容,但是它们出现在文件中的位置不一样,Patch记录下位置信息。红色的是额外(Extra)的内容,Patch文件记录下其在新文件的位置及其内容本身。这些记录形成的指令让我们用旧文件和Patch文件恢复出新文件。
由此,我们领悟到,对重复内容,记录位置偏移(蓝色、绿色区块)所需要的信息量少;对于额外区块,我们不仅要记录位置偏移,还要在Patch文件里留存其内容本身(尽管可以压缩)。位置偏移所占的Patch文件体积要远小于内容所占体积。额外内容越少(新旧文件越相似),Patch文件体积越小。
2.3.2压缩资源使用BSDiff的缺陷Lempel-Ziv编码算法是ZIP压缩算法的重要环节,它又被称为“滑动窗口压缩”。该算法的核心思想是在之前的历史数据中寻找重复字符串。
但是,并不是一路回溯到文件头,而是考虑到重复内容的局部性,它设定了一个区间(常见是KB)。这个KB的窗口随着编码不断进行而向前滑动。理论上来说,这个滑动窗口(SlidingWindow)如果更大,我们有更大概率找到重复字符串,但这样会增大计算量。KB是ZIP的折中设定。
在上图中,当编码来到“OK.”(右侧,蓝色标记)时,在滑动窗口回溯发现有重复的“OK.”(左侧,蓝色标记)。LZ算法记录下左侧“OK.”相对于当前位置的距离(Distance)和长度(Length),然后再推进到下一个字符(NextCharacter)。在压缩的结果文件中,此处就会保留一个“OK.”,然后用Distance+Length的方式把SlidingWindow里重复的“OK.”表示出来。这样就避免了“OK.”重复出现,节约了体积。若重复字符若更长,压缩效果会更明显。
若这段字符出现了细微修改,LZ算法的编码结果会产生巨大的改动。
考虑上图第二行的情况,若插入了“!”(绿色标记),则编码可能产生两个变化。
第一个变化就是编码时扫描到右侧“OK.”时,其对应的左侧重复字符的Distance发生了改变(Distance值的变化会产生一系列其他副作用)。
第二个可能的变化是因为插入了字符,左侧的“OK.”已经超出了滑动窗口的左沿,因此右侧“OK.”无法找到此重复字符(此处当然在KB滑动窗口内,仅作示意)。
考虑上图第三行的情况,若插入了“!”(橙色标记),则原有的“OK.”重复字符(Literal)不复存在,编码产生了巨大的改动。
此外,在ZIP压缩算法中还有霍夫曼编码环节,无论是字符(Literal),距离(Distance),还是长度(Length),都不会用其真值表示,而是采用了霍夫曼编码,越常出现的就用越短的字符表示,越不常出现的就用越长的字符表示。另外再保留一张霍夫曼编码后的字符与原字符的对应表格。
上面第二行和第三行的情况,会影响到Literal、Distance、Length不同值出现的频率,也就影响到了其对应的编码。这个编码的影响是全局而非局部的。
其他主流压缩算法与ZIP压缩算法原理本质相同,为了追求压缩比,细微的差异也会有全局的影响。
由此,我们可知:压缩不利差分性质。
压缩过的文件有可能破坏了新旧RN资源的字节流的相似性,基于压缩过的文件进行BSDiff计算所得的Patch体积存在进一步缩小的可能。
计算BSDiff基于原始RN资源的字节流是一个值得探讨的方向。
2.4Store文件的BSDiff为了解决2.3存在的缺陷(压缩不利差分性质),我们尝试把包含各文件的直接资源以不压缩的方式合并成一个大文件,让原始字节流以其原有的样貌留在文件中,它还可以“解绑”恢复原有的文件及目录结构。通过这个方法,原始的字节流特征就不会被破坏。我们把这样的文件称之为Store文件,即没有压缩功能的Archive文件。
其主流实现有ZIP的Store模式(也是使用ZIP工具,但是不进行ZIP压缩算法)以及Tar文件格式。ZIPStore模式的资源执行BSDiff算法,(相较于压缩文件)大概%的体积。但是,这一方案也有其缺陷。
2.4.1ZIP的Store模式要生成ZIP的Store文件非常简单,所有的ZIP工具都有Store模式,一般来说是生成ZIP包时把入参布尔值store设置为true,解压/解绑时不需要额外提供参数。考虑到使用ZIP的Store模式主要是因为AndroidSDK原生支持ZIP文件的生成和解压/解绑,因此对于包含许多App的Shopee公司来说是一大优势,不仅节约包体积(重要),还减少协调难度。
精简依赖考量——在客户端,我们尽可能不安装额外的依赖包。
看似是最优解,但在实践尝试中发现此方案有一个问题:ZIPStore文件在各端并不兼容。
具体的问题是,在后端Node.js中,运用通用的archiver库所生成的Store文件不被Android原生的ZIP库识别,无法解绑。这一点在网上也有过广泛讨论,见StackOverflow。
其中提出的解决建议是Android另外装Oracle的ZIP库,这与精简依赖考量相违背,不是优秀的选项。
那么,在Android客户端运用直接资源去生成ZIPStore文件行不行呢?答案是否定的。因为Android客户端生成的Store文件和服务端生成的不同,而服务端的Patch是基于服务端的Store文件求BSDiff所得。哪怕有一个字节的差异,都无法打补丁成功。所以我们不能让客户端去生成Store文件。哪怕我们去掉了平台所特有的metadata,ZIP本身也是非确定性算法(Non-deterministicAlgorithm),这会让打补丁算法失效。所以:
ZIP不确定性——跨平台差异性使得ZIP压缩包或ZIPStore包不能由客户端运用直接资源去生成。
2.4.2Tar文件格式Tar文件格式在类UNIX系统非常流行,是不执行压缩的Archive-onlyFile(本文续称Store文件)。Tar文件格式不可避免地包含各种平台特有的metadata,在一部分平台的库中没有彻底去除metadata的选项,即便可以,Android和iOS客户端也要为此安装Tar文件的解绑依赖包,这与精简依赖考量相违背。
2.4.3Store文件格式难以避免的缺点上文讲解了ZIPStore文件和Tar文件的缺陷,假设我们寻觅到了一个优秀的Store文件格式,它支持跨平台统一的Archive操作,但还是避免不了一个难以接受的缺陷——增大了客户端存储空间的占用。
相比于ZIP压缩文件,Store文件由于未压缩,体积很大。在某些情况下传输全量Store包的流量消耗也就变大了。如果我们对于全量Store包再进行压缩,则给客户端带来了新的复杂度。那就是资源包具有多种格式,有的要解压两次,有许多异常的可能性,这给客户端带来的负担太沉重。我们需要有另外的方法来差分资源。
3.最佳实践方案:FolderBsdp为解决上一章的问题,我们创新性地提出FolderBsdp方案。FolderBsdp是以文件间的Bsdp算法为基础,对有目录层级结构的文件夹进行差分。具体来说,它由FolderBSDiff(求差分)和FolderBSPatch(打补丁)两个算法相结合。
3.1FolderBSDiff的具体算法先比较新旧文件夹的目录结构和内含文件,新文件夹相对于旧文件夹所产生的变动包括五种情况:新增目录、删除目录、新增文件、删除文件、修改文件。
对于新增目录、删除目录、删除文件的情况,记录下对应的操作;对于修改文件,调用BSDiff函数。我们基于直接资源里的每一个文件的内容修改求BSDiff,留下其Patch文件体积足够小,避开了压缩不利差分性质的困境;对于新增文件,则记录下所增文件的相对路径,并拷贝此文件。
我们把这些操作按照一定顺序(新增目录要在最前,删除目录要在最后)汇总到一个JSON文件里。并且把BsDiff求出的各个Patch文件和新增的文件保存下来,这些文件通过ZIP压缩算法为一个ZIP文件,即为FolderBSDiff的Patch文件。这个文件的体积与Store文件之间求BSDiff类似,也同样(相对于ZIP压缩包之间的BSDiff)节约了约%的体积。这个Patch可以用于对应的打补丁操作(FolderBSPatch)。
优点一:在客户端侧打补丁时内存占用低在打补丁操作时,我们需要把旧文件和补丁包加载到内存里,在执行完成前,新文件也在内存里。FolderBSPatch针对逐个资源文件,按顺序串行操作,“化整为零”,相比于ZIP包的BSPatch,内存占用更低,更不影响用户体验。
根据实际测算,相比于ZIP包的BSPatch,使用FolderBSPatch在客户端侧打补丁的内存峰值占用少了%。
内存考量——在客户端侧降低内存占用是一个优点。
在RN资源包更新这个情境中,FolderBSPatch这一优点非常有必要,因为打补丁的过程是在App运行时的后台进行,与此同时用户很可能还在积极使用App。此外,我们预期Shopee主要市场的用户手机内存配置较低。
优点二:节约存储空间在客户端侧,基于FolderBsdp可以舍弃掉储备文件,无论是ZIP压缩资源包,还是上文讨论的Store资源包。
在之前的算法中,因为ZIP不确定性,我们留存ZIP压缩包或Store文件在客户端。文件留存的唯一目的就是为了打补丁,没有其他用处,非常浪费存储空间。
从时间线上来看,根据FolderBsdp也形成了客户端侧的“RN更新链”,如下图所示:
以Shopee内某个App为例,客户端总包体积MB,其中RN的ZIP压缩包约8MB,使用FolderBsdp后,不再需要ZIP包,App也就“瘦身”了。
空间考量——节约掉储备文件所占的体积是一个重要的优点,我们要尽量做到。
优点三:不需要ZIP库在客户端,我们不再需要调用ZIP的解压算法,iOS端也就不再需要依赖ZIP库或其他压缩库(Android内置无法删除)。虽然我们需要引入FolderBSPatch,但其代码不过一百行左右,没有大型依赖,体积远小于ZIP库,符合精简依赖考量。
优点四:附带更精确的MD5校验我们可以把每一个新增、删除、修改文件的MD5值保存在JSON文件中,在打补丁操作时进行校验,更自信地确认我们的操作是正确无误的。
4.FolderBsdp与业界其他方案的对比4.1Google的archive-patcherGoogle考虑到了ZIP压缩文件之间求BSDiff破坏了原始字节流相似性的缺陷(压缩不利差分性质),产生了逐个文件恢复出其原始字节流并且求差异的方案,很好地解决了这个问题。
另一方面,因为跨平台的差异性(ZIP不确定性),此方案不可避免地需要在客户端保留ZIP压缩资源包。
这与我们追求尽可能节约存储空间的目标背道而驰(空间考量),因此不应该被采用。而本文提出的FolderBsdp方案很好地克服了archive-patcher的这一缺点。
4.2其他方案增量更新领域中有另一知名的开源项目,作者使用C++自行编写算法,将目录下各文件以不压缩的状态合并起来进行差分,即本文Store文件思路。FolderBsdp与此方案对比的优点是打补丁时更加节约内存(内存考量)。本文所述的RN资源更新,是在用户活跃使用App时后台静默更新,也考虑到Shopee主要用户群体手机内存配置较低的特点,FolderBsdp算法这一优点很重要。
此外,有方案对差分包的压缩格式进行扩展,使其不局限于ZIP格式,也可以支持其他压缩库。这个灵活性在某些场景适用。但在本文情境中,App的精简依赖考量更加重要。本文提出的FolderBsdp算法利用标准bsdp和AndroidSDK自带的ZIP库,不需要安装其他格式的压缩库。FolderBsdp的补丁包体积与其他压缩格式差异不大。
5.总结本文所介绍的FolderBsdp方案降低了打补丁时的内存峰值,避免了在客户端保留多余的ZIP包占用空间,额外提供了逐个文件的MD5精准校验,无需新增依赖库,因为用各端原生开发语言实现而具有兼容性。兼具各种优点,FolderBsdp成功实现了增量更新功能,是多番探索之下总结出来的RN资源增量更新的最佳实践。
本文作者
Pei,来自Shopee商家服务前端团队。
原文:/post/