Managing CSS and JavaScript Files as Media Items in Sitecore

One thing I love to do in any Sitecore implementation is to move some (or all) of my CSS files and JavaScript files out of the Visual Studio solution and into Sitecore as Media Items. Once you have your files in the Media Library, you may then assign them to your website pages as needed, either in template's Standard Values, or on an ad hoc basis. We also use this powerful technique for other file types, such as web fonts.

There are many advantages to managing your CSS and JavaScript files this way:

  • It gives designers and editors more control over the content, and makes them less dependent on developers.
  • It helps you be more agile by making your solution less "hard-coded" and more dynamic.
  • It allows you to improve site performance because you can reduce page payload by loading only those files needed for a page to work properly.
  • It allows you to deploy CSS and JavaScript updates right in the Sitecore shell without a full build of the solution.
  • As with any Sitecore Media Item, you can test the files on a staging site before publishing to the live site.

I have used this approach successfully in Sitecore versions 6.0 up to 8.2 - I expect it will work perfectly well in any Sitecore version.

Here are some general steps you can take to implement this in your own Sitecore solution (you'll need to customize this to your own needs, of course):

1. The first step is to create a content structure in your media library to hold your files. For example:

Next, upload your (hopefully minified) files into the Media Library.

2. Now it's time to create a base template that will allow you to select the CSS and JavaScript files that should be loaded on your web pages. Navigate to the appropriate templates folder, and create a new template named "Resources" based on the Standard template.

Set the template fields as shown here:

Save and publish your new template.

Now, add this template as a base template to any other templates that need it (such as the templates for your home page, sub-pages, etc.)

3. Now we can actually assign CSS and JavaScript files to your web pages. Setting a template's standard values is a great way to accomplish this (or you can do it at the individual item level). Here, I am assigning some CSS and JavaScript files to my home page:

Save and publish your items.

4. And now for some coding. First, you will need to modify the CSS and JS mimetypes in your Sitecore configuration to allow serving these filetypes from the Sitecore Media Library. As per Sitecore's best practice, this should be done with a config patch instead of directly modifying the MimeTypes.config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <!-- Update css mimetype to allow serving css files from Sitecore Media Library -->
  <add name="mediaType" extensions="css">
    <mimeType>text/css</mimeType>
    <forceDownload>false</forceDownload>
    <sharedTemplate>system/media/unversioned/file</sharedTemplate>
    <versionedTemplate>system/media/versioned/file</versionedTemplate>
  </mediaType>
  <!-- Update js mimetype to allow serving js files from Sitecore media library -->
  <add name="mediaType" extensions="js">
    <mimeType>application/x-javascript</mimeType>
    <forceDownload>false</forceDownload>
    <sharedTemplate>system/media/unversioned/file</sharedTemplate>
    <versionedTemplate>system/media/versioned/file</versionedTemplate>
  </mediaType>
</configuration>

5. And finally, you will need to modify your main layout to actually render the CSS and JavaScript links to the page. For the sake of simplicity, I'll just show an easy way to do this in an MVC view.

<head>
 @{
 var fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);

 var cssFiles = Sitecore.Data.ID.ParseArray(Sitecore.Context.Item["CSS Files"])
 .Select(id => Sitecore.Context.Item.Database.GetItem(id)).ToList();

 foreach (var cssFile in cssFiles)
 {
 var cssFileUrl = Sitecore.Resources.Media.MediaManager.GetMediaUrl(cssFile) + "?v=" + fileVersion
 <link href="@cssFileUrl" rel="stylesheet" type="text/css" />
 }

 var jsFiles = Sitecore.Data.ID.ParseArray(Sitecore.Context.Item["JavaScript Files"])
 .Select(id => Sitecore.Context.Item.Database.GetItem(id)).ToList();

 foreach (var jsFile in jsFiles)
 {
 var jsFileUrl = Sitecore.Resources.Media.MediaManager.GetMediaUrl(jsFile) + "?v=" + fileVersion
 <script type="text/javascript" src="@jsFileUrl"></script>
 }
 }
</head>

If you look closely at this code you will discover another nice little trick. I am appending the assembly version as a query string parameter to all the CSS and JS file Urls. This will force the client to fetch the latest version of of the file every time we do a software release (assuming you update your assembly versions like we do).

Since you are essentially moving code into the CMS as content, it's important that you have a good strategy for quality control and version control, and the discipline to strictly enforce it. In a nutshell, the way we do it is that all CSS and JavaScript development is performed in the developer environment. Modified CSS and JavaScript files are then code-reviewed, attached to Media Items in Sitecore and synced to the version control system (in our case TFS) using Team Development Server (TDS). Next, the Media Items are to deployed to upper environments using a build server (in our case Team City and TDS), where they are published and QA tested. And finally the Media Items are deployed to Production servers in a scheduled software release.

Standard disclaimer: there are surely 100 other ways to accomplish this, some of them probably even better than mine. :-) I'd love to hear your thoughts and ideas on this.

Happy Sitecoring!

~David

Add comment

Loading