@Shazwazza

Shannon Deminick's blog all about web development

Smidge + Nuglify bundling, minification and source maps

May 8, 2017 23:23

  + + ASP.NET-Core-Logo_2colors_RGB_bitmap_MEDIUM

Smidge 2.0.0 RTM is finally here!

What is Smidge? Smidge is a lightweight runtime bundling library (CSS/JavaScript file minification, combination, compression) for ASP.NET Core -  Here’s some more background info on Smidge

There’s plenty of great new features in the version 2.0.0 , but in this post I’ll just highlight a couple of fun ones….

Nuglify and source maps

Nuglify if an ASP.NET Core port of the old AjaxMin library and this works very nicely with Smidge too. By default Smidge uses an updated version of JsMin that I maintain called JsMinSharp for it’s JavaScript minification engine. JsMin works fairly well, it’s primary feature is that it’s fast because it doesn’t come with any bells and whistles and doesn’t produce a Syntax Tree. Nuglify on the other hand does produce a Syntax Tree which gives it loads of control over how the minification is done so that it can produce much smaller files, has the ability to rename/reduce parts of the JS and to produce source maps. The downfall of all this control is that it becomes much slower but Smidge is smart enough to cache processed files on the server in a persistent state so it won’t re-process your files if it doesn’t need to.

Here’s a quick benchmark of JsMin vs Nuglify to minify jQuery using the default options (and no source map). As you can see JsMin is substantially faster and is far better for memory but Nuglify can reduce the file size quite a lot more (smaller Minified % is better)

Method Median StdDev Scaled Scaled-SD Minified % Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
JsMin 10.2008 ms 0.3102 ms 1.00 0.00 51.75% - - - 155,624.67
Nuglify 69.0778 ms 0.0180 ms 6.72 0.16 32.71% 53.00 22.00 15.00 4,837,313.07

Source maps you say? JsMin isn’t all that smart so it can’t produce source maps (yet) but Nuglify certainly can and by default the Smidge.Nuglify package has this turned on by default. Here’s how you can get this working:

  1. Follow the super easy Smidge quick start installation guide
  2. Install the Smidge.Nuglify package

    PM> Install-Package Smidge.Nuglify

  3. Add Smidge Nuglify to your services: services.AddSmidgeNuglify();
  4. Use Smidge Nuglify in your Configure method: app.UseSmidgeNuglify();
  5. Replace JsMin  with Nuglify for the default pipeline:
    services.Configure(opt =>
    {
        opt.PipelineFactory.OnCreateDefault = (type, pipeline) => pipeline.Replace(opt.PipelineFactory);
    });
    
  6. That’s it! Nuglify is now the JS minifier for the default pipeline and will produce source maps. You can configure the Nuglify settings in the AddSmidgeNuglify method.

Now you can debug via the source maps in dev tools:

image

File watching

Smidge can now watch your source files and if any changes are detected it can auto cache bust the bundle and flag for re-processing.

Previous to version 2.0.0 if you were in release mode all of the bundling/minification would be active but you really just wanted to test this behavior but unfortunately it meant that if you updated a js/css file you would have to go bump the Smidge version in the config file to clear out the server side persistent cache. In 2.0.0, you can configure your bundle with different environment options for both Debug and Production. For example, perhaps in Debug mode you still want your bundles to be active so that the minification, combination, compression, etc… is still happening but you want to still actively edit files … you can easily do this! Here’s a nice fluent syntax to achieve this:

bundles.CreateJs("my-application", "~/js/site.js", "~/js/app")
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
        .ForDebug(builder => builder
            .EnableCompositeProcessing()
            .EnableFileWatcher()
            .SetCacheBusterType())
        .Build()
    );

For this example the “my-application” bundle will do the following when being rendered in debug:

  • Still process the files in the bundle and minify, combine, compress into a composite file
  • Attach file watchers to all files in the bundle
  • Change the cache buster for this bundle to only survive the lifespan of the current app domain

And what’s cool is that if you edit any of the source files in this bundle it will auto cache bust to a new value and re-process the bundle when it’s next requested.

Debug vs Production?

There’s a few ways that you could render assets in either debug or production mode but this is probably the easiest and uses ASP.NET Core’s environment tag helpers. Notice the debug attribute on the script/link tags and that the src/href attributes just include the bundle name … this is using Smidge’s tag helpers to define which bundle to render and if it’s in debug mode.

