Flexmojos. Уменьшаем размер swf-файла подключая flex framework как RSL.

Немного теории

Работа с RSL подразумевает две довольно разные задачи. Одна задача -- собрать проект так, чтобы flex framework подключался как RSL, а не входил в состав swf-файла. Другая задача -- создание собственных RSL библиотек и их подключение. Первая задача проще, ибо библиотеки уже есть. С нее и начнем, а другую задачу рассмотрим позже :)

Итак, RSL суть Runtime Shared Library. Из названия ясно, что это библиотека (library), которая загружается и линкуется во время исполнения (runtime) вместо того, чтобы статически линковаться при компиляции. И она предназначена для совместного использования одновременно несколькими разными приложениями (shared). Впрочем, последнее опционально, можно обойтись и одним приложением :)

RSL бывают трех видов: Standard RSLs, Cross-domain RSLs, Framework RSLs. Но я бы сказал, что двух видов.

Framework RSLs сделаны и подписаны адобом, в них входят классы, составляющие flex framework. И они существуют в виде файлов с расширением swz. Что значит "подписаны"? Это значит, что данные swz файлы подписаны адобовским сертификатом, и поэтому флеш-плеер умеет отличить их от подделки. К примеру, если вы сами скомпилируете флекс фреймворк (со своими модификациями или без), то вы не сможете подсунить это флэш плееру как swz файл (но можете подсунуть как Standard RSL). Взять эти swz негде, кроме как у адоба.

В отличие от них пользовательские RSLs (Standard и Cross-domain) создаются самим разработчиком и существуют в виде swf файлов. Они должны быть на том же домене, что и приложения, их использующие (про кросс-доменные RSL пока говорить не будем).

Фишка Framework RSL в том, что они кешируются независимо от конкретного приложения. Если пользователь где-то загружал какое-то флэш приложение (не обязательно ваше) и с ним загружал такие же swz, какие использует ваше приложение, то эти swz есть у пользователя в кеше. И теперь, когда пользователь добрался до вашего приложения, эти swz не будут грузиться еще раз. И это очень хорошо, поэтому что это позволяет сильно уменьшить размер swf файла и сильно ускорить его загрузку. Чем, собственно, мы сейчас и займемся.

Еще такой нюанс, что Standard RSL будет хранится в кеше браузера, а Framework RSL -- в кэше флэш плеера (под линуксом это тут: ~/.adobe/Flash_Player/AssetCache).

На этом с теорией все, ибо это все очень подробно описано в адобовской документации. А перейдем сразу к практике.

Добываем swz файлы

Сперва нужно решить, какую версию Flex SDK мы будем использовать. Flexmojos нам позволяет выбирать из целой кучи сборок Flex SDK ( вот гляньте сюда, сколько их тут :) Ну и какую версию нужно использовать? Самую-самую последнюю? Однако нет.

Давайте-ка посмотрим вот сюда: Flex 4 Downloads. На момент написания статьи тут лежит Latest Milestone Release Builds версии 4.1.0.16076 и несколько версий Nightly Builds. Нужно скачать любой Flex SDK отсюда. Зачем? Ведь у нас есть Flexmojos и он сам все скачает в свой репозиторий. Однако это нужно, ибо в составе Flex SDK есть swz файлы, а в репозиториях Flexmojos нет. А они нам нужны.

Я использую версию 4.0.0.14159. Более поздние версии требуют флэш плеер 10.1, а у меня он тормозит, виснет, и временами не показывает исключения (особенно сильно тормозит и виснет при работе с веб-камерой). Так что я использую флэш плеер 10.0. Из-за этого и фреймворк использую не самый свежий :)

Итак, у нас есть Flex SDK. Давайте заглянем сюда: flex_sdk_your_version/frameworks/rsls. Вот они родимые :)

datavisualization_4.1.0.16076.swf   480 Kb
datavisualization_4.1.0.16076.swz   285 Kb
framework_4.1.0.16076.swf          1022 Kb
framework_4.1.0.16076.swz           613 Kb
osmf_flex.4.0.0.13495.swf           148 Kb
osmf_flex.4.0.0.13495.swz            96 Kb
rpc_4.1.0.16076.swf                 203 Kb
rpc_4.1.0.16076.swz                 129 Kb
spark_4.1.0.16076.swf               492 Kb
spark_4.1.0.16076.swz               312 Kb
sparkskins_4.1.0.16076.swf           69 Kb
sparkskins_4.1.0.16076.swz           54 Kb
textLayout_1.1.0.604.swf            257 Kb
textLayout_1.1.0.604.swz            154 Kb

Тут и сам флекс фреймворк, и спарк компоненты со скинами, и Remote Procedure Call, и Text Layout Framework, и Open Source Media Framework, и Data Visualization. Каждая библиотека есть в виде swz (подписаная) и в виде swf.

Создаем проект

Теперь создадим небольшой проект. Он будет простенький, типа Hello World. Но мы чутка заюзаем Text Layout Framework и тем самым заметно увеличим swf файл. И потом его уменьшение будет еще нагляднее :)

