Reducing .XAP file size? - silverlight

I created a customized version of the Silverlight Player. After building/compiling, the .XAP which gets pushed out, it ends up being over 700KB.
I'm not too sure why it's doing this because I'm not adding any new resources. All my changes have all been in the code.
Is there any way to reduce the file size?

You are probably including DLLs you did not intend to. The Copy Local option for DLL references you add is True by default.
A XAP file is just a ZIP file with a different extension so the first thing to do is unzip it and take a look at what is included.
You can use a better Zip program to recompress the XAP file, but that will only gain you another 10%-20% at best.
If it turns out you are really just concerned about initial load time vs. total load time you can load an initial (small) bootstrapper to update the display while loading subsequent modules dynamically (look at PRISM and MEF).

You can check the "Reduce XAP size by using application library caching" option.
By default any system dlls that your application uses will be included in the XAP file. By checking this option they are downloaded as separate zip files.
This won't reduce the total size of the files that your application downloads, but will mean that when you publish an update your users won't have to download all the system dlls again - they'll already have these in their local cache.
This option is primarily used in applications that are split across several XAP files to ensure that only one copy of the system dlls are downloaded for the whole application.

Related

The XAP file not exist in Temporary Internet Files

When the Silverlight application is loaded , I expect that Xap file should be in Temporary Internet Files, but can not find it, how can I make sure that my default path and do I have any setting to change this path and is it possible to run silverlight application without Xap file. I mean the Framework loads the Xap file in memory and stores the Xap file in Temporary Internet Files for future use ?
For in-browser applications the plugin relies on the browser's cache ("temporary internet files" in the case of internet explorer). For out-of-browser applications the xap will be stored in a file called application.xap in .../AppData/Local/Microsoft/Silverlight/OutOfBrowser/. or similar.
I'm not sure why you couldn't find it in IE's cache. I clearly see xaps cached in Chrome which is what I mostly use.

How to stop Silverlight xap files including "Copy Local=False" dlls?

In the past I've used the solution outlined in the following URL to avoid multiple downloads of 3rd party dlls in modular Silverlight applications:
How to optimize the size of silverlight XAP file by removing common files?
However I am working on a Visual Studio 2010/Silverlight 5 solution application where this is not working.
I have a PRISM module let's call it Parent1.csproj that has no references to my 3rdParty dlls but it does have a reference to two other project files which reference the 3rdParty dlls child1.csproj and child2.csproj
child1.csproj and child2.csproj both have "Copy Local" set to false for 3rdParty.dlls but in spite of this the .xap file for Parent1.csproj contains the 3rd party dlls.
If I set child1.csproj and child2.csproj references in the Parent1.csproj file with "Copy Local" set to false then I get a dramatically reduced xap file with no 3rd party dlls but also none of the other code in the child projects that I actually need to be able to run.
It seems as if included project files get their "Copy Local" setting ignored and use the parent "Copy Local" setting instead, and there's no way for me to exclude those 3rdParty.dlls
Have I missed something subtle here? Is there some other way I can avoid downloading those 3rdParty.dlls in multiple modules when the shell application has already downloaded them?
I'm not 100% sure why this problem occurs, but it is related to Prism. The way we've solved it is add references to all the startup project and each of the sub projects even though they're not directly referenced but that project.
Make sure that the "Reduce XAP size by using application library caching" is enabled for all your projects.
Make sure that Parent1.csproj has references to all your 3rd party dlls.
Add these same references to child1.csproj and child2.csproj.
Double check you have extmap files for all your 3rd party dlls. If these are missing the dlls will be loaded into the XAP files.
Adding the references to the module projects and setting Copy Local to false on them will work, which is more or less what the accepted answer describes. However, Application Library Caching is not supported in Prism modules, so that may not work as expected.
If you have a lot of assembly references, adding them in this fashion is not very maintainable. You could also use a post-build step that removes unneeded assemblies from the XAP. Here's a short article that I wrote about how.

Silverlight fails to fetch resource assemblies

