Home

Integrating JavaScript into your build

Have you ever wished that JavaScript had an /* @include "..." */ statement that worked in every browser? Now it does.

JavaScript presents an interesting problem to many web developers. As a client-side scripting language, it is very forgiving about how it is used, and how it is included in the context of a larger web document. There is a sloppy way to serve JavaScript, and a professional way to serve JavaScript.

The "sloppy" method covers many possibilities: inline amongst the HTML, buried inside the href of an anchor, or heaped into the <head> in a stack of script-tags that comes up to your eyeballs. All of these methods work, but they also have issues.

The current best practice recommends a different approach. Instead of including HTML inline, we should serve it as external files. Moreover, these files should be minimized to reduce the page load time. If multiple files are necessary, we should concatenate them to reduce the number of HTTP requests required to load them.

However beneficial this is to the end-user, the act of minimizing and concatenating script files adds an additional burden onto the developer. Fortunately, it is quite possible to automate this process, and numerous tools exist to facilitate this.

Introducing MinCat for MSBuild / Visual Studio

MinCat exists to address exactly the problem described above. It is a small, simple tool that lets you control the Minimization and Concatenation of your JavaScript files. It is designed to integrate directly with MSBuild. Because Visual Studio uses MSBuild under the hood, this means it provides easy integration with your existing Visual Studio web projects.

It's usage is simple and straightforward. Under its default settings, MinCat will scan your project for all referenced JavaScript files. If any files require minimization, MinCat produces the appropriate minimized file as part of your build process. Of course, it is possible to exercise fine-grained control over which files are processed: complete reference for more information.

For MVC projects, MinCat also provides an MVC Script helper extension. At a basic level, this extension will facilitate the switch between the minimized or development version of a particular file. However, it really begins to shine when combined with the new "directives" that MinCat offers (more on those later!)

@Html.Script("~/Scripts/MyScript.js")

Since minimizing JavaScript is not always a quick operation, MinCat will only re-minimize files if they have changed since the last time they were minimized. It accomplishes this by comparing the last modified date of the source files with the corresponding date on the minimized files. This helps keep the overall build time down to a minimum.

MinCat comes bundled with the excellent UglifyJS2 Javascript compressor.

New JavaScript Directives

As if all that weren't enough, MinCat additionally provides support for a number of directives, designed to be placed in the actual source of individual JavaScript files. These provide further control over how each file is treated by the minimization process. Because these directives are fully supported by the (optional) MinCat MVC Script helper extension, they provide some exciting new ways to organize and structure your JavaScript.

/* @skip minimize */
This directive will cause the source file to never be minimized, even if it is otherwise included by a wildcard in the input path. This has no effect when used with the MVC helper extension.

/* @require "filename.js" */
This directive instructs the minimizer that the current file depends on code from another file. When this file is minimized, all required external files will be collected, sorted into the correct order, reduced to a distinct list, and concatenated in front of the file that specifies them. Therefore, the resulting minimized file will contain everything it needs to function. When used with the MVC Script helper extension, each required file will be loaded in its own <script /> tag, in the correct order, before the <script /> tag that contains your target file.

/* @include "filename.js" */
This directives causes the minimizer to include the complete contents of the specified file directly inline, wherever that directive is found. When used with the MVC Script helper extension, the loaded <script /> file will also include the desired content directly inline.

Note the differences between @require and @include. The @include directive is primarily exciting because it allows you to create assembly-like structures:

var Global = (function () {
	"use strict";

	var internal = {};

	/* @require "Access to Global Variables Only.js" */
	/* @include "Access to Internal and Global Variables.js" */

	function Global() {
		var instance = {};

		/* @include "Access to Internal, Instance, and Global Variables.js" */
	}


	return Global;
}());

However, it will obviously wreck havoc with line numbers, which may confuse debugging efforts. To mitigate this, the MVC Script helper will automatically add file demarcation borders around each included file.

Script Bundling

MinCat.MVC also provides support for script bundling on a per-request basic. Unlike other script bundlers available, MinCat.MVC does not require you to define the bundles in advance; simply begin requesting JavaScript and MinCat.MVC will keep track of what it needs to load.

For example, consider this basic layout view:

@{
	this.RequireScript("/path/to/javascript.js");
	this.RequireScript("/path/to/another/script.js");
}

<html>
	<body>
		@RenderBody()
		@Html.RenderScripts()
	</body>
</html>

And this view that uses the above layout:

@{
	this.RequireScript("/path/to/javascript.js");
	this.RequireScript("/this/page/script.js");
}
<p>view body</p>

MinCat.MVC will track each call to RequireScript and place the necessary scripts onto the page, in the correct order. Also, MinCat.MVC will detect and eliminate duplicate scripts: even though /path/to/javascript.js was requested twice, it will only be emitted once. The resulting script tags will like so:

<script src="/path/to/javascript.js"></script>
<script src="/path/to/another/script.js"></script>
<script src="/this/page/script.js"></script>

Additionally, MinCat.MVC will detect when two different scripts both require the same dependency. In development mode, this will result in an error being raised, as it signals a probable misconfiguration with your scripts.

Installation

MinCat is available as a NuGet package, or by cloning this repository and building it yourself.

Reference

A complete reference is available.

License

MinCat is released under a BSD license.

Updated

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.