Adobe Flex 3 Help

Reducing SWF file sizes

You can improve initial user experience by reducing the time it takes to start an application. Part of this time is determined by the download process, where the SWF file is returned from the server to the client. The smaller the SWF file, the shorter the download wait. In addition, reducing the size of the SWF file also results in a shorter application initialization time. Larger SWF files take longer to unpack in Flash Player.

The mxmlc compiler includes several options that can help reduce SWF file size.

Using the bytecode optimizer

The bytecode optimizer can reduce the size of the Flex application's SWF file by using bytecode merging and peephole optimization. Peephole optimization removes redundant instructions from the bytecode.

If you are using Flex Builder or the mxmlc command-line compiler, you can set the optimize compiler option to true, as the following example shows:

mxmlc -optimize=true MyApp.mxml

The default value of the optimize option is true.

Disabling debugging

Disabling debugging can make your SWF files smaller. When debugging is enabled, the Flex compilers include line numbers and other navigational information in the SWF file that are only used in a debugging environment. Disabling debugging reduces functionality of the fdb command-line debugger and the debugger built into Flex Builder.

To disable debugging, set the debug compiler option to false. The default value for the mxmlc compiler is false. The default value for the compc compiler is true.

For more information about debugging, see Using the Command-Line Debugger.

Using strict mode

When you set the strict compiler option to true, the compiler verifies that definitions and package names in import statements are used in the application. If the imported classes are not used, the compiler reports an error.

The following example shows some examples of when strict mode throws a compiler error:

package {
    import flash.utils.Timer; // Error. This class is not used.
    import flash.printing.* // Error. This class is not used.
    import mx.controls.Button; // Error. This class is not used.
    import mx.core.Application; // No error. This class is used.

    public class Foo extends Application {
    }

}

The strict option also performs compile-time type checking, which provides a small optimization increase in the application at run time.

The default value of the strict compiler option is true.

Examining linker dependencies

To find ways to reduce SWF file sizes, you can look at the list of ActionScript classes that are linked into your SWF file.

You can generate a report of linker dependencies by setting the link-report compiler option to true. The output of this compiler option is a report that shows linker dependencies in an XML format.

The following example shows the dependencies for the ProgrammaticSkin script as it appears in the linker report:

<script name="C:\flex3sdk\frameworks\libs\framework.swc(        mx/skins/ProgrammaticSkin)" mod="1141055632000" size="5807">
    <def id="mx.skins:ProgrammaticSkin"/>
    <pre id="mx.core:IFlexDisplayObject"/>
    <pre id="mx.styles:IStyleable"/>
    <pre id="mx.managers:ILayoutClient"/>
    <pre id="flash.display:Shape"/>
    <dep id="String"/>
    <dep id="flash.geom:Matrix"/>
    <dep id="mx.core:mx_internal"/>
    <dep id="uint"/>
    <dep id="mx.core:UIComponent"/>
    <dep id="int"/>
    <dep id="Math"/>
    <dep id="Object"/>
    <dep id="Array"/>
    <dep id="mx.core:IStyleClient"/>
    <dep id="Boolean"/>
    <dep id="Number"/>
    <dep id="flash.display:Graphics"/>
</script>

The following table describes the tags used in this file:

Tag

Description

<script>

Indicates the name of a compilation unit used in the creation of the application SWF file. Compilation units must contain at least one public definition, such as a class, function, or namespace.

The name attribute shows the origin of the script, either from a source file or from a SWC file (for example, frameworks.swc).

If you set keep-generated=true on the command line, all classes in the generated folder are listed as scripts in this file.

The size attribute shows the class' size, in bytes.

The mod attribute shows the time stamp when the script was created.

<def>

Indicates the name of a definition. A definition, like a script, can be a class, function, or namespace.

<pre>

Indicates a definition that must be linked in to the SWF file before the current definition is linked in. This tag means prerequisite.

For class definitions, this tag shows the direct parent class (for example, flash.events:Event), plus all implemented interfaces (for example, mx.core:IFlexDisplayObject and mx.managers:ILayoutClient) of the class.

<dep>

Indicates other definitions that this definition depends on (for example, String, _ScrollBarStyle, and mx.core:IChildList). This is a reference to a definition that the current script requires.

Some script definitions have no dependencies, so the <script> tag might have no <dep> child tags.

<ext>

Indicates a dependency to an asset that was not linked in. These dependencies show up in the linker report when you use the external-library-path, externs, or load-externs compiler options to add assets to the SWF file.

You can examine the list of prerequisites and dependencies for your application definition. You do this by searching for your application's root MXML file by its name; for example, MyApp.mxml. You might discover that you are linking in some classes inadvertently. When writing code, it is common to make a reference to a class but not actually require that class in your application. That reference causes the referenced class to be linked in, and it also links in all the classes on which the referenced class depends.

If you look through the linker report, you might find that you are linking in a class that is not needed. If you do find an unneeded class, try to identify the linker dependency that is causing the class to be linked in, and try to find a way to rewrite the code to eliminate that dependency.