<environment names="Development">
	<link rel="stylesheet" href="my-css" debug="true" />
	<script src="my-js" debug="true"></script>
</environment>

<environment names="Staging,Production">
	<link rel="stylesheet" href="my-css" />
	<script src="my-js"></script>
</environment>

Thanks!

Big thanks to @dazinator for all the help, recommendations, testing, feedback, etc… and for the rest of the community for filing bugs, questions, and comments. Much appreciated :)

Smidge 2.0 alpha is out

December 30, 2016 03:39
ASP.NET-Core-Logo_2colors_RGB_bitmap_MEDIUM

What is Smidge? Smidge is a lightweight runtime bundling library (CSS/JavaScript file minification, combination, compression) for ASP.NET Core.

If you’ve come from ASP.NET 4.5 you would have been familiar with the bundling/minification API and other bundling options like ClientDependency, but that is no longer available in ASP.NET Core, instead it is advised to do all the bundling and pre-processing that you need as part of your build process …which certainly makes sense! So why create this library? A few reasons: some people just want to have a very simple bundling library and don’t want to worry about Gulp or Grunt or WebPack, in a lot of cases the overhead of runtime processing is not going to make any difference, and lastly, if you have created something like a CMS that dynamically loads in assets from 3rd party packages or plugins, you need a runtime bundler since these things don’t exist at build time.

Over the past few months I’ve been working on some enhancements to Smidge and have found a bit of time to get an alpha released.  There’s loads of great new features in Smidge 2.0! You can install via Nuget and is targets .NET Standard 1.6 and .NET Framework 4.5.2

PM> Install-Package Smidge -Pre

New to Smidge?

It’s easy to get started with Smidge and there’s lots of docs available on GitHub that cover installation, configuration, creating bundles and rendering  them.

New Features

Here’s a list of new features complete with lots of code examples

Customizable Debug and Production options

https://github.com/Shazwazza/Smidge/issues/58

Previous to version 2.0, you could only configure aspects of the Production options and the Debug assets that were returned were just the raw static files. With 2.0, you have full control over how your assets are processed in both Debug and Production configurations. For example, if you wanted you could have your assets combined but not minified in Debug mode. This will also allow for non native web assets such as TypeScript to have pre-processors running and able to work in Debug mode.

Example:

services.AddSmidge(_config)
    .Configure<SmidgeOptions>(options =>
    {
        //set the default e-tag options for Debug mode
        options.DefaultBundleOptions.DebugOptions.CacheControlOptions.EnableETag = false        
    });

Fluent syntax for declaring/configuring bundles

https://github.com/Shazwazza/Smidge/issues/55

If you want to customize Debug or Production options per bundle, you can do so with a fluent syntax, for example:

app.UseSmidge(bundles =>
{                
    //For this bundle, enable composite files for Debug mode, enable the file watcher so any changes
    //to the files are automatically re-processed and cache invalidated, disable cache control headers
    //and use a custom cache buster. You could of course use the .ForProduction options too 
    bundles.Create("test-bundle-2", WebFileType.Js, "~/Js/Bundle2")
        .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
                .ForDebug(builder => builder
                    .EnableCompositeProcessing()
                    .EnableFileWatcher()
                    .SetCacheBusterType<AppDomainLifetimeCacheBuster>()
                    .CacheControlOptions(enableEtag: false, cacheControlMaxAge: 0))
                .Build()
        );                
});

Customizable Cache Buster

https://github.com/Shazwazza/Smidge/issues/51

In version 1.0 the only cache busting mechanism was Smidge’s version property which is set in config, in 2.0 Smidge allows you to control how cache busting is controlled at a global and bundle level. 2.0 ships with 2 ICacheBuster types:

  • ConfigCacheBuster – the default and uses Smidge’s version property in config

  • AppDomainLifetimeCacheBuster – if enabled will mean that the server/browser cache will be invalidated on every app domain recycle

If you want a different behavior, you can define you own ICacheBuster add it to the IoC container and then just use it globally or per bundle. For example:

//Set a custom MyCacheBuster as the default one for Debug assets:
services.AddSmidge(_config)
    .Configure<SmidgeOptions>(options =>
    {
        options.DefaultBundleOptions.DebugOptions.SetCacheBusterType<MyCustomCacheBuster>();       
    });