(Кстати, вот клевый тул, чтобы поиграться с TFL разметкой Text Layout Editor)

Вот будет наше приложение:


<?xml version="1.0" encoding="utf-8"?>
<s:Application
		xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark"
		xmlns:flow="http://ns.adobe.com/textLayout/2008"
		width="400" height="250">

	<s:VGroup>
	<s:Label text="Hello"/>
	<s:Label text="World"/>
	<s:TextArea width="100%" height="100%" text="Hello">
		<s:textFlow>
			<s:TextFlow>
				<s:p>
					<s:span fontSize="29" color="0xff0000">Hello</s:span>
					<s:span fontSize="29"></s:span>
					<s:span fontSize="29" color="0x66ff00">World!</s:span>
				</s:p>
			</s:TextFlow>
		</s:textFlow>
	</s:TextArea>
	</s:VGroup>

</s:Application>

И вот пом проекта:


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>try-flexmojos</groupId>
	<artifactId>flexmojos-swz</artifactId>
	<version>1.0</version>
	<packaging>swf</packaging>

	<properties>
		<flexmojos.version>3.7.1</flexmojos.version>
		<fdk.version>4.0.0.14159</fdk.version>
		<fp.version>10.0.42</fp.version>
		<www.root>/var/www/html</www.root>
	</properties>

	<build>
		<sourceDirectory>src/main/flex</sourceDirectory>
		<testSourceDirectory>src/test/flex</testSourceDirectory>

		<plugins>

			<plugin>
				<groupId>org.sonatype.flexmojos</groupId>
				<artifactId>flexmojos-maven-plugin</artifactId>
				<configuration>
					<output>${www.root}/flexmojos-swz/demo.swf</output>
				</configuration>
			</plugin>

			<plugin>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.4.3</version>
				<executions>
					<execution>
						<id>copy-resources</id>
						<phase>package</phase>
						<goals>
							<goal>copy-resources</goal>
						</goals>
						<configuration>
							<outputDirectory>${www.root}/flexmojos-swz/rsl</outputDirectory>
							<resources>
								<resource>
									<directory>src/main/resources/rsl</directory>
									<filtering>false</filtering>
								</resource>
							</resources>
						</configuration>
					</execution>
				</executions>
			</plugin>

		</plugins>

		<pluginManagement>
			<plugins>
				<plugin>

					<groupId>org.sonatype.flexmojos</groupId>
					<artifactId>flexmojos-maven-plugin</artifactId>
					<version>${flexmojos.version}</version>
					<extensions>true</extensions>

					<dependencies>

						<dependency>
							<groupId>com.adobe.flex</groupId>
							<artifactId>compiler</artifactId>
							<version>${fdk.version}</version>
							<type>pom</type>
						</dependency>

						<dependency>
							<groupId>com.adobe.flex.compiler</groupId>
							<artifactId>asdoc</artifactId>
							<version>${fdk.version}</version>
							<type>zip</type>
							<classifier>template</classifier>
						</dependency>

					</dependencies>

					<configuration>
						<debug>true</debug>
						<targetPlayer>${fp.version}</targetPlayer>
						<warnings>
							<noConstructor>false</noConstructor>
						</warnings>
						<rslUrls>
							<rsl>http://fpdownload.adobe.com/pub/swz/flex/{version}/{artifactId}_{version}.swz</rsl>
							<rsl>rsl/{artifactId}_{version}.swz</rsl>
						</rslUrls>
					</configuration>

				</plugin>
			</plugins>
		</pluginManagement>

	</build>

	<dependencies>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>playerglobal</artifactId>
			<version>${fdk.version}</version>
			<classifier>10</classifier>
			<type>swc</type>
		</dependency>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>flex-framework</artifactId>
			<version>${fdk.version}</version>
			<type>pom</type>
		</dependency>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>framework</artifactId>
			<version>${fdk.version}</version>
			<type>swc</type>
			<scope>caching</scope>
		</dependency>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>spark</artifactId>
			<version>${fdk.version}</version>
			<type>swc</type>
			<scope>caching</scope>
		</dependency>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>sparkskins</artifactId>
			<version>${fdk.version}</version>
			<type>swc</type>
			<scope>theme</scope>
		</dependency>

		<dependency>
			<groupId>com.adobe.flex.framework</groupId>
			<artifactId>textLayout</artifactId>
			<version>${fdk.version}</version>
			<type>swc</type>
			<scope>caching</scope>
		</dependency>

		<dependency>
			<groupId>com.adobe.flexunit</groupId>
			<artifactId>flexunit</artifactId>
			<version>4.0-rc-1.1</version>
			<type>swc</type>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.adobe.flexunit</groupId>
			<artifactId>uiRunner</artifactId>
			<version>4.0-rc-1.1</version>
			<type>swc</type>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<repositories>

		<repository>
			<id>sonatype-repository</id>
			<url>http://repository.sonatype.org/content/groups/flexgroup</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>

	</repositories>

	<pluginRepositories>

		<pluginRepository>
			<id>sonatype-repository</id>
			<url>http://repository.sonatype.org/content/groups/flexgroup</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>

	</pluginRepositories>

