Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » Howto » Downloads
 
Add your own
alternative version

Fast ASP.NET Web page loading by downloading multiple JavaScripts after visible content and in batch

, 3 Aug 2008
Download all external scripts on your Web page after the visible content is loaded for faster perceived speed and donwload multiple JavaScript in batch for better actual speed
FastLoad_src.zip
FastLoad_src
App_Code
App_Data
Global.asax
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Xml;
using System.IO;

/// <summary>
/// Summary description for CombineScripts
/// </summary>
namespace Dropthings.Web.Util
{
    public class CombineScripts
    {
        private static Regex _FindScriptTags = new Regex(@"<script\s*src\s*=\s*""(?<url>.[^""]+)"".[^>]*>\s*</script>", RegexOptions.Compiled);
        private static readonly string SCRIPT_VERSION_NO = ConfigurationManager.AppSettings["ScriptVersionNo"];
         

        /// <summary>
        /// Combine script references using file sets defined in a configuration file.
        /// It will replace multiple script references using one 
        /// </summary>
        public static string CombineScriptBlocks(string scripts)
        {
            List<UrlMapSet> sets = LoadSets();
            string output = scripts;

            foreach (UrlMapSet mapSet in sets)
            {
                int setStartPos = -1;
                List<string> names = new List<string>();

                output = _FindScriptTags.Replace(output, new MatchEvaluator(delegate(Match match)
                {
                    string url = match.Groups["url"].Value;

                    UrlMap urlMatch = mapSet.Urls.Find(
                        new Predicate<UrlMap>(
                            delegate(UrlMap map)
                            {
                                return map.Url == url;
                            }));

                    if (null != urlMatch)
                    {
                        // Remember the first script tag that matched in this UrlMapSet because
                        // this is where the combined script tag will be inserted
                        if (setStartPos < 0) setStartPos = match.Index;
                        
                        names.Add(urlMatch.Name);
                        return string.Empty;
                    }
                    else
                    {
                        return match.Value;
                    }

                }));

                if (setStartPos >= 0)
                {
                    string setName = string.Empty;
                    // if the set says always include all urls within it whenever a single match is found,
                    // then generate the full set
                    if (mapSet.IsIncludeAll)
                    {
                        // No need send the individual url names when the full set needs to be included
                        setName = string.Empty;
                    }
                    else
                    {
                        names.Sort();
                        setName = string.Join(",", names.ToArray());
                    }
                    
                    string urlPrefix = HttpContext.Current.Request.Path.Substring(0, HttpContext.Current.Request.Path.LastIndexOf('/') + 1);
                    string newScriptTag = "<script type=\"text/javascript\" src=\"Scripts.ashx?" + HttpUtility.UrlEncode(mapSet.Name) + "=" + HttpUtility.UrlEncode(setName) + "&" + HttpUtility.UrlEncode(urlPrefix) + "&" + HttpUtility.UrlEncode(SCRIPT_VERSION_NO) + "\"></script>";

                    output = output.Insert(setStartPos, newScriptTag);
                }
            }

            return output;
        }

        public static List<UrlMapSet> LoadSets()
        {
            List<UrlMapSet> sets = new List<UrlMapSet>();

            using (XmlReader reader = new XmlTextReader(new StreamReader(HttpContext.Current.Server.MapPath("~/App_Data/FileSets.xml"))))
            {
                reader.MoveToContent();
                while (reader.Read())
                {
                    if ("set" == reader.Name)
                    {
                        string setName = reader.GetAttribute("name");
                        string isIncludeAll = reader.GetAttribute("includeAll");

                        UrlMapSet mapSet = new UrlMapSet();
                        mapSet.Name = setName;
                        if (isIncludeAll == "true") 
                            mapSet.IsIncludeAll = true;

                        while (reader.Read())
                        {
                            if ("url" == reader.Name)
                            {
                                string urlName = reader.GetAttribute("name");
                                string url = reader.ReadElementContentAsString();
                                mapSet.Urls.Add(new UrlMap(urlName, url));
                            }
                            else if ("set" == reader.Name)
                                break;
                        }

                        sets.Add(mapSet);
                    }
                }
            }

            return sets;
        }
    }

    public class UrlMapSet
    {
        public string Name;
        public bool IsIncludeAll;
        public List<UrlMap> Urls = new List<UrlMap>();
    }

    public class UrlMap
    {
        public string Name;
        public string Url;

        public UrlMap(string name, string url)
        {
            this.Name = name;
            this.Url = url;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author


| Advertise | Privacy | Mobile
Web01 | 2.8.140718.1 | Last Updated 3 Aug 2008
Article Copyright 2008 by Omar Al Zabir
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid