Showing posts with label Compression. Show all posts
Showing posts with label Compression. Show all posts

Tuesday, August 13, 2013

Control Minification per Request with Web Optimizations

The Microsoft ASP.NET Web Optimization Framework is a great bundling and minification solution for your web applications. Simply grab the Microsoft.AspNet.Web.Optimization NuGet package, register your bundles, render them with a single line of code, and your environment will automatically resolve your dependencies based on whether or not the web server is running in debug mode.

But how can you debug minified styles and scripts in production?

Normally that is a difficult proposition, but here is a simple solution: JUST DON'T MINIFY THEM! With the little code snippets below you can add a simple query string parameter to disable minification for specific sessions or requests.

Adding this functionality to your website is extremely easy and requires no additional dependencies. Web Optimizations already has an internal AssetManager class that supports this functionality, we just need to access it via reflection.

Simply apply the following two steps and you will be ready to debug in production:

  1. Create the HtmlHelperExtensions class with the code below.
  2. Add a call to TrySetOptimizationEnabled inside of your ViewStart.

_ViewStart.cshtml

@using System.Web.Optimization
@{
 Layout = "~/Views/Shared/_Layout.cshtml";
 Html.TrySetOptimizationEnabled();
}

HtmlHelperExtensions.cs

public static class HtmlHelperExtensions
{
 public const string Key = "OptimizationEnabled";
 public static bool TrySetOptimizationEnabled(this HtmlHelper html)
 {
 var queryString = html.ViewContext.HttpContext.Request.QueryString;
 var session = html.ViewContext.HttpContext.Session;
 // Check the query string first, then the session.
 return TryQueryString(queryString, session) || TrySession(session);
 }
 private static bool TryQueryString(
 NameValueCollection queryString, 
 HttpSessionStateBase session)
 {
 // Does the query string contain the key?
 if (queryString.AllKeys.Contains(
 Key, 
 StringComparer.InvariantCultureIgnoreCase))
 {
 // Is the value a boolean?
 bool boolValue;
 var stringValue = queryString[Key];
 if (bool.TryParse(stringValue, out boolValue))
 {
 // Set the OptimizationEnabled flag
 // and then store that value in session.
 SetOptimizationEnabled(boolValue);
 session[Key] = boolValue;
 return true;
 }
 }
 return false;
 }
 private static bool TrySession(HttpSessionStateBase session)
 {
 if (session != null)
 {
 var value = session[Key] as bool?;
 if (value.HasValue)
 {
 // Use the session value to set the OptimizationEnabled flag.
 SetOptimizationEnabled(value.Value);
 return true;
 }
 }
 return false;
 }
 private static void SetOptimizationEnabled(bool value)
 {
 // Use reflection to set the internal AssetManager.OptimizationEnabled
 // flag for this request specific.
 var instance = ManagerProperty.GetValue(null, null);
 OptimizationEnabledProperty.SetValue(instance, value);
 }
 private static readonly PropertyInfo ManagerProperty = typeof(Scripts)
 .GetProperty("Manager", BindingFlags.Static | BindingFlags.NonPublic);
 private static readonly PropertyInfo OptimizationEnabledProperty = Assembly
 .GetAssembly(typeof(Scripts))
 .GetType("System.Web.Optimization.AssetManager")
 .GetProperty(
 "OptimizationEnabled",
 BindingFlags.Instance | BindingFlags.NonPublic);
}
Shout it

Enjoy,
Tom

Sunday, May 20, 2012

MvcBundleConfig NuGet Package

MvcBundleConfig is now available on NuGet!

MvcBundleConfig is a very simple project that adds configuration and debugging features to MVC 4's bundling framework. Once you create a new MVC4 web application and install the MvcBundleConfig NuGet Package, then you need only update our layout to use the new bundle extension methods, and you are ready to go!

Please note that the System.Web.Optimization NuGet package is still in beta, and thus that dependency is not included in the current version of the NuGet package. However, if you have created a new MVC4 project then that assembly should already be included.

Sample Installation Steps

  1. Create a new ASP.NET MVC 4 Project
  2. Select Manage NuGet Packages
  3. Search for and install MvcBundleConfig
  4. Update the Layout