</project>

Комментарии по пом файлу:

  • Очень важная настройка -- rslUrls. Это пути, откуда нужно загружать RSL библиотеки. И тут у нас указаны два пути. Первый -- абсолютный путь к библиотекам на сайте адоби (http://fpdownload.adobe.com/...). Второй -- относительный путь. Он тоже нужен на случай, если по каким-то причинам не удалось получить файл с сайта адоби (такое иногда случается).
  • В pom добавлены артефакты, соответствующие swz-файлам, которые мы имеем. У меня добавлены framework, spark, sparkskins, textLayout. Если надо, добавьте rpc, osmf, datavisualization. Для этих артефактов указан scope=caching (кроме sparkskins, где scope=theme).

Сперва соберем приложение без указания scope=caching для артефактов, и поглядим его размер -- 1019 Kb. Неплохо для Hello World :)

Теперь включим scope=caching и посмотрим, что получилось -- 75 Kb. Ага, ну что скажете? Неплохо так похудел swf.

Все хорошо, но, как обычно, есть кое-какие нюансы :)

textLayout.swz помечена другой версией. Поскольку мы не можем задавать rslUrl индивидуально для каждой swz, а задаем общую для всех маску, то нам придется сделать небольшой трюк -- переименовать textLayout_1.0.0.595.swz в textLayout_4.0.0.14159.swz. Конечно, по первому url с сайта адоба она не загрузится, и тут сработает второй урл. Или можно не указывать caching для этого артефакта и получить лишние 250Kb в наш swf (что в общем-то не критично). Еще один вариант -- подключить textLayout.swf как Standard RSL. Но я остановился на первом варианте.

После того, как мы указали caching для артефактов, мы уже не сможем запустить нашу флешку локально. Во-первых, потому что у нас пока нет swz-файлов в папке rsl рядом с нашим flexmojos-swz-1.0.swf (в target). Во-вторых, даже если бы и были, то не загрузилась бы, потому что swf не может загружать локальные ресурсы. Тут нужен веб-сервер и запуск через http://localhost/

Поэтому переходим к следующему этапу.

Развертывание на веб-сервере

Итак, нам нужно развернуть файлы на локальном веб-сервере так, чтобы рядом с swf-файлом была папка rsl и в ней все необходимые swz-файлы. Для начала положим нужные нам swz в папку src/main/resources/rsl. А понадобится нам следующие:

framework_4.0.0.14159.swz
spark_4.0.0.14159.swz
sparkskins_4.0.0.14159.swz
textLayout_1.0.0.595.swz (который мы переименуем в textLayout_4.0.0.14159.swz)

Затем воспользуемся maven-resources-plugin и попросим его скопировать эти файлы в ${www.root}/flexmojos-swz/rsl. Обязательно нужно отключить filtering, иначе плагин попортит нам swz и они перестанут загружаться.

Затем добавим в configuration параметр output, который скажет компилятору куда класть swf файл.

В обоих местах мы используем переменную ${www.root}, которая указывает на рут локального веб-сервера. В данном случае эта переменная определена прямо в пом, но на самом деле такие параметры лучше выносить в .m2/settings.xml, потому что они будут отличаться на разных машинах у разных разработчиков.

Ну и все, теперь mvn install и можно открывать в браузере http://localhost/flexmojos-swz/demo.swf и любоваться :)

Проект можно скачать тут.

Comments

Ты показал не все депенденси в поме. А так былобы хорошо заходить на твою страничку и копипастить. Удалять не добавлять.

yzh44yzh's picture

Не, зависимости указаны все.

Я именно такую цель и ставил -- чтобы можно было скопипастить пом и он сразу заработал у всех. Для этого и проекты целиком выкладываю, ибо не в одном только поме дело.

В данном случае проблема можеть быть в переменной ${www.root}. Там указан путь /var/www/html, а такой путь не на каждой машине есть :)

Если у тебя проект не собирается, пришли, плз, мне на мыло, что мавен выводит в консоль.

По умолчанию rslUrls равно /{contextRoot}/rsl/{artifactId}-{version}.{extension}
То есть если вы не используете и не хотите использовать fpdownload.adobe.com, то и указывать ничего не надо.
Для веб-сервера — WAR — вручную ничего копировать не нужно, достаточно заклинания copy-flex-resources. Таким образом, зачастую (и в моем проекте так и есть), достаточно лишь указать scope для артефакта и все. Но это мелочи — по существу добавить нечего, спасибо :)

yzh44yzh's picture

Еще один нюанс: в оригинальных swz файлах имя артефакта и версия разделяются подчеркиванием, а в умолчальном rslUrls дефисом. Этот нюанс можно не заметить и не понимать, почему swz не грузятся.

Так что нужно либо указать явно rslUrls, либо не забыть поправить имена всех swz файлов :)

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
question for bots )
Image CAPTCHA
Enter the characters shown in the image.