//Set a custom MyCacheBuster as the cache buster for a particular bundle in debug mode:
bundles.Create("test-bundle-2", WebFileType.Js, "~/Js/Bundle2")
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForDebug(builder => builder
                .SetCacheBusterType<MyCacheBuster>()
            .Build()
    );

Customizable cache headers

https://github.com/Shazwazza/Smidge/issues/48 

You can now control if you want the ETag header output and you can control the value set for max-age/s-maxage/Expires header at a global or bundle level, for example:

//This would set the max-age header for this bundle to expire in 5 days
bundles.Create("test-bundle-5", WebFileType.Js, "~/Js/Bundle5")
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForProduction(builder => builder                                
                .CacheControlOptions(enableEtag: true, cacheControlMaxAge: (5 * 24)))
            .Build()
    );

Callback to customize the pre-processor pipeline per web file

https://github.com/Shazwazza/Smidge/issues/59

This is handy in case you want to modify the pipeline for a given web file at runtime based on some criteria, for example:

services.AddSmidge(_config)
    .Configure<SmidgeOptions>(options =>
    {
        //set the callback
        options.PipelineFactory.OnGetDefault = GetDefaultPipelineFactory;
    });

//The GetDefaultPipeline method could do something like modify the default pipeline to use Nuglify for JS processing:

private static PreProcessPipeline GetDefaultPipelineFactory(WebFileType fileType, IReadOnlyCollection<IPreProcessor> processors)
{
    switch (fileType)
    {
        case WebFileType.Js:
            return new PreProcessPipeline(new IPreProcessor[]
            {
                processors.OfType<NuglifyJs>().Single()
            });                
    }
    //returning null will fallback to the logic defined in the registered PreProcessPipelineFactory
    return null;
}

File watching with automatic cache invalidation

https://github.com/Shazwazza/Smidge/pull/42 

During the development process it would be nice to be able to test composite files but have them auto re-process and invalidate the cache whenever one of the source files changes… in 2.0 this is possible!  You can enable file watching at the global level or per bundle. Example:

//Enable file watching for all files in this bundle when in Debug mode
bundles.Create("test-bundle-7",
    new CssFile("~/Js/Bundle7/a1.js"),
    new CssFile("~/Js/Bundle7/a2.js"))
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForDebug(builder => builder.EnableFileWatcher())
            .Build()
    );

What’s next?

This is an alpha release since there’s a few things that I need to complete. Most are already done but I just need to make Nuget packages for them:

More pre-processors

I’ve enabled support for a Nuglify pre-processor for both CSS and JS (Nuglify is a fork of the Microsoft Ajax Minifier for ASP.NET Core + additional features). I also enabled support for an Uglify NodeJs pre-processor which uses Microsoft.AspNetCore.NodeServices to invoke Node.js from ASP.NET and run the JS version of Uglify. I just need to get these on Nuget but haven’t got around to that yet.

A quick note on minifier performance

Though Nuglify and Uglify have a better minification engine (better/smarter size reduction) than JsMin because they create an AST (Abstract Syntax Tree) to perform it’s processing, they are actually much slower and consume more resources than JsMin. Since Smidge is a Runtime bundling engine, its generally important to ensure that the bundling/minification is performed quickly. Smidge has strict caching so the bundling/minification will only happen once (depending on your ICacheBuster you are using) but it is still recommended to understand the performance implications of replacing JsMin with another minifier. I’ve put together some benchmarks (NOTE: a smaller Minified % is better):

Method Median StdDev Scaled Scaled-SD Minified % Gen 0 Gen 1 Gen 2 Bytes Allocated/Op
JsMin 10.2008 ms 0.3102 ms 1.00 0.00 51.75% - - - 155,624.67
Nuglify 69.0778 ms 0.0180 ms 6.72 0.16 32.71% 53.00 22.00 15.00 4,837,313.07
JsServicesUglify 1,548.3951 ms 7.6388 ms 150.95 3.73 32.63% 0.97 - - 576,056.55
The last benchmark may be a bit misleading because the processing is done via NodeJs which executes in a separate process so I'm unsure if the actual memory usage of that can be properly captured by BenchmarkDotNet but you can see it's speed is much slower.

Thanks!

Big thanks to @dazinator for all the help, recommendations, testing, feedback, etc… and for the rest of the community for filing bugs, questions, and comments. Much appreciated :)

ASP.Net 5 Linux support for runtime JS & CSS preprocessing with Smidge

September 24, 2015 17:33