Enjoy,
Tom

Saturday, March 31, 2012

Configuring Bundles in MVC 4

We write a lot of JavaScript.

Thus the bundling, compression, and minification of JavaScript is important to the speed and performance of modern websites. This is why I love and have been a big advocate of tools like Combres, and also why I was so excited to hear that such features were (finally) coming built in to ASP.NET MVC 4.

Introducing MvcBundleConfig

MvcBundleConfig is a very simple minimalist project I wrote to add configuration and debugging features to MVC 4's bundling framework, and achieves all 6 six of the goals listed below. It requires only MVC4 to run, and you need only add one config file to your project, one line of code to your application start, and you are off and running.

NuGet Package: https://nuget.org/packages/MvcBundleConfig/

Source on GitHub: https://github.com/tdupont750/MvcBundleConfig

Before we get to the demonstration at the bottom, let's review the needs and wants of a good minification framework.

What I NEED in a minification tool:

  1. Compress resources into single files.
    • Multiple request take time and resources, neither of which are things that any of us have to spare. By compressing resources into single requests and can limit the overhead and load time on both our clients and our servers.
  2. Minify JavaScript and CSS content.
    • Minification removes as many unnecessary white spaces and characters as possible from your resource files, reducing file size by up to 80% on average. When then compounded with gzip, we can reduce the file size another 50%. This means that our web applications can be brought down to clients 90% faster.
  3. Make use of both client and server side caching.
    • Making 90% less requests is nice, and making those requests 90% smaller is even better, but only ever having to request or serve them once is the key to true performance. Unfortunately client and server caching can be a bit complex due to quirks of different technologies and browsers. A good minification framework should abstract these concerns away from us.
  4. Ability to turn off during debugging.
    • As fantastic as everything that we have listed about is for a production website, it is a nightmare for a development website. Debugging JavaScript is no less complicated or time consuming than debugging C#, and we need to be able to use a debuggers and other client side tools that are inhibited by minification. A good minification framework must expose a debugging mode that skips compression pipeline.

What I WANT in a minification tool:

  1. Simple and dynamic configuration.
    • I hate hardcoded configuration. It bloats my code, and it requires bin drops to deploy. Meanwhile I really like the ability to add simple configuration files to my site as often as I can. Config files are explicit, abstract, and can be updated at any time. Win.
  2. Take a few dependencies as possible.
    • I mentioned above that I like Combres and it has a reasonably sized code base, unfortunately the fact that it's NuGet package pulls down half a dozen additional dependencies makes it feel quite heavy. The fewer dependencies a framework takes the better.

MvcBundleConfig Examples

Bundles.config

<?xml version="1.0"?>
<bundleConfig ignoreIfDebug="true" ignoreIfLocal="true">
 <cssBundles>
 <add bundlePath="~/css/shared">
 <directories>
 <add directoryPath="~/content/" searchPattern="*.css" />
 </directories>
 </add>
 </cssBundles>
 <jsBundles>
 <add bundlePath="~/js/shared" minify="false">
 <files>
 <add filePath="~/scripts/jscript1.js" />
 <add filePath="~/scripts/jscript2.js" />
 </files>
 </add>
 </jsBundles>
</bundleConfig>

Global.asax.cs

protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
 RegisterGlobalFilters(GlobalFilters.Filters);
 RegisterRoutes(RouteTable.Routes);
 BundleTable.Bundles.RegisterTemplateBundles();
 // Only code required for MvcBundleConfig wire up
 BundleTable.Bundles.RegisterConfigurationBundles();
}

_Layout.cshtml

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width" />
 <title>@ViewBag.Title</title>
 @* Call bundle helpers from MvcBundleConfig *@
 @Html.CssBundle("~/css/shared")
 @Html.JsBundle("~/js/shared")
 </head>
 <body>
 @RenderBody()
 </body>
</html>

In the Browser

NuGet Package: https://nuget.org/packages/MvcBundleConfig/

Source on GitHub: https://github.com/tdupont750/MvcBundleConfig

kick it on DotNetKicks.com

Enjoy,
Tom

Subscribe to: Posts (Atom)

AltStyle によって変換されたページ (->オリジナル) /