Including scripts/stylesheets on a page

In order to optimize the performance of your website, there are best practices for where to include stylesheets and scripts. It is generally true that the best place to include stylesheets is in the header of your web page, so that when the html is rendered, it is rendered initially with the intended styling and the user does not see a weird shift/flickr when styles are applied. Scripts, on the other hand, are best included at the very bottom of your webpage. The reason for that is that loading a javascript file with a <script> tag is generally a blocking call to the browser, and it will halt rendering and execution of other scripts until the .js file can be retrieved and executed. By including scripts at the bottom, the browser will render the styled html very fast, and then will download and execute the javascript after that to hook up all of the functionality of the page. The advantage of this is that the user perceives the page loading/rendering very fast, and then it can apply the functionality behind the scenes. The only risk with doing that is that buttons and other functional elements may not be fully functional immediately when the user sees it. However, usually by the time the user has digested the page and is ready to interact with it, the scripts have all executed and the page works as intended.

People sometimes find it inconvenient to include scripts at the bottom of the webpage, and for smaller lower/traffic websites it can be overkill. One drawback to including scripts at the bottom, is that if you need to run initialization scripts inline on the page, those need to be put after the .js includes. Without some help from a framework like Assman, that can be tricky and many people decide its not worth the trouble. Fortunately, Assman provides a way to make this as seemless as possible.

The bottom line is that Assman doesn't really care where you put your script or stylesheet includes. It allows you to declare in your master page/layout where you would like your stylesheets and scripts to be rendered. If you want some core scripts at the top of the page and others at the bottom, it supports that too. Here is how it works:

Defining where you want your scripts and stylesheets rendered

In your master page or Layout (some view engines use the term Master Page, others use Layout. They are basically the same thing), you need to call a helper method where you want your scripts to be rendered. The RenderScripts extension method extends the HtmlHelper object and will render a <script> element for all of the scripts that you register on the page. Note that if a script is configured to be consolidated, only the consolidated script will be rendered. If you registered inline scripts in your view, those will be rendered directly below the script includes. Similarily, RenderStylesheets will render all requested stylesheets in <link> elements, also taking consolidation into account. Inline styles (those should be rare) that were registered will be rendered inside of a <style> element. A sample Razor Layout might look something like this:


Note that in the example above, the stylesheets will be rendered in the header of the page, followed by "head" scripts. "head" scripts would be any scripts you registered to the "head" registry. All other scripts would be rendered by the default script registry at the bottom of the page. Note that Assman is smart enough to know if you registered the same script in both the head and the default registry. In that scenario, it will render it in the head and will not render it in the default area.

Requesting a script on a page

From your view, if you want to ensure a .js file gets included on the page, normally you would put declare <script> element with a src attribute. Similarily, to ensure a stylesheet gets included on the page, you would declare a <link> element on the page with an href attribute. The problem with that approach is that:
  1. It is quite possible that the script or stylesheet was already included on the page by another Partial View on the same page. Including it again will force the browser to execute the script twice.
  2. Declaring a <script> or <link> element directly from your View or Partial View usually will put it in a sub-optimal place on the page. As mentioned above, you usually want your stylesheets at the top of your page, not halfway down.

Given the issues with using native <script> and <link> elements directly in your views, Assman provides some helpers to help ensure that the scripts and stylesheets you want on your page will only be included once, and will be included exactly where you want them on your page.

To request a script on the page, you can simply call the RequireScript extension method of the HtmlHelper class. Using razor, it would look like this:


If you are using the Spark View Engine (my personal favorite), you can call the RequireScript extension method, or you can use the <RequireScript> binding that is automatically installed with the Assman.Spark NuGet package. It would look like this:

<RequireScript path="~/path/to/my/script.js" />

To include a stylesheet, you can use the RequireStylesheet extension method (or Spark binding).

Defining multiple areas for scripts/stylesheets

It is not uncommon that you want to include most of your scripts at the bottom of your webpage, but have a couple core scripts at the top. Assman supports the concept of Named Script Registries. If you do not specify a registry name when you request a script include, it will be added to the Default Script Registry. However, you can optionally specify a registry name in the RequireScript method. In Razor, it would look something like this:

@Html.RequireScript("~/path/to/my/script.js", "head")

or using Spark:

<RequireScript path="~/path/to/my/script.js" target="head" />

In your master page, you can then specify where you want the head scripts rendered and separately where you want the default scripts rendered. See the Master pages section above for details.

Assman also supports named registries for stylesheets, though I believe the need for that functionality is less.

Including scripts/stylesheets and Consolidation

If you are consolidating your scripts/stylesheets, which you probably will want to do, then that is where this approach for including stylesheets and scripts can really pay off. When you use RequireScript or RequireStylesheet, Assman will go look to see if the script or stylesheet you are requesting is being consolidated into a group. If it is, then it will instead register the request for the consolidated script or stylesheet instead. Assman also supports requesting the consolidated resource directly if you prefer to work that way.

What if consolidation is disabled?

You can disable consolidation of scripts or stylesheets globally, or for individual groups. If you request an individual script that is in a group with consolidation disabled, then that script will just be registered on the page as-is. If you request a group by its consolidated url, and that group has consolidation disabled, then it will instead register every resource in the group to the page. This is mostly useful in a debugging/development scenario.

Registering scripts/stylesheets when you aren't using ASP.NET MVC

While Assman provides good integration with ASP.NET MVC out of the box, it does not require it. Behind the scenes, the extension methods on the HtmlHelper are just convenience wrappers around the IResourceRegistryAccessor and IResourceRegistry interfaces. A WebForms plugin is provided to integrate Assman with good ol' ASP.NET WebForms, or if you are using a different framework to render your views, you can probably leverage the DefaultResourceRegistryAccessor class to plug in all of the functionality mentioned above. You simply want to tie the lifecycle of the DefaultResourceRegistryAccessor class with the lifecycle of your view

Last edited May 27, 2011 at 1:08 AM by andyalm, version 1


No comments yet.