I’ve been working on a side project called Smidge which is a runtime JS & CSS preprocessor for ASP.Net 5. I started this late last year after the 2014 MS MVP Summit as a good starting point to deep dive into ASP.Net 5. I’ve been keeping the codebase up-to-date with the beta releases of ASP.Net 5, I have it cross compiled to both dnx451 and dnxcore50 and recently updated to use Beta 7. This week I decided to give running ASP.Net 5 CoreCLR on Linux… and the result is IT WORKS!

I have next to no experience with Linux and considering that, it wasn’t actually very difficult to get my test site for Smidge up and running. Here’s the info on how I set this up:

Linux setup

I decided to use Ubuntu 14.04.3 LTS. I installed in on Hyper-V on Windows 10 and that was all very easy. I also setup SSH with the server so that I could remote terminal to it which is much nicer than using the terminal through the UI interface of Ubuntu via Hyper-V. Then basically followed the instructions here: https://github.com/aspnet/Home/blob/dev/GettingStartedDeb.md#getting-started-with-aspnet-5-and-linux – except that I didn’t configure any Nuget package sources since that is built into dnvm now. Once that was done I used dnvm to install the default runtime:  dnvm upgrade. This installed mono by default but for my purposes I needed ASP.Net 5 CoreCLR since that’s what Smidge is built against and I wanted to see this CoreCLR cross-platform stuff in action. Issuing this command does the trick: dnvm install 1.0.0-beta7 -r coreclr . Now when I list the runtimes installed (dnvm list) I get:

image

So now dnx is installed! We’re ready to go.

dnu publish & bash

What I really wanted to see was that I could build my solution on my Windows machine in Visual Studio and then export it and see if it would work on the Linux machine. Through the command line on Windows at the root of my project I used dnu publish (https://github.com/aspnet/Home/wiki/DNX-utility#publish-dnu-publish) which outputs a ‘self-contained directory that can be launched’ = great! So I executed that command, it put the folder in my /bin folder for my current project and I copied over that directory to my Linux machine….  and realized I didn’t know what to do next ;)

I had a look through the files that dnu publish exports and the one that is listed in ASP.Net’s docs is the output/kestrel.cmd (since the command in my project is named ‘kestrel’). Inside this file this is listed:

@"dnx.exe" --appbase "%~dp0approot\src\Smidge.Web" Microsoft.Dnx.ApplicationHost --configuration Debug kestrel %*

which if you want to translate to Linux, you could execute this at the Linux terminal at the root of this folder:

dnx --appbase "approot/src/Smidge.Web" Microsoft.Dnx.ApplicationHost --configuration Debug kestrel

… which will actually work, BUT it turns out there’s a way more Linuxy way to do it. dnu publish also creates this file which isn’t in the docs:  output/kestrel Having a look at this file, the first line is: #!/usr/bin/env bash …  so I can only assume this is something for Linux since I’ve heard the term bash before. Turns out on Linux you can just do this in the terminal from the root of this folder!

bash kestrel

Result:

image

WHOOHOOO!

Lets see it in action

Now that it’s running, I’ll jump over to the UI in Ubuntu and fire up the browser… Tada!!

image

Problems along the way

I probably made the above sound a bit easier than it was ;) … I did run into a few setup issues along the way.

Problem #1

The first one was when I first tried to run dnx:

failed to locate libcoreclr with error libunwind.so.8: cannot open shared object file: No such file or directory” when you run dnx or dnu command

I solved this issue from reading about it on this nice post: http://blogs.msdn.com/b/rdcdev/archive/2015/08/28/some-issues-when-hosting-asp-net-5-on-ubuntu-on-azure.aspx which has some other nice tricks if you run into Ubuntu issues with ASP.Net 5.  The solution was that I needed to run this command:

sudo apt-get install libunwind8

Problem #2

Then I got this exception:

The type initializer for 'libcrypto' threw an exception

Which is referenced on this ASP.Net issue: https://github.com/aspnet/dnx/issues/1806 … and turns out that it’s also referenced on the above link. I can’t remember where exactly I found this solution but I had to run:

apt-get install libcurl4-openssl-dev

Problem #3

