So you have a website filled with images, CSS and JavaScript files, and you realize that you haven’t bothered optimizing the images or minified the CSS and JavaScript files. Or maybe you have, but your users can upload their own and they don’t get optimized/minified.

What’s the easiest way to go about that? Well, you could use tools like Web Essentials and PngGauntlet to help out, but that doesn’t solve the issue with user-uploaded files. You probably have to modify your website to include *.min.js files, commit them to source control, modify your website project and so on.

It would be much nicer if we didn’t have to worry about any of this and didn’t have to make any modifications to our website. It would be much nicer if it just happened automatically.

With Azure Websites that is now possible. Any web application hosted on Azure Websites no longer have to bother with these types of optimizations anymore.

It doesn’t matter if your website is running ASP.NET, PHP, Node.js or plain static HTML, it works for them all.

All there is needed is to install a NuGet package and publish the website to Azure. Here’s a video demonstrating how to add automatic image optimization.

The video shows how simple it really is to optimize images. To optimize CSS and JavaScript files, we can do the exact same thing, but with a different NuGet package.

Here’s what we need:

  1. Install NuGet package: Azure Image Optimizer
  2. Install NuGet package: Azure Minifier
  3. On a web application hosted on Azure Websites

How it works

Both the Image Optimizer and the CSS/JavaScript Minifier works the same way.

When they are installed and you publish to Azure Websites, an MSBuild trick makes sure to publish the Webjobs with your web application. As soon as that is done, Azure recognizes the Webjobs and starts them up.

The first time they start up, it can take a little while for them to finish the first pass of optimizations if you have a lot of files to optimize. You might even see the Webjobs restarting in the Azure portal. That’s ok, no problem. They start up immediately again and continues on where they left off.

The Image Optimizer supports .png, .gif and .jpg files. And the Minifier supports .js and .css files.

Server Explorer in Visual Studio shows us the Webjobs along with a log file and a cache file.

image

The log file is being written to every time a file has been optimized. You can open it by double clicking directly on the .csv file in Server Explorer. The cool thing about using a .csv file is that it an be opened in Excel, so you can easily do more calculations on the data.

The cache file (.xml) contains a list of files and their MD5 hash values. That ensures that the same files aren’t being optimized over and over again each time you publish or restart the WebJob.

If you have enabled Streaming Logs, then you can see the optimizations happen in real time directly within Visual Studio’s Output Window as well.

Open Source

As always, we keep our source code on GitHub and of course accept pull requests.

These features have been some that both Sayed and I have been wanting to add for a long time, but it was never possible before Microsoft introduced Azure Webjobs, because they required continuously running background tasks to work most reliably and in a way that scales.

The demo website used in the video is also open source and is great for playing around with these two optimizers yourself.

Happy optimizing!

The current JavaScript Intellisense in Visual Studio is generated based on IE’s JavaScript engine Chakra and its support for the various browser/DOM APIs. The cool thing about that is that the accuracy is really high, since the good folks on the IE team spends a lot of time implementing the APIs according to the web standard specifications. Awesome!

However, this means that the Intellisense in Visual Studio doesn’t include APIs that IE doesn’t support yet, such as the Shadow DOM, Server-Sent  Events, HTML Imports etc.

The good news is that the JavaScript editor in Visual Studio can easily be extended to include Intellisense for all of these APIs. The even better news is that it can all be done in JavaScript.

To do that, we need 2 things:

  1. Add a JavaScript file to the global Visual Studio references
  2. Add code to that file containing Intellisense

So let's get started.

Add a .js file to the global references

First of all, we must create a .js file somewhere on disk. Potentially on a network share for your entire team, or just in the user's documents folder. It doesn't matter where.

Then add a reference to it in Tools -> Options like this:

JavaScript references

Make sure to chose Implicit (Web) in the Reference Group dropdown. Otherwise it won't take effect for web projects.

Write some Intellisense

Now that the file has been referenced by Visual Studio, we can start adding additional Intellisense to it. Open the newly created .js file as well as any other JavaScript file. We are using the other JavaScript file to test the changes we make to our Intellisense file. We don't have to restart VS to see the changes, just save your Intellisense .js file and the changes take effect immediately.

Let's start by adding support for the new HTML Imports API. It's really simple because it only adds a single new property to DOM elements called import. So an example of how to use it would be something like this:

var link = document.querySelector('link[rel=import]');
var partial = link.import;

The value of partial is a Document element just like window.document. To add Intellisense for the import property, simple add this one line to your Intellisense .js file:

Element.prototype.import = Document.prototype;

We are extending the prototype of the Element object with an import property and giving it the value of the Document object's prototype. So now when we type this into our other JavaScript file, we should see this Intellisense:

HTML Imports Intellisense

What I've found to be a good rule of thumb is to make the added Intellisense apply more broadly than the spec might call for. In the example above, the import property should only apply to <link> elements (HTMLLinkElement), but since VS can't always know what type of element you're referencing, it makes good sense to just make it apply to all elements. It's up to you of course, but I think that this makes for a better experience.

Web Essentials

Today, Web Essentials 2013 ships two .js files that improves JavaScript Intellisense. One adds JSDoc comment support and the other adds many of the missing APIs including support for Angular.js.

The issue is that Web Essentials can't always add those two files to the global references.

If you already have Web Essentials installed, then you already have these two files located in C:\users\yourname\.

The files are:

  • JsDocComment.js
  • Modern.Intellisense.js

So make sure to check if you already have them in the JavaScript References options:

image

If not, just add them in the above dialog. The APIs that are added through Web Essentials are:

  • Shadow DOM
  • Vibration API
  • Fullscreen API
  • Canvas (improvements)
  • Server-Sent Events
  • HTML Imports
  • Object.observe()
  • Angular.js

Contribute

You can help improving the JavaScript Intellisense shipped in Web Essentials by adding support for more APIs to the Modern.Intellisense.js file on GitHub. A great way to get started is to go to status.modern.ie to look for APIs that Internet Explorer doesn't yet support. Under each API there's a link to the W3C specification.

As an added bonus, all of this also applies to Visual Studio 2012, but you have to get the two .js files from Web Essentials 2013 manually since they aren't shipped with Web Essentials 2012.