We use the .NET resource manager to localize our Silverlight application and want to embed the satellite assemblies for the german language ("de") into the XAP file. Therefor, we set the neutral language to "en" and added "de" to the list of supported languages in the csproj file. This works fine, when we build the project locally. If we build the Silverlight solution with MSBuild (TFS), Silverlight will try to fetch the satellite assemblies with HTTP requests from /ClientBin/de/*.dll instead of taking those files embeded into the XAP (which do exist). Because the webserver returns 404 error codes for the non existent files, Silverlight crashes with an initialization error.
It turned out that if we remove a custom TFS build activity manipulating the assembly info code files, the Silverlight applications works as expected. Strangely, after re-enabling the activity the compiled XAP application still works (verified for two different build definitions working on seperate branches). The custom activity manipulates the assembly attributes AssemblyConfiguration, AssemblyCompany, AssemblyProduct, AssemblyCopyright, AssemblyTrademark, AssemblyVersion, and AssemblyFileVersion.
Some additional hints:
The custom activity will change the assembly info files before any compilation is done
Compiling the manipulated sources with Visual Studio will build a working XAP
The content of the XAP files (working and not working) is equal (nearly same sizes, no difference in manifest file)
The resource manager is instantiated using ResourceManager("Resource", Assembly.GetExecutingAssembly())
My questions are:
Why does Silverlight try to fetch those satellite assemblies from /ClientBin/de/ instead of just using those in the XAP file?
What kind of attribute in the assembly info file could cause such a behavior?
Why does re-enabling the versioning activity not break the XAP again?
And here's the solution: We use a tool named "Total Commander" for editing a file in the generated XAP to adjust the URL the (generic) client connects to. Since we added the localization dlls, editing the XAP with the Total Commander will lead to the behavior described above. If we manipulate the XAP with WinRAR or the internal Windows archive manager, all works as expected.
Edit: After comparing the XAP files we found, that Total Commander uses the backslash (\) to seperate directories, whereas WinRAR and the Silverlight Tools use slashes (/). It seems that we discovered a hidden Silverlight feature here ;-)

Storing resources in XAP package

Is it possible to store resx files and access them from the application package without changing any code?
EDIT: I don't want to embed them into the assembly. The resource files should be able to be modified without compiling the project so I tought storing them in XAP and replace when needed.
Thanks.
It is possible to include any file in a XAP by specifying that its build action to be Content.
However I'm not sure that is useful to you in the way you are hoping. Silverlight can only utalise a resx file in the intended manner if it is embedded in a dll.
Instead of using .resx files consider using ResourceDictionary .xaml files.
a XAP file is encrypted. you could load resources into isolated storage and access them in a similar way to a resource.

How to optimize the size of silverlight XAP file by removing common files?

I have bunch of common thrid party dlls that I use in multiple silver light projects. Each produce its own XAP files with same copy of the thrid party dlls. I would like to know, is it possibl to seperate the common thrid party dlls out and load only if the local cache dll is different from the common dll used by some other XAP that was previously loaded?
In other words, what I was thinking is, first time when I enter a new silverlight page, it would load the application XAp and the Common XAP file, from that silverlight app, I go to another silverlight page, which in turn loads another XAP but this time, it will not load the common dll XAP since it was already loaded by the first XAP load.
Thanks,
If the third-party DLL's are well done, they'll come with an .extmap.xml file that allows for precisely this scenario. But you need to turn it on by checking the "Reduce XAP size by using application library caching" option in your Silverlight project(s). See http://msdn.microsoft.com/en-us/library/dd833069(VS.95).aspx for more details about how this works.
I think a more optimal solution would be to try to minify your XAP/Zip files using something like ComponentOne XAPOptimizer. The problem with your approach is that you are introducing dependencies between projects that in no way could be managed if one or more projects change. This is a good resource for strategies to lower XAP file size.
I believe that you have a main XAP which makes the calls to load the others XAPs, right?
All you have to do is, in the properties of each DLL, change the atribute "Copy to Local" to FALSE, except on your main XAP.
When the user download the main XAP, the DLL will be available to all dependents XAP.

Resources