Fork Me on GitHub

Nodeassets

Provides a complete asset manager solution including compilation from coffee/stylus, minification, combination, compression, caching, and also a refresh-on-change css live updater

Download this project as a .zip file Download this project as a tar.gz file

Get it using Nuget

Built on top of OWIN.

Install-Package NodeAssets.AspNet

Piles

In NodeAssets you group your assets into Piles where each pile is a logical grouping of your assets in a page. By default there is a global pile, but you can add any number of additional piles. Lets have a look at the pile configuration for a simple web site that has an admin area

piles
    .AddFile(Server.MapPath("~/Scripts/jquery-1.6.4.js"))
    .AddFile(Server.MapPath("~/Scripts/jquery.signalR.js"))
    .AddDirectory("Home", Server.MapPath("~/Scripts/Home"), false)
    .AddFile("Admin", Server.MapPath("~/Scripts/Admin/admin.coffee"))
    // NEW: Use regexs to narrow down when adding from directory
    // in this example, add .js files but not .min.js files
    .AddDirectory(Server.MapPath("~/Scripts/Mixed"), true, new Regex("(?<!.min).js"))

Now you can replace your script tabs on your layout page with

// Razor - We will include the global JS libs and the Admin libs
@Html.Raw(Assets.Js(true, "Admin"))

Compilation/Minification

NodeAssets uses each file's extension to decide how to compile it. Here is an example of an example config:

compilerConfig
    .CompilerFor(FileExtensions.Coffee, new CoffeeCompiler()) // Use your own coffee compiler
    .CompilerFor(FileExtensions.Css, new PassthroughCompiler())
    .CompilerFor(FileExtensions.Js, new PassthroughCompiler())
    .CompilerFor(FileExtensions.JsMin, new JSMinifyCompiler()) // Add the .min extension for minification

As of v0.0.9 the compilers are moved out into their own packages, search for NodeAssets.Compilers to find them

Minification is turned on/off depending on the source configuration

sourceConfig.Minimise(true)

Compilation using .NET

As of v0.0.4 a number of compilers wrap up packages available on nuget so you can get your awesome asset management without having to include NodeJS

Note that the Js/Css minify libs use YUI compressor for .NET and not the Microsoft Optimization libs, the reason for this is that I have found that a number of CSS3 properties cannot be properly minified - frankly I no longer trust the optimization libs!

Compilation using NodeJS

On top of the NET compilers there are also compilers backed by NodeJS if you want to go down that route (remember these are optional!):

When you install the nuget package a Node folder is added to your project, make sure to install the latest NodeJS for windows from here. After this in the command line browse to your Node folder and run

npm install

This will grab all the required modules and enable them in your nodejs backed builds!

As of v2.0.0 you can specify the location of the node.exe binary, this makes it possible to deploy node using your deployment packages

Typescript compilation

If you have installed typescript we also support compiling that directly

Combination

If the combination setting is turned on each pile will be combined into one file to be served up to your web application. Note that the compilation and minification occurs before this step. Recommended for production environments to reduce the number of requests that a browser has to make. Compilation is turned on/off via the source configuration

sourceConfig.Combine(true)

Compression

If compression is enabled NodeAssets will compress the response stream using gzip/deflate. The behavior is standards compliant, so it depends on the Accept-Encoding header sent by a browser. This is great for production environments as the bottleneck with websites is usually bandwidth. Compression is turned on/off via the assets configuration

assetsConfig.Compress(true)

Caching

If caching is enabled NodeAssets uses an aggressive caching mechanism. Assets are versioned using their last modified timestamp and set to be cached for the maximum time of a year. This is perfect for production environments as browsers will not even make a request for an asset that is has loaded before which means a MUCH faster site. However if your files have changed then the hash will change and browsers will be forced to grab the latest version of the asset. Your tags in your production environment will look a lot like

<link href="assets/global/global.css?v=1e0479d3ee71d58c33f82ebf68e1669653b8eb9e" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="assets/global/global.js?v=b1dda81e543867fba59c07e0fb48f31529e01f81"></script>

Caching is turned on/off via the assets configuration

assetsConfig.Cache(true)

Live CSS

This feature is extremely useful in development environments as it uses SignalR to force css updates on your page as you change them. No longer do you need to refresh your browser to see the css changes you make to your site.

There is a dependence on the SignalR client side libraries in this case so make sure to add them in by getting the SignalR nuget package

Install-Package Microsoft.AspNet.SignalR

And add the added javascript file to your assets.

Live CSS is turned on/off via the assets configuration

assetsConfig.LiveCss(true, "signalRNamespace")

NEW: When this option is selected your javascript files are now also watched, this means if you change your javascript all you have to do is manually reset the browser to instantly see your changes.

Put it all together

[assembly: OwinStartup(typeof(NodeAssets.Example.Startup1))]

namespace NodeAssets.Example
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
            #if DEBUG
                bool isProd = false;
            #else
                bool isProd = true;
            #endif

            var assets = Assets
                .Initialise(config => config
                    .ConfigureCompilers(
                        compilers => compilers.WithDefaultNodeConfiguration(MapPath("~/Node"), MapPath("~/Node/node.exe")))
                    .ConfigureSourceManager(
                        source => source.UseDefaultConfiguration(MapPath("~/built"), isProd))
                    .Cache(isProd)
                    .Compress(isProd)
                    .LiveCss(!isProd))
                .SetupCssPile(pile => pile
                    // An Example regex where you will add files ending in .css
                    // but NOT files ending in .min.css
                    .AddDirectory("Styles", MapPath("~/Content"), true, new Regex("(?<!.min).css$")))
                .SetupJavascriptPile(pile =>
                {
                    pile.AddFile(MapPath("~/Scripts/jquery-2.0.3.js"));

                    if (!isProd)
                    {
                        pile.AddFile(MapPath("~/Scripts/jquery.signalR-2.0.0.js"));
                    }

                    return pile;
                });

            app.MapNodeAssets(assets);
        }

        private string MapPath(string basePath)
        {
            return HostingEnvironment.MapPath(basePath);
        }
    }
}

More info?

Get Started Guide

Default NET/Node compilers

Thanks

The work here was very much inspired by the piler project for nodejs. I highly recommend this module if you are building nodejs websites in Express.