Suffice to say, Page Speed is really fascinating. During the time (not too long I hope) I'm writing Front-line of Front-end series, there are two versions (1 major, 1 minor) had been released. Hat off to the engineers who working on this amazing project.

Background

This is the last post in this Front-end Performance Tuning Series. The aim of this post is to eliminate performance pitfalls all the way. Looking back on the last post, we have achieved a score of 91, which is pretty cheerful. Nevertheless, from now on, every improvement is tough. You know, from 70 to 90 is a piece of cake, while from 90 to more is different. Even though, I believe every single step we take is significant. Well, let’s take stock of the result Page Speed gave us in last post.

From the result, we find there are a handful of things that we need to do, they are

  1. Combining CSS files
  2. Minifying html

Actually, besides the stuff listed above, there are something unlisted as well.

  1. Minifying CSS file
  2. Minifying JavaScript file
  3. Utilising CDN

Implementation

Combining CSS

Let’s combine CSS files first, because by doing so, we can kill two birds with only one stone. The only trick in this task is that our backgrounds defined for elements are using relative paths. So, firstly, we need to prepare a place to assemble all the images together. And actually, that place we can simply treat it as CDN.

See? If we have successfully combined CSS files, we are CDN-ready as well. Cool! But how to do so? Well, take it easy. Let me show you the steps now.

Firstly, you need to create a CDN folder under your website project folder like this.

image

Then, put all images you are using in your project to this folder and keep it in the structure as you write in CSS file. For instance, you may define your background like background: url(images\sprite.png) or background: url(bg.png). So these images should be in the following structure.

CDN\bg.png

CDN\images\sprite.png

Actually, by doing so, we can gain the flexibility and convenience when we continue. You will find it a while later. Now, all the changes of project structure is finished. We need to implement server-side code to combine CSS files and use CDN resources. Still remember the SiteController implemented in Battle I and a Js action therein? Now, we need to extend it a little bit by adding a correspondence Css action. Here’s the code.

    public class SiteController : Controller
    {
        private static string CssContent = string.Empty;
        private static string ReplacePattern = @"url\s*?\(\s*?";
        private static string CDNLocation = @"url(http://localhost:2128/CDN/";

        ...

        [CacheFilter(Duration = 30)]
        [CompressionFilter]
        public ActionResult Css(string id)
        {
            if (string.IsNullOrEmpty(CssContent))
            {
                var sb = new StringBuilder();

                foreach (var cssFile in StaticFiles.CssFiles)
                {
                    var cssFilePath = Path.Combine(Request.PhysicalApplicationPath, cssFile);

                    sb.AppendLine(System.IO.File.ReadAllText(cssFilePath));
                }

                CssContent = Regex.Replace(sb.ToString(), ReplacePattern, CDNLocation);
            }

            return Content(CssContent, "text/css");
        }

        ...
    }

The concept is similar to Js action. Pre-defined CSS files are read into memory and concatenate them together. Then, we do a magic to replace image reference by CDN one. ReplacePattern is the magic source, which defined the rule to replace. As you can see, the pattern is actually finding url(, so we keep the structure in CDN folder does help. CDNLocation is hard-coded here for convenience, but you can easily put it into web.config to acquire the flexibility. Well, to use it is basically the same as Js action as well, you just need to put one line of code.

<link rel="stylesheet" type="text/css" href="<%:Url.Action("Css","Site",new{id="site.css"})%>" />

Now, you are all set. Let’s evaluate our work by Page Speed.

image

Awesome! The score exceeds my expectation. However, as listed by Page Speed, we need to minify our resources(i.e. HTML, CSS, JavaScript).

I hope I can get a perfect 100. Most of time, however, investing on every aspect is not worthy. So, I will not care the second and last entries because for one thing, there are many external inefficiencies (from YUI library itself); for another, unused CSS in one page doesn’t means it is not used in other pages. As a result, it certainly stops me from getting a perfect 100.

Minifying Resources

In terms of CSS and JavaScript, we can hire an promising library, Microsoft Ajax Minifier, to do the minifying job for us. Quickly download and install it, then you are able to find the nugget in the folder C:\Program Files\Microsoft\Microsoft Ajax Minifier 4. Next, add AjaxMin.dll to your project reference like this.

image

Now, you have the power to compress CSS and JavaScript files by add only 3 lines of code in SiteController. Cool, isn’t it? Let me show you the code.

using Microsoft.Ajax.Utilities;

...

    public class SiteController : Controller
    {
        ...

        public ActionResult Css(string id)
        {
            ...

                CssContent = new Minifier().MinifyStyleSheet(CssContent);

            ...
        }

        ...

        public ActionResult Js(string id)
        {
           ...

                JsContent = new Minifier().MinifyJavaScript(sb.ToString());

           ...
        }
    }

Although we minified CSS and JavaScript files, but unfortunately, we didn’t get any progress in Page Speed. But don’t be gloomy. If you browser the source code, you will find the code is pleasantly neat.

image

Finally, minifying HTML, the last thing I would like to think about as I don’t find a sound solution to it. Nevertheless, there is one potential solution appealing me. This solution will utilise a handful of different technologies. They are,

  1. Html Minifier, a pure JavaScript implementation which is built on top of HTML Parser
  2. IKVM.NET, a .NET implementation of Java Virtual Machine
  3. Rhino, a Java implementation JavaScript engine

The idea is to IKVM.NET to enable Rhino in .NET Environment and HTML Minifier on the server side. But even by doing so, I found there is at least still one enhancement. That is the embedded JavaScript and CSS are not minified by Html Minifier. So we can extract these blocks and compress them by Microsoft Ajax Minifier like we did above.

Having said that, the complexity of this definitely beyond this series. Till now, we have improve the score of Page Speed from 73 all the way to 96. We almost eliminated all the performance pitfalls by using various technologies and techniques. If you are still interested in the solution of minifying HTML, I am glad if you find my ideas listed here are helpful to you. And your insights, suggestions and ideas are always welcome.

 posted on 2011-03-08 17:40  助平君  阅读(1184)  评论(4编辑  收藏  举报