After fixing those 2 things, the bash kestrel command succeeded but when I went to test this in my browser, I just had a white screen. After Googling, I found this link: http://stackoverflow.com/questions/28845892/blank-white-screen-on-error-with-kestrel-asp-net-5 and as it turns out, I had the same issue. I forgot to add the error handling middleware. Perhaps when running in VS with IIS this is automatically taken care of for you… not sure. But in any case, it’s super important that you add it and you should add it as the first middleware so you can actually see if your other middleware fails, typically your ‘Configure’ method in your Startup class should start with:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Add the following to the request pipeline only in development environment.
    if (env.IsDevelopment())
    {
        app.UseErrorPage();
    }
    else
    {
        // Add Error handling middleware which catches all application specific errors and
        // sends the request to the following path or controller action.
        app.UseErrorHandler("/Home/Error");
    }

Problem #4

We’re not in Windows-land anymore! The errors I was getting were due to invalid file system paths. Turns out that .Net has always had this property: System.IO.Path.DirectorySeparatorChar but there wasn’t much reason to use it since .Net only runs in Windows and that character is always backslash. So I had to change my hard coded backslash use to use this instead. Next file path issue was case sensitivity… DOH. The Smidge configuration file is: ~/smidge.json however in my c# code I was trying to load it in with “Smidge.json” which fails in Linux of course.

Problem #5

Static files… I’m so used to working with IIS I forgot that outside of IIS I’d need to make sure the static file middleware was used:

app.UseStaticFiles();

I fixed that up and everything just worked… very freakin cool!!

Release – beta6

I’ve put up a new release on Nuget with these changes:

PM> Install-Package Smidge -Pre

And the source is on GitHub:

Introducing ‘Smidge’ – an ASP.NET 5 runtime JS/CSS pre-processor

December 11, 2014 23:19

During the past month I decided to dive deep into learning ASP.NET 5, and what better way to learn than to start a new OSS project :)

I chose to make a new new simple and extensible Javascript/CSS runtime pre-processor for ASP.NET 5. It does file minification, combination and compression, has a nice file caching layer and it’s all done in async operations. I ported over a few ideas and code snippets from CDF (client dependency framework) but with a more modern approach. I’ve called it ‘Smidge’ = something really small.

The project is on GitHub, it’s still a work in progress but its functional and there’s even some documentation! In the next few weeks I’ll get more of the code and docs updated and hopefully have a beta release out. In the meantime, you can clone the source, browse the code, build it and of course use it if you like.

Project details

It’s currently only targeting aspnet50 and not the Core CLR… I didn’t start with Core CLR because there was some legacy code I had to port over and I wanted to get something up and working relatively quickly. It shouldn’t be too much work to convert to Core CLR and Mono, hopefully I’ll find time to do that soon. It’s referencing all of the beta-* libraries from the ASP.NET 5 nightly myget feeds since there’s some code I’m using that isn’t available in the current beta1 release (like Microsoft.AspNet.WebUtilities.UriHelper). The target KRE version is currently KRE-CLR-amd64 1.0.0-beta2-10760.

Installation

I’ve put up an Alpha 1 release on Nuget, so you can install it from there:

PM> Install-Package Smidge -Pre

There’s some installation instructions here, you’ll need to add the smidge.json file yourself for now, can’t figure out how to get VS 2015 (kpm pack) to package that up … more learning required!

 

There’s certainly a lot of detective work involved in learning ASP.NET 5 but with the code being open source and browse-able/searchable on GitHub, it makes finding what you need fairly easy.

Styling XML with CSS

April 23, 2010 22:26
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
I’m sure you’ve heard of XSLT (DON'T GO AWAY I'M NOT SUPPORTING XSLT!). XSLT is used to transform XML into different XML – for example, rendering XML as HTML.  An example:

The XSLT method

<album>
	<title>Funkentelechy Vs. The Placebo Syndrome</title>
	<artist>Parliament</artist> 
	<year>1976</year> 
	<funkativity>10</funkativity> 
</album>

can be transformed (using XSLT) to this:

<div class="album">
	<h1>Funkentelechy Vs. The Placebo Syndrome</h1>
	<p class="artist">Parliament</p>
	<p class="year">1976</p>
	<p class="funkativity">This album has a funkativity rating of 10/10</p>
</div>

Now the question is, "is h1 a better tagname for the artist of the album than artist?". I'm pretty sure the answer is no. However, the HTML engine has no idea how to display an artist tag - it treats every unknown tag like a span tag.

The pure CSS method

