Tuesday, January 15, 2013

PackScript – Next Generation Build for the Web

*UPDATE* Check out http://packscript.com/ for a complete reference and examples.

What?

PackScript is a powerful open source (MIT license) resource build tool designed specifically for the combining and minification JavaScript, HTML and CSS files in modern, single page web applications. It was built from real need, specifically to support knockout.composite, and is focused around taking all of the pain out of managing all of the resources for your web app. You can find it on github.

If you’re pretty familiar with these sorts of tools, you might want to have a look at the post on a few reasons why we believe PackScript is better than all current alternatives.

The Story

Too much of my life as a web developer has been spent managing the multitude of JavaScript, HTML and CSS for whatever current project. Keeping track of where that JavaScript function is. Making sure script and link tags reference the right files from multitudes of scripts and stylesheets. Or worse… Keeping all of the JavaScript for a project in one behemoth file in a team environment.

Now remember we need to have different sets of files for each of our development environments. Facilitate debugging in the dev environment, minify but include some debugging or tracing stuff in the test environment, supercharge everything in production. Ok, that’s not so bad.

But wait… Our mobile app uses some (but not all) of the stuff from our desktop site, but needs some custom code to do all that “responsive” bollocks.

To top all this off, our JavaScript codebase is getting pretty big. We could combine it all into one massive file and load it up front, but it would be even better if we could load largish chunks of it as the user hits various parts of the app.

My head hurts. No more!

Powerful and Flexible Configuration API

PackScript is written primarily in JavaScript and runs in an instance of the Google V8 engine, courtesy of the excellent Noesis.Javascript library. It exposes a powerful and flexible JavaScript API for specifying input and output files and other options.

pack({
    to: 'site.min.js',
    include: '*.js',
    recursive: true,
    minify: true
});

PackScript scans the target folder recursively and, by default, picks up any file that ends with ‘pack.js’ and treats it as a configuration file. These files are executed in an instance of a V8 JavaScript engine.

The fact that the configuration is live JavaScript and not just static text allows us to do some pretty cool things.

Convention Over Configuration

PackScript allows you to define powerful conventions about the location and naming of your files. Tell your devs where to put and what to call your script files and forget about those script tags and AJAX calls.

GlobalExcludes = ['*.debug.js', 'admin.js'];
pack({
    to: 'site.js',
    include: '*.js',
    exclude: GlobalExcludes
});

The GlobalExcludes variable can be defined in a configuration file in another location and used throughout your project. You can also create reusable functions and extend the API to your liking by creating custom “transforms”; each property of the object passed to the pack method is a transform, like ‘include’ and ‘minify’.

We will have a reference site for knockout.composite and PackScript released soon that will show you some much more complex examples.

Painless, Seamless Debugging

PackScript is not fussy about your IDE and provides a memory-resident mode where file changes are detected and the appropriate outputs updated automatically. Keep your code neatly split up in separate files, edit and restructure them, refresh your browser and each file is there in your debugger, no messing with script references, all loaded using a single HTTP connection. Isn’t this how it should work?

The example in the next post will show you how you can keep your code in separate files and retain full debugging support (at least in Chrome) without needing to maintain script references. A production-ready script is produced at the same time.

Templates

PackScript gives you powerful and extensible templating for your content files. Out of the box, it provides support for underscore.js templates, but you can easily plug in support for other engines like handlebars, mustache or jsRender. More on this later.

By default, the target folder is scanned recursively for files with an extension of ‘.template.*’. A template for wrapping script files in HTML script tags might be called wrapScript.template.html and might look something like:

<script type="text/javascript">
<%=content%>
</script>

These templates can then be referenced in your pack configurations using the filename without extension.

pack({
    to: 'scripts.htm',
    include: '*.js',
    template: 'wrapScript'
});
Templates can be applied to any file type. A much more useful application of templates is explored in the next post.
Minification

Minification is provided out of the box courtesy of the Microsoft AjaxMin library and can be applied to any or all of your script and stylesheet files by setting the minify option to true. AjaxMin gives quite good compression for zero effort and exposes a .NET interface, so it was a good choice for the first supported minifier. Support for Closure Compiler and others is coming, and plugging in your own is easy.

Prioritisation

Simple prioritisation is offered by passing a file name or array of file names to the prioritise option. The files passed will be combined first in the order specified. This is enough to satisfy most scenarios, but will be expanded to allow for wildcards, etc.

Extensibility

PackScript offers a great deal of extensibility. Reusable functions will cater for many situations, but custom transforms can easily be created for simple APIs.

APIs implemented in .NET can also be exposed within JavaScript, again thanks to the awesome Noesis.Javascript library. The file access, minification and logging functions are implemented in this way. A simple marker interface is provided for this, more in a future post! If you’re interested in learning more, leave a comment or drop me a tweet.

What’s Coming?

Some extensions coming will include

  • SASS integration,
  • source map integration,
  • build information (build configuration, version, etc),
  • automatic checkout of files from TFS (though it’s arguable that it would be a better option to switch to git than to use it),
  • combining images and icons into a single file with CSS map generation,
  • HTML minification.
A Cool Trick

The console PackScript application also serves as a JavaScript console where you can interrogate configuration, test functions, etc. This feature is provided by a small wrapper for the Noesis.Javascript library - Noesis.Javascript.Extensions. The wrapper also adds support for dynamic invocation and return types to the JavaScript engine.

> Pack.options
{
  "configurationFileFilter": "*pack.config.js",
  "packFileFilter": "*pack.js",
  "templateFileExtension": ".template.*",
  "logLevel": "debug"
}
>

Until Next Time…

I hope this gives you a reasonable idea of the capabilities of PackScript. It’s worth noting at this point that it is a very early release of the product, and while it is well tested, there may be some reliability issues, and many more features on the way.

You can see a more detailed list of configuration options at the github repository. The unit tests and integration tests are also good sources of information.

Head on over to the next post for a neat practical application!

No comments:

Post a Comment