Avoiding initializing unused classes

Some common ways to avoid unnecessary references include avoiding initializing classes you do not use and performing type-checking with the getQualifiedClassName() method.

The following example checks if the class is a Button control. This example forces the compiler to include a Button in the SWF file, even if the child is not a Button control and the entire application has no Button controls.

<?xml version="1.0"?>
<!-- optimize/UnusedClasses.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="checkChildType()">
    <mx:Script><![CDATA[
    import mx.controls.Button;

    public function checkChildType():void {
        var child:DisplayObject = getChildAt(0);
        var childIsButton:Boolean = child is mx.controls.Button;
        trace("child is mx.controls.Button: " + childIsButton); // False.
    }
    ]]></mx:Script>

    <!-- This control is here so that the getChildAt() method succeeds. -->
    <mx:DataGrid/>

</mx:Application>

The executing SWF file for the previous example is shown below:

You can use the getQualifiedClassName() method to accomplish the same task as the previous example. This method returns a String that you can compare to the name of a class without causing that class to be linked into the SWF.

The following example does not create a linker dependency on the Button control:

<?xml version="1.0"?>
<!-- optimize/GetQualifiedClassNameExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        creationComplete="checkChildType()">
    <mx:Script><![CDATA[
    public function checkChildType():void {     
        var child:DisplayObject = getChildAt(0);
        var childClassName:String = getQualifiedClassName(child);
        var childIsButton:Boolean = childClassName == "mx.controls::Button"
        trace("child class name = Button " + childIsButton);
    }
    ]]></mx:Script>

    <!-- This control is here so that the getChildAt() method succeeds. -->
    <mx:DataGrid/>

</mx:Application>

The executing SWF file for the previous example is shown below:

Externalizing assets

There are various methods of externalizing assets used by your Flex applications; these include:

  • Using modules
  • Using run-time stylesheets
  • Using Runtime Shared Libraries (RSLs)
  • Loading assets at run time rather than embedding them

This section describes loading assets at run time. For information about modules and run-time stylesheets, see the Adobe Flex 3 Developer Guide. For information about RSLs, see Using RSLs to reduce SWF file size.

One method of reducing the SWF file size is to externalize assets; that is, to load the assets at run time rather than embed them at compile time. You can do this with assets such as images, SWF files, and sound files.

Embedded assets load immediately, because they are already part of the Flex SWF file. However, they add to the size of your application and slow down the application initialization process. Embedded assets also require you to recompile your applications whenever your asset changes.

The following example embeds the shapes.swf file into the Flex application at compile time:

<?xml version="1.0"?>
<!-- optimize/EmbedAtCompileTime.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Image source="@Embed(source='../assets/butterfly.gif')"/>
</mx:Application>

The following example loads the shapes.swf file into the Flex application at run time:

<?xml version="1.0"?>
<!-- optimize/EmbedAtRunTime.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Image source="../assets/butterfly.gif"/>
</mx:Application>

The only supported image type that you cannot load at run time is SVG. Flash Player and AIR require that the compiler transcodes that file type at compile time. The player and AIR runtime cannot transcode that file type at run time.

When you load SWF files from domains that are not the same as the loading SWF file, you must use a crossdomain.xml file or other mechanism to enable the proper permissions. For more information on using the crossdomain.xml file, see Using cross-domain policy files.

An alternative to reducing SWF file sizes by externalizing assets is to increase the SWF file size by embedding assets. By embedding assets such as images, sounds, and SWF files, you can reduce the network bandwidth and connections. The SWF file size increases, but the application requires fewer network connections to the server.

For information on loading assets, see Embedding Assets in the Adobe Flex 3 Developer Guide.

Using character ranges for embedded fonts

By specifying a range of symbols that compose the face of an embedded font, you reduce the size of an embedded font. Each character in a font must be described; if you remove some of these characters, it reduces the overall size of the description information that Flex must include for each embedded font.

You can set the range of glyphs in the flex-config.xml file or in the font-face declaration in each MXML file. You specify individual characters or ranges of characters using the Unicode values for the characters, and you can set multiple ranges for each font declaration.

In CSS, you can set the Unicode range with the unicodeRange property, as the following example shows:

@font-face {
    src:url("../assets/MyriadWebPro.ttf");
    fontFamily: myFontFamily;
    unicodeRange:
        U+0041-U+005A, /* Upper-Case [A..Z] */
        U+0061-U+007A, /* Lower-Case a-z */
        U+0030-U+0039, /* Numbers [0..9] */
        U+002E-U+002E; /* Period [.] */
}

In the flex-config.xml file, you can set the Unicode range with the <language-range> block, as the following example shows:

<language-range>
    <lang>Latin I</lang>
    <range>U+0020,U+00A1-U+00FF,U+2000-U+206F,U+20A0-U+20CF,U+2100-U+2183</range>
</language-range>

For more information, see Using Fonts in the Adobe Flex 3 Developer Guide.