Introduction
My XAP file is 5 Mb size, is that bad?
Unfortunately that’s a usual question for lot of new Silverlight developers, … you start coding you Silverlight app everything is easy to do, you can use lot of powerful third parties stuff, and finally you end up with an awesome application that runs quite well under Cassini / localhost, then you a realize that…
There’s only a small issue: the XAP file takes about 5 Mb, will that be a problem once the app (an internet facing one) is on production?
Well... the answer is yes
Does it mean that Silverlight is a bad platform for Internet facing applications?
The answer is absolutely NO.
Then… What’s going on? I’m doing something wrong?
Let’s take a look at what you are deploying: A XAP file is nothing more than a ZIP file that contains a bunch of DLL’s and resources that you use in your application, the more content you add to it the more it will grow.
As thumb rule if an internet facing app contains a XAP file that is greater than 1 or 2 Mb., you should analyze the root causes and low down the size.
Ok, How can I do that?
Let’s analyze two scenarios:
- At early stages, when you are designing / architecting your project.
- When is too late… you have realized that your XAP file is way too big just one week before the going live date !!
Step 1: When you are designing / architecting your project
Things to consider
- Check the size of the application that you want to implement: is it a small app and is not expected to grow in the future? If the answer is no, you should think about chopping your application in modules (XAP’s), each module would contain different application's functionality /modules and they will be loaded on demand. About how to perform this partitioning:
- You can base your app on Prism, a compound of best practices that let you easily chop your app in XAP modules and load them on demand, some resources to start:
- 10 things to know about prism.
- Moving to a module Silverlight Project. Complete tutorial series available here.
- You can load XAP modules using WebClient.Download, and instantiate them using reflection.
- Managing Dynamic Content Delivery In Silverlight Part 1 .
- You can even download single Dll's and instantiate them at runtime (one thing to take into consideration Dll’s are not zipped).
- Load Assemblies on demand.
- How to load them on demand and keep strong typing.
- Before adding any third party component, check the weight it adds to your XAP, if it’s a considerable one, check other components with similar functionality and less weight, or check as well if the download of this component can be performed on demand or background.
- Watch out when using images, videos and other resources, normally you should not include them in your XAP, the usual approach is to download them on demand using webclient download (Sample).
Step 2: When is too late… we deliver in one week
You can still do something:
- First find the root cause: rename your XAP file to ZIP and open it using, for instance, Winzip. Check the size of your projects DLL’s, Resources (images…) Silverlight Dll’s, and third parties DLL’s, this will give you a clear picture of where can be the problem located (usually it’s hard to fill 4 megabytes with own code). As a sample, let’s take a look at a Silverlight app I delivered a year ago, a DB Diagram Schema editor , compiled on version 3, the XAP file takes just 451 Kilobytes, if we analyze the content we find that 76 % of the file belongs to SDK libraries, most of that size is because we are using the Silverlight DataGrid on some application's properties dialogs, we could just defered the load of the assemblies related with the datagrid (loading them in background or on demand) and save more than 100 Kilobytes. Another approach, could be to separate the dialogs that use the DataGrid in a separate module.
- If the audience of your application is global, check as well the time responses (taking into account where is your server located, and the different location of the final users). Using Fiddler you can get a nice simulation.
- Use application library caching (it's just a project setting), by doing this all signed assemblies will be stored in separate ZIP files, this means: first time the user starts the app he will have to download all the content anyway, next time he will have to download only the main XAP file and the rest of ZIP elements will be retrieved from the browser cache (sample ), this solution is interesting if you share that signed assemblies between different Silverlight App’s. If we apply this optimization to the previous DBSchema app XAP it would get down to 156 Kb’s !!
- Load DLL’s on demand, there is an interesting trick to do that keeping strong typing.
- XAP files are cached by web browser as images, you can set a long expiration on your IIS, so first time users will experience the expected download time, but next time there won’t be any download, the browser will just grab the file from cache. One thing to take into account is application versioning, when you setup a new version... How can you ensure the client / proxy associated will get a fresh copy of your XAP? A simple approach is to rename the XAP file or add a version parameter in order to force the browser to download a fresh copy.
- Use Isolated Storage: keep in cache XAP files, DLL’s, resources and application data. This won't enhance the first load of the application, but in subsequent downloads you can check whether the resource is already available on the client local storage and avoid downloading it from the server. Three things to bear in mind: It’s up to you building a timestamp mechanism to invalidate the cached information, by default isolated storage is limited to 1 Mb size (by user request it can grow), and users can disable isolated storage on a given app. More info:Basics about Isolated Storage and Caching and sample.
Summary:
A common mistake when we develop web applications is worrying about performance just on the latest stages of the application life cycle, maybe when is too late, or at least when there is not a clean and easy solution available.
Like in any other web technology, you should keep in mind performance / network foot print on your Silverlight app from day zero. Summarizing:
- Check under which scenarios you application will run, is an internet facing application? An intranet one? Where are located the final users? What bandwidth and response time can you expect?
- Your application architecture / designs should take into account minimizing the network traffic, one week spent at early stages can save months of hacks and customer complains.
- Using Localhost / Cassini is ok for development, but you will need as well a development server to test your application on a real scenario.
- If you are at early stages, it's worth to take your time and deep into Prism and MEF.
- If you are facing the issue late, before applying any workaround / hack, analyze the root cause of the problem and concentrate on solving the offending piece (for instance, I was asked to review a 4 Mb XAP... after the analysis we found that the offending part was resources... the application was storing the photos of all the hospital patients in the application XAP, we moved the images to the server, downloaded them on demand and problem solved!.