In a mixed development scenario ,Flutter The slightly larger package increment has always been criticized by everyone , also Google The official made it clear that Flutter No support for dynamic , And now Flutter SDK The government has not yet provided a customized solution . So I want to lose weight , Then you have to do it yourself .
The so-called package reduction , The premise is that you have to know what the content of the product is ？ What parts of the product can be reduced ？ How do we add back the subtracted part ？ So this article will focus on “ Product analysis ” And “ Package reduction scheme ” Two topics are discussed respectively iOS And Android At both ends Flutter The principle and scheme of packet reduction .
that , First from iOS Let's start .
notes ： The data and code fragments in this article are all from a project based on Flutter 1.17.1 Of Flutter Module stay Release（AOT Assembly）Mode Next, the product after construction , Without any compression .
We know how to use
flutter build ios-framework You can put a Flutter Module Build into a Framework for iOS Host integration , This kind of integration is called product integration , So this “ product ” Namely Flutter product , It consists of the following parts ：
After the production , We can display the volume of each part at the terminal , Finally, tidy up iOS End Flutter The structure of the product is shown in the figure below ：
It should be noted that Mac Finder The volume shown in will be too large , The conversion ratio is 1000 Instead of 1024, We need to use the command line to get the displayed volume and then calculate the real volume manually .
Besides ,Engine The volume of the product we choose is profile Pattern （arm64+arm32） The volume at the bottom , because Flutter 1.17.1 release There is bug,bitcode Can't be compressed , The resulting volume has 351.47 MB, The impact analysis . Specific reasons can be seen. ：Flutter app size is too big · Issue #45519.
There are two basic ways to reduce packets ：
In view of the product structure summarized in the previous paper, we realize the product packet reduction , First of all App.framework Medium App part .
Before we talk about the plan , Let's see App.framework Under the App How it was built , As shown in the figure below ：
First ,frontend_server Will Dart Source code compiled into an intermediate dill, We can also achieve the compilation effect by running the following command ：
app.dill It's binary bytecode , We go through string app.dill You can see that it's actually Dart The product of code merging ：
and Dart Provided in development mode Hot Reload In fact, it's just by passing the changed code through frontend_server Compile to get the new kernel（app.dill.incremental.dill）, adopt WS Submit to Dart VM Update And then we'll do the whole tree Rebuild, So as to achieve Hot Reload.
After that, it will pass through the two platform sides gen_snapshot Compile to get IL Instruction set and optimization code , Finally, output the assembly product . The assembly product is passed through xcrun Tools get single architecture App product , Last pass lipo Get the last two ARM Architecturally App product . therefore , What we're showing here App.framework Under the App The volume of is dual architecture .
ARMv7: iPhone 5s Previous iOS equipment . ARM64: iPhone 5s And after that iOS equipment .
next , We will explain how to reduce the volume of the product from two aspects of deleting product and removing product .
This part of the volume is Dart Code AOT After the product , It's bigger , It's our focus in the process of package reduction .
According to the basic method of packet reduction mentioned before , Let's try it first “ Delete product ”, Let's see what can be deleted directly , Use Flutter The volume analysis tool provided can directly get the volume diagram ：
We found that there are two libraries that are not used in the business , Just delete the dependency .
Besides, there are some optimizations , Can help us reduce code size ：
Besides , We can also delete some symbols to achieve packet reduction effect
notes ：dSYM Is save 16 Binary function address mapping information transfer file , Including our debugging symbols, Used for analysis crash report file , Parse out the correct error function information .
next , Let's see how to achieve “ It's a product ”, Then you need to be right App.framework/App The content of this article is analyzed in detail . We said it was Dart Code AOT After the product , you 're right , Because it's mainly made up of four AOT Snapshot Library （snapshot） form ：
See the official website for details Wiki In the introduction ：github.com/flutter/flu…
There can be many in the same process Isolate, But the two one. Isolate You can't share the heap of .Dart VM The development team has long considered the issue of interaction , So I designed a VM Isolate, It's running on UI In the thread Isolate A bridge of interaction between .Dart VM in isolate The relationship between them is shown in the figure below ：
therefore isolate Corresponding AOT Snapshot Namely kDartIsolateSnapshot, It is divided into instruction segment and data segment ;VM Isolate Corresponding AOT Snapshot Namely kDartVmSnapshot, It is also divided into instruction segment and data segment .
Based on the above analysis ,App.framework We can further split it into the following figure ：
We know App Store Audit regulations do not allow dynamic distribution of executable binary code , So for the above 4 A snapshot , We can only distribute the content of the data segment （kDartIsolateSnapshotData And kDartVmSnapshotData）, And the content of the instruction segment （kDartIsolateSnapshotInstructions And kDartVmSnapshotInstructions） It will remain in the product .
that , Where are we going to separate this snapshot Library ？
stay Dart VM Data loading phase at startup , As shown in the figure below , modify settings The read path of the snapshot library is OK ：
The specific implementation after modification is not explained in this paper , stay 《Q Live broadcast Flutter Package clipping scheme (iOS)》 This article has a detailed introduction to code modification .
flutter_assets yes Flutter Module Local static resources used in , For this part, we can't “ Delete ” The only way is “ Norway ”, We have two options to It's a product —— The conventional solution is still Dart VM Start the data loading phase to modify settings Inside flutter_assets route , To do remote loading , Normally we can remove it in this way flutter_assets 了 .
So is there any way not to modify Flutter Engine Code removal flutter_assets？ yes , we have , have access to CDN picture + Disk caching + Preloading The same effect can be achieved by the combination scheme of , Steps are as follows ：
precacheImageMethod pair CDN Images are preloaded .
This scheme is a little troublesome , And we have to distinguish the environment , Therefore, it is suggested to revise Flutter Engine To achieve remote loading flutter_assets.
icudtl.dat It's an international support data file , It is not recommended to delete it directly , It's the same as the above It's a product The plan is the same , stay Dart VM Data loading phase modification at startup settings Inside icudtl.dat route （
icu_data_path） To achieve remote loading ：
This part is Flutter Engine （C++） The compiled binary product of , It's the largest part of the product , At present, we refer to the sharing of byte beating 《 How to reduce proximity 50% Of Flutter Package volume 》, At present, there are two parts that can be optimized ：
Flutter Engine Use LLVM Compile , Among them, link optimization （LTO） There is one Clang Optimization Level Compile parameters , As shown in the figure below （ stay buildroot in ）:
We will be here iOS Platform Engine Compile parameters from -Os The parameter is changed to use -Oz Parameters , In the end, it can reduce 700 KB Left and right volume .
And there are two parts of engine tailoring that can be cropped ：
attach : stay github.com/flutter/flu… Another aspect of compiler optimization is mentioned in , Function compilation optimization . The same addition function ,Dart After compiling, there are 36 Orders , and Objective-C Only 11 Orders ,36 There is a head in the command 8 Bar and tail 6 The alignment command of the bar , It can be removed , There is 5 The stack overflow check can also be removed ,** namely Dart The compiled 36 Instructions can be optimized to 13 Orders .** We need to wait here Google It's official to optimize .
After modification, we need to compile the engine , First of all, let's introduce Flutter Engine Tools needed to compile ：
The compiler tools are described in detail Flutter official Wiki：Setting up the Engine development environment - Flutter wiki
Specific compilation is divided into sa, First create a .gclient file , To pull the source code and all the corresponding dependencies , As shown in the figure below ：
The second step , perform
gclient sync Download dependency .
It should be noted that the above changes are dependent on （ Such as buildroot,skia etc. ） Not the source code , So we need to fork One copy flutter engine, Then change the dependence first and then , Get the corresponding dependency commit Fill in the number engine Of DEPS In the document , Then submit the code and get engine The latest in the warehouse commit Number , Fill in .gclient In file .
The third step , Use ninja coordination gn Generated configuration file to compile engine, What platform architecture do you want to compile engine Just use gn Generate a configuration , after ninja Just compile . As shown in the figure below ：
Final , We're going to get a couple of （ Different platform architectures ） The custom of Engine, And it's easy to use them , Directly replace the local Flutter SDK Medium Engine that will do .
After the above steps for each product content packet reduction processing , Our final product architecture is shown in the figure below ：
iOS App The volume of view is divided into the following methods , The sizes we get are all different ：
The first way is to look at the local build ipa The following analysis report , Two volumes will be provided in the analysis report , But it's important to note that they are all unencrypted Of ：
But upload App Store After that, it will be encrypted , So you want to know the last volume that the user sees , Need to upload App Store Check the report , The report here also provides two volumes , As shown in the figure below ：
Users end up in App Store To see is Install Size.
notes ： But there is an exception , That is to use Web Browser login App Store To view the App Volume , The volume that was shown at that time Download Size, because Apple I don't think what you're focusing on right now is installation footprint .
We use the blank project as the host project to upload App Store see Install Size, Find out App Volume from 18.7MB Reduced to 11.8MB.
Android The side reduction package is relatively simple , Because no App Store The audit regulations of the company limit , All products can be removed roughly and distributed dynamically . We're still made up of products 、 Package reduction scheme 、 Let's see the effect of package reduction Android On the side Flutter Package reduction .
First let's take a look Android End Flutter Module product （Release） Compilation process , and iOS equally , Is still Dart Source code and Engine Two parts of the product make up ：
The end product flutter.gradle It includes ：
among ,flutter.jar Also contain libflutter.so,icudtl.dat With some Java file , and libflutter.so It's the product of the engine ,icudtl.dat It's still an international support document , The last ones Java Is exposed to business side calls Flutter The interface of .
The composition of key products is shown in the following table ：
libflutter.so It's an engine product , We can still do tailoring , But it's no longer necessary , because Flutter The product is in Android The end can be distributed completely dynamically . Steps are as follows ：
The specific code will not be demonstrated .
Using blank project as host , Measure before and after package reduction APK The size of , You can find 6.2MB Of Flutter The volume of the product can be completely subtracted .
That's double ended Flutter Package reduction scheme , The content is relatively simple , All of them refer to the steps of predecessors and the effects obtained from practice step by step , Therefore, it is strongly recommended that readers extend their reading to the two articles at the end of this article , As a further study to deepen the understanding of .
Reference article ：