Hello everybody, those of you who followed up my sss.aspx posts, should note that this server control is the successor to sss.aspx.
There are many ways to speed up your website, and there are even more articles and books on how to do that. One of the Important ways is that the resources in your website like scripts, javascript and css files, have to be properly cashed so that the browser does not request them every time it visits the same page thus wasting valuable load times. Instead the first time the browser visits the website, it should download the files and not download them again until they are changed in the future. The way to achieve this is to use some headers that tells the browser the “version” of your files. The next time the browser visits the page again it asks the webserver for the same file(s) and it sends with the request header(s) the version it already has, if the file is not changed, the webserver should return 304 error to indicate “no change”. Another common and important method is to stream back the files compressed to the browser, this is something that happens at the http transport layer and the files are not actually modified in any way. The stream to send back the files is compressed usually using gzip compression and the browser when it receives them decompresses them again, this obviously saves on the amount of data transported over the Internet, saving you load times as well. Another good way to improve speed is to minimize the number of requests sent to download the files you need for the page to function, for example instead of having 6 javascript files and 2 css files to load inside your page, try to minimize them as much as you can. Minimizing the files will also speed up your page loading times since most browsers downloads 2 resources at at time (2 connections per domain), the more you have resources, the more time it takes to download them. However combining your files into fewer larger files is not good for the cleanness of your code, usually we divide our scripts into separate files for code organization purposes and combining them makes your site’s code less clean, less modular and less manageable. Another way to speed up the loading time of your website is to add the scripts at the end of the page, this way the page elements are rendered and then the scripts are processed, also speeding the load time of your page.
Web 2.0 brings a lot of change to the way we interact with the web and the websites we develop nowadays have less server side code and more client side code. A direct consequence of this is that we have much more JavaScript code than we did few years ago :) One problem that arises with lots of JavaScript code is file dependencies, if your client side code is modular and it should be, you should not have code duplication, when you come to use client side code, you have to carefully analyze the dependencies of your JavaScript files and include them in order in your web page so that the page functions correctly, this is an error prone task and sometimes you find yourself adding two copies of the same JavaScript file in the same page without paying attention, silently delaying load times more than it should. Read on to see how AdvancedScriptManager control has a smart dependency system.
AdvancedScriptManager to the rescue. AdvancedScriptManager helps you with all these problems/optimizations with minimal effort from you. Read on to know what it does.
- AdvancedScriptManager is a Server side control that has support for design time. You add it by simply dragging it from your Tools toolbar.
- For it to function properly, the control needs to add an HttpHandler to your Web.Config files. In design time, it will detect that it is missing and prompt you to add it automatically for you.
- You add one or more scripts to it by using the designer, if the file you add is not found, it will be highlighted in red. This is a typical look of the control:
- For JavaScript files, you have a the option “Delay Load” for each of the scripts. This is a very powerful feature, when you set it to on. The script will not be loaded directly with the page, instead the page will load, once it is done, the script is injected dynamically, this speeds up the site quite well for long scripts as the rendering of the page will be completely finished before the script is injected. Please note that you need to have jquery to use this feature. jquery is a very poweful, very popular JavaScript library. If you do not have it in your project, it is just one JavaScript file, download it and add it to your project. jquery-1.2.6.js is already included with the sample application.
- The script files that you add to the control will be combined at runtime and streamed back as one file only, minimizing requests. Moreover the file is sent back using GZip compression if the browser supports it.
- The combined file that is sent to the browser has the proper Response headers set to support smart cashing. It supports the ETag and the Modified-Since headers. The control will properly handle the responses with 304 errors when the files are not changed, the browser will not download the files again.
- The dependency management feature goes as follows: Each file that depends on another file, will have a comment at the beginning of the file that indicates the proper dependency. Take a look at script1.js, script2.js and script3.js in the sample provided, script3 depends on script2 and script2 depends on script1 and script1 depends on jquery. Here is how the comment would look like:
/// <AdvancedScriptManager include="/scripts/jquery-1.2.6.js"/>
Do not worry if you re-include base scripts, for example script3 depends on script2 and script1. But script2 already includes script1. If you reinclude script1 in script3 you will not have a problem. The control builds a proper dependency list based on all the comments in the script files it has and handles the order properly. Moreover, if you have more than one control on the page, say 1 in the head of the page and another in the body. If you include a script file in the first control, and you include it in the second control as well by mistake or due to dependencies, it will not be injected again, all of the controls on the same page track the injected files and will not reinject the same file again when it is already injected. I use the HttpContext.Current.Items to enable the controls on the same page to be “aware” of each other at runtime.
-
In design time, when you add scripts to the control, the control will show you the full list of the files it will inject based on the dependencies of the files, this will help you detect problems in dependencies if you included the wrong files. You also have a property in design time “ShowFullDependencies” which can be toggled on and off to show the actual files added to the control or the full list of dependency files.
-
There is another design time property “ShowInDesign” that is on by default. When it is on, you will see the control as the screen shot above. If you want to see your page design without the control interfering with the final look, set this property to off and the design time control will not be visible.
-
You can use the control for JavaScript files and CSS files as well, if you have another special type of scripts for your site, you can add the extension to the property Handler.allowedExtensions in the source code to enable the control to support it.
-
You have the ability to modify the final combined file’s contents before it is sent to the browser. This feature will enable you to have “server side” modifications of CSS files or JavaScript files. One example of its usage If you have a website that users can log into, you might give each account the ability to specify the colors of the look of the site. You can do this by creating your CSS files with certain variables in them; instead of hardcoding a certain color in the CSS file, you specify it as [COLOR1], and then before the file is sent to the user’s browser, you replace all occurrences of [COLOR1] with the color that the user has set in his control panel. Using this feature is very easy, you hook up the static event OnModifyScriptContents which will be called right before the final file is served.
-
If your project has virtual path providers, you can add support to them in this control by hooking the event OnGetFile.
Let me know if you have any comments and have fun speeding up your website :)
Download the sample application + code from here
Hello all, I wanted to write some filters on a query I had and I needed to compare some datetime variables, but only the time part of the datetime and not the full datetime value. I realized there is no built in function in MS Sql Server to isolate or separate the time field out of a datetime value or the date field out of a datetime value. I googled some solutions on the internet and non of them gave me the quick simple solution I needed so I decided to approach the problem with a simple solution. I wrote two functions called GetTimeOnly and GetDateOnly and they serve a simple purpose, to isolate the time or date out of a datetime value.
Here is the sql code for them.
create function GetTimeOnly(@val datetime)
returns datetime
begin
IF (@val is null)
return null
return cast(
cast(datepart(hh,@val) as varchar(2)) + ':' +
cast(datepart(mi,@val) as varchar(2)) + ':' +
cast(datepart(ss,@val) as varchar(2)) + '.' +
cast(datepart(ms,@val) as varchar(4))
as datetime)
end
create function GetDateOnly(@val datetime)
returns datetime
begin
if (@val is null)
return null
return cast(
cast(datepart(yyyy,@val) as varchar(4)) + '-' +
cast(datepart(mm,@val) as varchar(2)) + '-' +
cast(datepart(dd,@val) as varchar(2))
as datetime)
end
go
Its usage is simple and straight forward, instead of using the datetime variable directly in an sql query, just put it in the function that you need, for example:
select dbo.GetTimeOnly(getdate()) as TimeOnly, dbo.GetDateOnly(getdate()) as DateOnly
Now using functions like DateDiff or comparing with
“>” and
“<” becomes very easy.
Hello everybody,
It's been a while since I posted here, mainly because my hardisk crashed on me on the 31st of December
it could not make it till the coming year. After the crash and a new hardisk, I decided to upgrade to Windows XP, I had vista before
and Life is Great again :) I had some trouble finding the drivers, but eventually I found everything I need... Some simple differences to note, VS2008 took around one hour to install on XP. SP1 of VS2008 took less than 30 minutes to install, I remember I had to wait hours to finish installing SP1 when I had Vista... Makes you wonder what is it doing?! Mind you that when I had Vista, all the graphics effects were stripped down to gain maximum performance, most unnecessary services were stopped but still it was extremely slow compared to XP. Hopefully Windows 7 will be much better. Within the near future I will be giving a presentation at Microsoft offices in Lebanon on speeding up your WebApplications. I will keep you posted.
Please check this post, it is the successor to this post. Thank you.
I have updated sss.aspx to include a couple of more features and here is what it can do for you now.
- The most important benefit is it allows you to combine several script files (CSS or js) into one file to return to your client, this helps increase performance of your website by minimizing the http requests the page requires.
- The returning stream tries to use GZip compression if supported by the client browser. This further increases load speeds of your site.
- You can specify default script files to include always.
- Proper cashing headers and proper generation of 302 response codes (not modified) to minimize the transfer of scripts to the client browser. Script files are sent back to the client browser only if they have been modified. Two headers are processed to achieve this, "If-Modified-Since, Last-modified" and "If-None-Match, ETag".
- The ability to process your script files on the server to modify them before you send them back to the client (server side scripts), for example, your css files could have two colors replaced by variables [[COLOR1]], [[COLOR2]] and these variables could be replaced with the actual colors that you want to send to the client browser when requested. Using this you could achieve things like custom css files per client account (custom colors for each client account), or it could be used to specify different strings (inside JavaScript files) depending on the current language set.
- Last, but not least, a feature I am enthusiastic about. You can put special comments in your css, js files to indicate file dependencies. If for example you have two javascript files common.js and popups.js. If popups.js depends on common.js then you write a special comment in the beginning of the popups.js file to indicate that common.js is needed. sss.aspx properly parses this "dependency tree" and combines the files properly, in the proper order and serves them back to the client browser. If you have a lot of javascript files, you know you have the headache of specifying them in the correct order in the html/aspx files. If you "describe" your dependencies correctly in all your files by including these special comments, then you will not have to worry about this anymore, when you specify a javascript file that you need, the scripts it depends on are automatically added.
To use sss.aspx, it is very simple.
1. add the file sss.aspx it to your site (no need to recompile).
2. instead of including your script files like this:
<script language="javascript1.2" src="common.js" type="text/javascript"></script>
<script language="javascript1.2" src="sample.js" type="text/javascript"></script>
<script language="javascript1.2" src="engine.js" type="text/javascript"></script>
Add this now.
<script language="javascript1.2" src="sss.aspx?sample.js,engine.js" type="text/javascript"></script>
Note how the file common.js was omitted from the list, this is because the files sample.js and engine.js start with the comment:
/* <sss include="common.js"/> */
This comment will make sss.aspx combine the file common.js with sample.js and engine.js in the proper order and serve them back as one file.
If you have any comments, please let me hear about them. I tried to be straight to the point in this post, if some things are not clear enough, let me know and I will gladly explain more. You can use fiddler2 (http proxy debugger) to check the results of using sss.aspx.
Another important tip for increasing your site's load speeds is to enable "Content Expiration" in IIS.
Download the latest sss.aspx file here
I answered a post the other day about an easy way to have printer friendly look of pages in your web application and I decided to blog it here. You just need 5 minutes to have all your pages in your web application printer ready, ok maybe a bit more, like 10 minutes :)
When you design your web application, have your pages implement a master page, let us call it MainMaster.Master. Create another master page, call it PrinterFriendlyMaster.Master and make sure it has the same content holders as your MainMaster.Master, however make it printer friendly, without a header, maybe simpler footer, no background color, maybe different CSS files, etc... anything you need to do to have it ready for printers. Create a base class for all your pages, let us call it BasePage, it is a simple class like this:
using System;
using System.Web;
namespace telephone.NOC
{
public class BasePage : System.Web.UI.Page
{
protected void Page_PreInit(object sender, EventArgs e)
{
if (Request["print"] != null)
Page.MasterPageFile = "~/PrinterFriendlyPage.master";
}
}
}
Have all your pages derive from BasePage class.
Now at runtime, when you add a query string to a URL with print=1 the Page_PreInit of BasePage will detect that and will switch the master page dynamically to the printer friendly one, simple, modular and fast to implement.
Hello everybody, its been a while I haven't posted anything, I've been very busy :) But I promise you today's post will be good, or at least I hope so. Read on...
Every website needs to show alerts, popups, layers, whatever you want to call them. New Web 2.0 websites need this more as they show information with popups about the asynchronous actions the end user does. Take a look at Google Reader for example, my favorite RSS reader, when you do things like scroll down, you see a small popup (or a layer if you want) that is a simple div with a different background color that shows on the top of the page centered, displaying things like "Loading..." etc.
What I will present to you in this post is an engine for displaying such popups in a snap. Adding the engine to your site is very simple, you just have to include some JavaScript files in your pages. Please check my earlier post on Server side JavaScript because it contains a small engine that allows you to serve JavaScript files to the client browser in a more efficient manner. Let me start with a simple syntax of adding a simple popup to your site, it is as easy as this:
CommonPopupsEngine.GetHtmlPopup(0, "<div class='popup'>Loading...</div>").
Center(CommonPopupsEngine.CenterHorizontal).
ShowDialog();
This will show a div in the middle of the page (horizontal) saying "Loading...". The CSS class popup will customize it's color, background color and so on.
The first parameter is the channel, I will defer the explanation of this till later, for now set it always to zero. The next parameter is the actual html text of the popup you want to add, in this case it is a simple div with a CSS class. The function GetHtmlPopup at this point returns an object that is called "PopupCollection". The "PopupCollection" object is considered as one popup, visually speaking, however the name is set to collection because each visual popup you show, could be created from several html elements and not just one, for example if you want to add a shadow to your popup, then the popup will have your html code that was specified with the function call and another html element behind your element that is casting the shadow, together they form the visual popup that you see.
The PopupCollection object has several functions defined on it including ShowDialog() which will show the PopupCollection once called. The PopupCollection functions use the chaining method, which means each function returns "this" at the end of it to enable chaining the functions one after the other, this technique makes it easy to customize the PopupCollection in an easy memorable/expandable way without having to shove everything as parameters on one function.
The engine also offers you Grayouts to popups. Grayouts are when the whole page fades before showing the popup. Adding a grayout is as easy as calling AddGrayout() on your PopupCollection object, similarly for adding a shadow, you call AddShadow(). These two functions have a restriction on the order that you call them. If you want them, you have to call them in the beginning of the chain and the AddShadow() should be before the AddGrayout().
The functions that you can use in chaining are:
- AddShadow: Adds a shadow to your PopupCollection.
- AddGrayout: Adds a grayout to your PopupCollection.
- SetDimensions: Sets the position/dimensions of your PopupCollection. It takes 4 parameters, each of the parameters is optional and you specify null if you do not want to specify it. The parameters are x, y, width and height. The parameters are self explanatory.
- Center: Center the element instead of specifying dimensions using SetDimensions. You can call this method without any parameter and it will put the PopupCollection in the middle of the page. Or you can pass it one of the following parameters: CommonPopupsEngine.CenterVertical, CommonPopupsEngine.CenterHorizontal, CommonPopupsEngine.CenterBoth.
- SetFadeInDelay: Usually the popups show and hide, however if you call this function passing it a delay value (in milliseconds), it will FadeIn.
- SetFadeOutDelay: Same as above but for closing the dialog.
- EnableUserPositioning: Enables the PopupCollection to be dragged by the end user.
- AutoCloseDialogAfter:If you want to have the PopupCollection close automatically after a period of time, call this function passing it the delay in milliseconds.
- ShowDialog:Usually this is the last function you call in the chain, it will display the PopupCollection.
An example on the usage of these:
CommonPopupsEngine.GetHtmlPopup(0,
"<div class='popup'>An error has occurred</div>")
.AddShadow()
.AddGrayout()
.SetDimensions(null, 40)
.Center(CommonPopupsEngine.CenterHorizontal)
.SetFadeInDelay(300)
.SetFadeOutDelay(400)
.EnableUserPositioning()
.ShowDialog();
This example will show a popup that says "An error has occurred" inside a div having the CSS Class 'popup', It will have a Shadow and a Grayout, it will be centered horizontally and its Y coordinates will be 40 pixels from the top. The popup will FadeIn in 300 milliseconds and will FadeOut in 400 milliseconds. The popup can be dragged by the end user.
You can also easily open an Iframe in a popup by using a call like this:
CommonPopupsEngine.GetIFramePopup(channel, "http://www.yahoo.com/",
450, 250, 200, 100, true)
.AddShadow(null, 10)
.AddGrayout()
.SetFadeInDelay(300)
.SetFadeOutDelay(400)
.ShowDialog();
More examples can be seen in the file commonpopup.js in the attached example project.
To close the popups, there is one easy function to call CommonPopupsEngine.CloseTopmostPopupCollection. This function can be called without any parameter, in this case, it will close the last PopupCollection that was showed on the page. You can also pass it a specific channel to indicate to close the top most popup of a specific channel, I will explain the channels next.
When you show several popups, the engine stacks them on top of each other. And when you close the popups, it will close the topmost and shows the ones under it. If you want to have a different stack on the page, then this is what the channel is for, a channel is a stack of popups, specifying a different channel instructs the engine to use a different stack for the popups internally.
The engine takes care of the z-index of the popups that it shows transparently for you. It also makes sure that each individual html element in a PopupCollection has the proper z-index set for it (usually this is dictated by the order of the elements in the PopupCollection, this is why the AddShadow() and AddGrayout() has an order restriction when you call them in the chain).
The popup engine is written in the file commonpopupsengine.js, in the top of the file, there are few customizable parameters that affect how the engine works, they are put between two comments called configuration.
- CommonPopupsEngine_startupZIndex:
This is the startup z-index that the engine uses to manage the z-indexes of the PopupCollections you show. You might need to raise this value if you have your own popups or your own elements that have higher z-indexes.
- CommonPopupsEngine_maxPopupCollectionElements:
As described in the paragraph above, the engine takes care of the z-index of the individual elements of the PopupCollection, to do so correctly, it needs to know the maximum number of html elements that may exist in one single PopupCollection, this is this value. Usually you will not need to change this value however if you want to expand this code you will need to understand this more. On a later post, I will go into more details to explain how you can expand the code here.
- CommonPopupsEngine_useGlobalZIndex:
If this value is set to true, then even if you have multiple channels, the last popup will be shown on top of all including all channels. If you have this set to false, if you open two popups in two different channels then they will have the same z-index and they will be shown both as on top and not just one.
- CommonPopupsEngine_onlyShowToplevelPopup:
When this is set to true, if you open more than one popup, then only the last popup will be seen. When you show a new popup, the current one will be hidden and when you close the topmost popup, then if there is a popup below it, it will be shown again.
Here are some snapshots:
Let me know if you have any comments or if you need further help.
Hope this helps you.