So display information has to come from somewhere else. Some people may find the idea of markup depending entirely on CSS for display abhorrent. I do not. I maintain that reading the source of the album XML block makes just as much sense as reading the rendered HTML version. And screenreaders...if I was a screenreader I'd want concise and descriptive XML, rather than having to wade through a bunch of HTML crap. And let's be real: everyone's web client supports CSS.

Styling XML with CSS is actually very simple and very robust. The first thing to understand is that HTML is just a custom namespace of XML. The second thing to understand is you can have multiple namespaces present in any XML document. That means you can use both HTML and, say, a custom namespace...which you can define and set styling rules.

I won't blather much more. I'll just fill you in on how CSS targets namespaces.

The CSS @namespace declaration

In short, I can write up a stylesheet which targets a specific namespace and only a specific namespace. My XML file would look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<albums xmlns="http://jdiacono.org/music">
	<album>
		<title>Funkentelechy Vs. The Placebo Syndrome</title>
		<artist>Parliament</artist> 
		<year>1976</year> 
		<funkativity>10</funkativity> 
	</album>
<albums>

Here I declare that the XML inside and including the albums block is of the namespace http://jdiacono.org/music. Don't be misled by the namespace looking like a URL...I haven't even registered jdiacono.org and this is still valid. This is because namespaces are actually just unique, case-sensitive strings, and URLs tend to be unique and full of information. Let it be known that this block is all there is. It is a completely self descriptive block of pure data, which references nothing external.

Now to style this...here is my CSS:

@namespace url("http://jdiacono.org/music");

albums {
	display:block;
	}
	
album {
	display:list-item;
	list-style-type:decimal;
	margin-bottom:0.5em;
	padding:0.5em;
	border:1px solid;
	}
	
album title {
	display:block;
	font-size:2em;
	font-weight:bold;
	border-bottom:1px dashed;
	}
	
album artist {
	display:block;
	font-size:0.9em;
	}
	
album year {
	display:block;
	font-weight:bold;
	letter-spacing:0.4em;
	color:Green;
	}
	
album funkativity {
	display:block;
	font-style:italic;
	}
	
album funkativity:before {
	content: "This album has a funkativity rating of ";
	}
	
album funkativity:after {
	content: "/10";
	}

Now I have another example that is much more nourishing, which uses HTML and a custom XML namespace in the same page. You will need a browser other than IE to view this.

farmcode.org/sourcecode/sourcecode/cssNamespaces/cssNamespaces.xml

UPDATE: Looks like IE9 is supporting this!

CSS3: Using the fun stuff in real life

April 20, 2010 05:08

Sweep IE6 under the carpet

