Flex is great, but it isn't a server technology. There, I said it.
I was very stubborn when it came to using Flex. There were a variety of reasons that I've never tried to build anything substantial with the technology. One of them was the apparent disrespect to Flash Developers. The other was the idea that I had to run Flex on a server. The last was the price tag. There were some others, but those were the major three for me personally.
As a long time Flash Developer I've seen the birth and rapid growth of "Rich Internet Applications." From smart clips came components, then the v2 architecture, and now Macromedia has an entire RIA framework available through Flex, but somehow along the way the Flash Developers got left behind. Maybe not officially, but it seems that way. In a way, we were the ones that drove the creation of Flex in the first place.. but so what? It wasn't long ago that Flash MX 2004 Professional was touted as the tool for developing Rich Itnernet Applications. Then Flex came along with an improved workflow and upgraded component set, and now Flash has gone the way of designers.
So where does that leave the Flash Developers? Jesse had an interesting take on this a few months ago. Times change, and it looks as though Flex is going to be the future of RIA development. Is it inevitable? Who knows, but for Flash Developers, I suppose we'll just "keep on keepin' on," as they say. There are still a ton of things I would favor Flash for, but for applications I don't think Flex can be beat. Aral would agree, I'm sure. Flex is worth learning because it really does improve how RIAs are built, but I'm still partially stuck on the pricing. The time saved should pay for the price tag, but you have to make a long term commitment to it for it to pay for itself.
Anyway, I'm not trying to get philosophical or anything. I've avoided Flex long enough, and now that I've started to use it there was a major problem I needed to solve right out of the starting gate. Flex should not be server-side technology. Period.
In my eyes, Flex is and should be just a compiler. The MXML markup is converted to ActionScript, run through some magic, and *poof* we get a .swf file. We all know that .swf files run in the Flash Player which is all client side technology. So why is a server necessary? It was probably a strategic move on Macromedia's part, like how Generator was Enterprise as well. After all, no one would pay then of thousands of dollars for a compiler.. but when it's bundled as a server and labeled Enterprise, the wool is pulled over the eyes. Needless to say I disagree with the Flex pricing model / server strategy, but I've already mentioned that.
Anyway, on to the good stuff. If you're like me then you don't think Flex should be running on the server at all, and it's actually not that hard to get around this. In the installation directory there are two jar files, mxmlc.jar and compc.jar, our compilers. The former produces .swf files form .mxml files. The later produces .swc files. We can invoke these compilers directly giving them appropriate input, and deploy the .swf output to our server.
This technique is similar to what Ted posted about in scaling Flex, but goes one step further in that it doesn't require flex running at all, not even on localhost.
Below is my ant build.xml file for automated precompiling of Flex applications. You'll need to have version 1.6+ of ant to use it since I'm using the new "macrodef" tag. If you want to build everything, you can run "ant all", otherwise just configure your modules / libraries and you can build them one at a time or in groups ("ant library1", "ant module1", "ant libraries", "ant modules" etc).
This is probably not just a copy and paste solution - you'll at least need to configure the libary / module sections, but also note the path for the Flex installation directory and also the path for the WEB-INF stuff. I just copied the WEB-INF directory into /etc of my project directory and went from there. Make sure your flex-config.xml file has the right paths as well. Watch out for "webroot" in the maskeswf macro as well, and also careful of the path where rsl's will be located on the server (currently I just use "libs"). Make sure the library destination jives with the url in your .sws files.
Anyway, here's the script. Comments are appreciated..
<project default="all">
<property name="flex.dist.lib" value="C:\Program Files\Macromedia\Flex\lib" />
<property name="flex.compc.jar" value="${flex.dist.lib}\compc.jar" />
<property name="flex.mxmlc.jar" value="${flex.dist.lib}\mxmlc.jar" />
<property name="app.dir" value="." />
<property name="config.xml" value="${app.dir}/etc/WEB-INF/flex/flex-config.xml" />
<property name="src.dir" value="${app.dir}/src" />
<property name="dest.dir" value="${app.dir}/bin" />
<property name="library.dest.dir" value="${dest.dir}/libs" />
<target name="init">
<!-- create directories -->
<mkdir dir="${dest.dir}" />
<mkdir dir="${library.dest.dir}" />
</target>
<!-- macro to easily create an rsl -->
<macrodef name="makelibrary">
<attribute name="library" />
<sequential>
<!-- compile the shared library -->
<java jar="${flex.compc.jar}" dir="${app.dir}" fork="true" failonerror="true">
<arg line="-flexlib '${flex.dist.lib}' -configuration
${config.xml} -webroot . -o ${src.dir}/@{library}.swc ${src.dir}/@{library}.sws" />
</java>
<!-- extract the .swf from the .swc for the library -->
<unzip src="${src.dir}/@{library}.swc" dest="${src.dir}">
<patternset>
<include name="**/*.swf" />
</patternset>
</unzip>
<!-- delete the .swc -->
<delete file="${src.dir}/@{library}.swc" />
<!-- rename and move the extracted library.swf to the name of the library -->
<move file="${src.dir}/library.swf" tofile="${library.dest.dir}/@{library}.swf" />
</sequential>
</macrodef>
<!-- macro to convert .mxml into .swf -->
<macrodef name="makeswf">
<attribute name="module" />
<sequential>
<!-- might need to watch out for webroot here... -->
<java jar="${flex.mxmlc.jar}" dir="${app.dir}" fork="true" failonerror="true">
<arg line="-flexlib '${flex.dist.lib}' -configuration
${config.xml} -webroot . -o ${dest.dir}/@{module}.swf ${src.dir}/@{module}.mxml" />
</java>
</sequential>
</macrodef>
<!-- individual library targets to build one at a time -->
<target name="library1" depends="init">
<makelibrary library="Library1" />
</target>
<target name="library2" depends="init">
<makelibrary library="Library2" />
</target>
<!-- group libraries target to build all rsls used -->
<target name="libraries" depends="library1,library2">
</target>
<!-- individual module target to build one at a time -->
<target name="module1" depends="init">
<makeswf module="Module1" />
</target>
<target name="module2" depends="init">
<makeswf module="Module2" />
</target>
<!-- group modules target to build all .swf files in an app -->
<target name="modules" depends="module1,module2">
</target>
<!-- group target to build all parts of an app -->
<target name="all" depends="libraries,modules">
</target>
</project>