Is swf size a major concern for you? Do you want to reduce the start up time for your applications?
If yes, read on..
What’s in the swf?
If you think your swf is bigger than you expect, it would be helpful to know what’s in your swf. When you compile your swf, the flex swc(s) are in the library-path, and so when your app uses a flex component it gets linked into your swf file. Not just that, any component on which the component your app uses depends will also get linked into your swf. So if you use a mx.controls.Button in your app, your swf will have the ABC (ActionScript Byte Code) for Button and also the ABC for classes that are used by mx.controls.Button (like mx.core.UIComponent etc.). So as you write your app the more components you use, the bigger your swf gets. Also in addition to the byte code, if you use embedded fonts or images that adds to the swf size.
Also MXML is a convenience feature, so while it speed up the development time, it also adds to your swf size as compared to a pure action script application. To see how much code the compiler generates in the background for your mxml files, try compiling with the -keep flag.
How to create smaller swfs?
Your really want to create rich beautiful application and leverage the components provided by Flex, so stripping down the components from your apps is not a viable option. But there are few other options that you can consider:
-
Leverage the player cache by using RSLs
Break your app into Modules
Embed fonts into Modules
Load assets at Runtime
To make it easier to digest, I will cover each of the above in separate posts. So for now lets look at the 1st option (“Leverage the player cache by using RSLs”) which gives the most bang for the buck.
What is RSL?
RSL (abbreviation for Runtime shared libraries) are libraries that you can preload (a Flex application has 2 frames and the RSLs get loaded in frame 1) before loading you application. But the real benefit of RSLs is not that you can preload them, but that the RSLs get cached and when cached they need not be re-downloaded. The runtime shared libraries were added to the Flex SDK starting from Flex 3 and can be found under <sdk folder>/frameworks/rsls folder. The RSLs come in two flavors signed (*.swz) and unsigned (*.swf). The RSLs can be signed by Adobe only, so you can not sign your custom RSLs.
One major difference between the signed and unsigned RSLs is the caching mechanism. The unsigned RSLs are cached in the browser cache and will get cleared when the browser cache is cleared, but the signed RSLs is cached directly by the flash player and it doesn’t get cleared when the browser’s cache is cleared. This is really really important and it implies, that if your users have the signed RSLs in their player’s cache then they don’t need to download it again. Its like the RSLs becomes part of the player.
How to use the RSLs?
In order to use the rsls for you applications, you need to do two things:
-
1. Compile your app with the -runtime-shared-library-path option
2. Deploy the rsls as per the location specified in the rsl-url
The -runtime-shared-library-path has the following format:
-runtime-shared-library-path [path-element] [rsl-url] [policy-file-url]
where
[path-element] is the location of the swc for which you want to use the rsl.
[rsl-url] is the url from which the rsl will be loaded. This can be absolute url or it can be relative path to your swf.
[policy-file-url] url for the crossdomain.xml – in case the rsl is being loaded from a different domain.
Here is an example for compiling an app using framework.swc as rsl:
./mxmlc -runtime-shared-library-path=<sdk-root>/frameworks/libs/framework.swc,framework_4.0.0.7217.swz myapp.mxml
in the above example there is no policy-file-url because the rsl location is same as the application swf. And in this case the rsl need to be present in the same directory as the swf file.
Another way of doing this is to use setting from flex-config.xml. The rsl configuration is present in the flex-config.xml it looks like:
<!– runtime-shared-library-path: specifies a SWC or directory to link against and an RSL URL to load with optional failover URLs –>
<runtime-shared-library-path>
<path-element>libs/framework.swc</path-element>
<rsl-url>framework_3.2.0.3958.swz</rsl-url>
<policy-file-url></policy-file-url>
<rsl-url>framework_3.2.0.3958.swf</rsl-url>
<policy-file-url></policy-file-url>
</runtime-shared-library-path>
<!– static-link-runtime-shared-libraries: statically link the libraries specified by the -runtime-shared-libraries-path option.–>
<static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
Above is an example from from the flex 3.2 build (3.2.0.3958). If you rely on the setting from flex-config.xml, then you need to make sure that the rsl is deployed to the location (rsl-url) specified in the flex-config.xml (in the above example it is required in the same location as the swf). And you need to make sure that static-link-runtime-libraries is set to false (as against to the default (true) in the flex-config.xml). So you can simple compile using:
./mxmlc -static-link-runtime-shared-libraries=false myapp.mxml
Or you can also use Flex/Flash Builder to do the job. You can configure your application via the project properties to use RSLs. Here are the steps:
-
1. Right Click on the project and go to properties
2. Choose the build path and select the tab for Library Path
3. Expand the library that you want to use as RSL and go to the link type.
4. Double click on the link type to open the library path dialog.
5. From the drop down choose linkage as “Runtime shared Library” (you may have to unselect the checkbox to enable the drop down)
6. The list in the library path dialog contains the rsl-url(s) in the order in which the app will try to look for the RSLs
7. You can add new by clicking on the “Add” button which will open up the RSL url dialog
8. Also you can perform other operations (“Edit/Remove existing or change the look-upRSL load order using Up/Down buttons).
It may look a bit complex (if you are looking at RSLs for the first time) but it actually is quite simple (I promise)
What do my users need to do?
Nothing. Really nothing !! (As long as they have flash player 9.0.115 or above).
If you setup for signed rsl only then your users will need flash player 9.0.115 or above. But if you set up an unsigned rsl as a fall back url (to the signed rsl) then nothing required at all.
BTW, the penetration for Flex framework RSL is already pretty high.
For example, if you can see the application below you already have the signed rsls cached for the Flex SDK 4 build.
The simple (tiny) app above is 210 K when the libraries are linked in, but reduces to 68 K with the RSLs. So for a medium size app you can easily save 500+ K just by using framework.swc as an RSL.
And the flex-config.xml that I used to build the app can be found here and the RSLs are hosted by Adobe. So if you are using Flash Builder beta build, feel free to use this flex-config.xml and build you app using the hosted RSLs.
What next?
Play with the RSL feature (if you haven’t already) and if you are using Flex 4 beta you should try the Adobe hosted RSL (the flex-config.xml you can use is present here)
If you face any issues feel free to log bugs at http://bugs.adobe.com/flex or feel free to drop comments here (but logging bug is a better option).
Since the beta release Alex Harui has done a lot of work to reduce the size of frame 1. What this means is for RSLs is a simple applicatin can be reduce to around 35k instead of 68k.
Yes, that’s true. Thanks for pointing this out, Darrell !!
The initial check-in for frame1 cleanup (by Alex) was in svn revision 7163. So that change is available in the latest nightly builds for the Flex SDK. The latest nightly builds can be downloaded from http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4
I am using Flex 4 and tried the flex-config.xml you have linked.
First I had to copy the flex-config.xml into 4.0.0/frameworks directory and I named it flex-config_rsl.xml.
When I compile against this flex-config the compiler can’t find the locale I am using in my project.
The error is: [mxmlc] Error: Unable to resolve resource bundle “boss” for locale “en_US”.
Any hint?
Nice to see an example for Adobe hosting the RSLs.
I’d like to hear more about what’s the fall back if (say) Adobe is overloaded – specifying your own server as a backup, for instance.
I’d also like to know if older Flex versions will be hosted here too (i.e. http://fpdownload.adobe.com/pub/swz/flex/3.3.0.4852/framework_3.3.0.4852.swz is 404 at the mo).
@Soenke,
Can you make sure that the folder containing the resource bundle is in the source path?
Also the flex-config.xml attached to the post is for the beta1 build. And you need to replace the existing flex-config,xml with attached one.
Thanks,
Gaurav
@Tom,
In the example flex-config.xml there is no fall back, but I believe the (default) fallback would be a relative location (i.e relative to the application swf). So you will have to deploy the fall back RSL to where ever you are hosting your application.
Also once the signed RSLs are cached, the application doesn’t need to go back to the hosted location to re-fetch the RSLs. So I don’t see Adobe hosted site getting overloaded.
I am not sure about the hosting of RSLs for the older version.
Thanks,
Gaurav
[...] Creating smaller SWF’s (3 part) [...]
> [rsl-url] is the url from which the rsl will be loaded. This can be absolute url or it can be relative path to your swf.
I wish that were the case. Unfortunately, the relative path is to the HTML, not to the SWF.