Do whatever you can to remove IE6 support from your website’s build spec. Proper CSS selectors like the direct child (ul > li), the :hover state for elements other than anchors, and attribute selectors (a[href*=”http://”]do not work in IE6. Then, add ie6updatein a conditional comment and voila! IE6 users see a totally legit looking alert bar across the top of their screen telling them that the page below looks horrible because they have an old browser and need to upgrade. Now you are ready to begin.

CSS3 is only sort of supported

CSS3 is currently a working draft. Microsoft hence decided to implement barely any of its features in IE8, and as a result your CSS3 magic is restricted to ‘modern’ (real) rendering engines, like WebKit (Google Chrome, Safari) and Gecko (Firefox). However, the developers of these engines understand that CSS3 is a draft and as such the interface can be changed without warning. As a safeguard they apply a prefix to the drafted properties they want to support. These are known as:

Vendor-specific extensions

If you’ve ever seen anything like -moz-border-radius: 6px; you know what I mean. Vendor-specific extensions are a standardised and accepted (however occasionally non-validating) way of implementing future rules without fear of breaking anything. If you want to use CSS3 properties you will most likely have to include the same property with a prefix right after (excepting the few properties like opacity and border-radius). Your rules will look something like this:

.box {
	-webkit-box-shadow:2px 2px 5px gray;
	-moz-box-shadow:2px 2px 5px gray;
	box-shadow:2px 2px 5px gray;
	}

I know that hurts, but at least your repitition of code is localised.  And it is future-friendly – as browsers start supporting CSS3 your advanced styles will begin to appear!  A shadow on a header here, a rounded corner there, an opacity somewhere. Patience. 

You’ll notice there’s no -ie-border-radius property above. This is very sad. This leads us to our next restriction in using CSS3:

Don't force a design

Think about it - why must the design for a site look the same in IE as Chrome? What if they looked different? Someone who sees the site in IE is not going to know what they're missing. If a design feature can't be implemented in IE that's no reason not to implement it in WebKit, so long as it degrades gracefully.

For this to work you need to be close to the designers (or be the designer) and have laid back superiors - it can't really be done when you're dealing with long chains of design approval. Convince everyone that the site is going to look better in Chrome (happy face!), not worse in IE (ANGRY FACE).

Validating CSS3

By default, the W3C's CSS Validator does not recognise CSS3. You must specify that you are validating CSS3 by clicking "More Options" on the validator page and selecting the CSS level 3 profile.

That’s it! Go forth and play:

CSS3 Goodies you have got to check out:

Note on this site

This post is pretty much a press release for the recent redesign of FARMCode.org – CSS3 allowed me to code the site exactly how I wanted in Google Chrome, translate it across to Firefox in like 5 minutes and then conduct quick damage control for IE (no rounded corners there).

Umbraco 4.1 Benchmarks Part 1

April 16, 2010 11:42
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
This is the first installment of what will hopefully be many Umbraco benchmark reports created by various members of the core team in the lead up to the launch of Umbraco 4.1. This benchmark report is about the request/response performance of the Umbraco back-office. This compares 4 different configurations: 4.0.3 with browser cache disabled (first run), 4.0.3 with browser cached files, 4.1 with browser cache disabled and 4.1 with browser cached files. These comparisons have been done by using newly installed Umbraco instances with ONLY the CWS package installed. The benchmark results were prepared by using Charles Proxy.
Test Stats 4.0.3 4.0.3
client cached
4.1 4.1
client cached
Content app Completed Requests 68 7 46 6
Response (KB) 687.05 72.48 431.41 32.54
Edit content
home page
Completed Requests 50 2 34 1
Response (KB) 385.10 47.28 343.36 12.07
Expand all
content nodes
Completed Requests 17 17 16 16
Response (KB) 18.47 18.47 13.96 10.85
TOTALS Completed Requests 135 26 96 23
Response (KB) 1063.62 138.23 788.73 55.46

Note: the above is based on <compilation debug=”false”> being set in the web.config. If it is set to true, the compression, combination and minification for both the ClientDependency framework and ScriptManager is not enabled. Also, this is not based on having IIS 7’s dynamic/static compression turned on, these benchmarks are based on Umbraco performing ‘as is ‘ out of the box which will be the same for IIS 6.

Though there’s only 3 tests listed above, these results will be consistent throughout all applications in the Umbraco back office in version 4.1.

The 4.1 difference:

  • In 4.0.3, all ScriptResource calls generated by ScriptManager were not being compressed or minified. This was due to a browser compatibility flag that was set in the base page (this was probably very old code from pre v3!).
  • Script managers in the back-office have the ScriptMode=”release” explicitly set (for minification of ScriptResource.axd)
  • The ClientDependency framework is shipped with 4.1 and all of the back office registers it’s JavaScript and CSS files with this framework. This allows for:
    • Combination, compression, minification of dependencies
    • Rogue script/style detection (for those scripts/styles that weren’t registered with the framework will still get compressed/minified)
    • Compression/minification of specified Mime types, in this case all JSON requests in the back office (namely the tree)
    • Compression/minification of all JavaScript web service proxy classes (‘asmx/js’ requests that are made by registering web services with the ScriptManager
  • Much of the back office client scripting in 4.1 has been completely refactored. Most of the JavaScript has been rewritten and a ton of file cleanup has been done.

Compared to 4.0.3, this is a HUGE difference with some serious performance benefits!

ClientDependency now supporting MVC

April 7, 2010 11:38
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
I’m please to announce that the ClientDependency framework now supports MVC! It’s very easy to implement using HtmlHelper extension methods. Here’s some quick examples:

Make a view dependent on a CSS file based on a path defined as “Styles”

<% Html.RequiresCss("Content.css", "Styles"); %>

Make a view dependent on jQuery using a full path declaration:

<% Html.RequiresJs("/Js/jquery-1.3.2.min.js"); %>

Rendering the Style blocks and defining a global style path:

<%= Html.RenderCssHere(new BasicPath("Styles", "/Css")) %>

Rendering the Script block (no global script path defined):

<%= Html.RenderJsHere() %>

There’s still a provider model for MVC but it uses a slightly different implementation from Web Forms. The same compositeFiles provider model is used but instead of the fileRegistration provider model that is used in Web Forms, a new mvc renderers provider model is used. A renderer provider is similar to the Web Forms fileRegistration providers but instead of registering the markup in the page using the page life cycle, a renderer provider is used to render out the html block necessary to embed in the page.

All of the functionality that existed in Web Forms exists in MVC. You can make as many views that you want dependent on as many of the same or different client files that you want and the system will still sort by position and priority and remove all duplicate registrations. Rogue scripts & styles still get processed by the composite file provider in MVC. Currently however, if you place user or composite controls on your views that have Client Dependencies tagged with either the control or attribute method used in Web Forms, these will not be registered with the view and output with the renderer. 

MVC pages have been added to the demo project as examples so have a look! You can download the source HERE

For full details and documentation go HERE

ASP.Net Client Dependency Framework RC1 Released!

March 19, 2010 09:13
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
With the community feedback, bug reports, patches, etc… I’ve managed to find time to upgrade this library to a release candidate status. We do use this framework in many production websites but it was great to hear from other in regards to specific bugs that were found relating to particular environments. These bugs have all been fixed up and this library is looking very stable.

You can download the binaries here.

Better yet, I’ve put together a near complete documentation library on CodePlex here !!

I still think the best way to learn about this project is to download the source code from CodePlex here and have a look at the demo web application included.

Moving forward, the next phase for this library is to add MVC support and another file registration provider called PlaceholderProvider which will give you even more granular control over where dependencies can be rendered in your markup. MVC support should be fairly straight forward and we’ll include a demo project for this as well.

Well definitely be releasing a final version soon after the next Umbraco 4.1 release candidate is released (which will hopefully be fairly soon!)

Happy day! Any and all feedback, bug reports and patches are definitely appreciated!

Client Dependency Framework Beta Released

September 30, 2009 00:06
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
I’ve posted a new Beta release on CodePlex, you can get it here: http://clientdependency.codeplex.com/Release/ProjectReleases.aspx. On the releases tab includes a sample web site that has most of the functionality that you can do so please download it for a documentation reference.

Newest changes & additions

  • Namespace and codebase changes/steamlining
  • Proper versioning added
    • Versioning is done on a global basis in the config
    • Old versions are retained and can still be accessed from the Client Dependency URL that was previously used (if necessary)
    • Versioned composite files names are prefixed with the version number (i.e. version 2 files will be prefixed with '2_') so it's easy to figure out which files are old
    • The composite file map also reflects which composite file sets are under a specific version
  • Provider model extended to support 2 types of providers:
    • File Registration Providers
      • Still comes with 2 providers: page header provider and a lazy loading JavaScript client based provider
    • Composite File Providers:
      • Comes with the standard provider: CompositeFileProcessor
      • You can implement your own provider to customize the way that files are combined, compressed, minified, etc... if the standard provider isn't exactly what you are after
  • Forced providers! You can now force a dependency to use a particular provider. This can be useful if you want to ensure that a particular script or stylesheet is rendered on to the page differently. For example, you may want to ensure that a script is lazy loaded (using the lazy load provider) but the rest are rendered in the page header.
  • Utility methods added to the ClientDependencyLoader for more dynamic implementations
  • A test website is included in the release which doubles as documentation, it includes:
    • Standard page header provider example
    • Forced providers example
    • Lazy load provider example
    • Dynamically registering dependencies in your code behind
    • Registering dependencies with attributes and via aspx controls

Things //TODO:

I’ve finished off versioning so at least i can cross that off from the previous list. But there’s still more to do:

  • Implement functionality for jQuery CDN
    • This will be a new control/attribute to easily include jQuery in your project
    • You will have the option to select which CDN you want to use (Microsoft or Google), or you can supply an address (like your own CDN/web server)
    • Though this framework will be included in Umbraco 4.1, we’ll be leaving this functionality out of the Umbraco build as we realize that there are quite a few installs that operate behind a firewall that won’t have access to the CDN.
  • Implement skeleton for Microsoft AJAX 4 CDN
    • Again, this will be another new control/attribute to easily include Microsoft’s new brand of AJAX with their CDN solution
  • Add support for MVC
  • Support for JS/CSS Minification with options to disable per dependency
    • The reason this hasn’t been implemented yet is that I’ve found a lot of scripts/stylesheets break with minification so we need to be able to turn this on/off on a per file basis
  • Some more documentation/examples in the example web application