Get Started!

PreProcessors

As suggested by their Name, PreProcessors are used to pre-compile a wide range of programming languages, LessCSS, Sass, JavaScript, ECMA6, TypeScript, etc, into usable & Cache-Busted components.

General

When setup, a PreProcessor will automatically generate the output without the developer having to manually trigger the Processing. When a file is saved via the editor, any PreProcessor that references the file is re-executed and the result written to disk.

Cache Busted

a common issue developers have with included content is the browser cache, PreProcessors handle Cache-Busting for you.

Back in the days, we would have a dedicate file, say a css file /css/style.css each time you made a change to the content, you couldn't be sure that returning visitors with a cached version, from a previous visit, would download the latest version.

To circumvent AKA "bust the cache" we would add a query string.

For example :

  • "/css/style.css?v=1"

Or by appending the Date/Time the file was lasted edited :

  • "/css/style.css?r=" + (+(new Date(2017, 01, 13)))

Which would generate something like :

  • "/css/style.css?r=1486944000000"

While this approach worked for a bulk of the caches, there were still some proxies that would strip the Query String for JavaScript or CSS files, meaning that these Cache-Busts wouldn't always work.

NetCanvas PreProcessor Cache-Busting

NetCanvas' PreProcessors use an MD5 Hash of the file's content to generate a filename for the give output.

For example the MD5Hash filename for the CSS used by this page is :

Using the MD5 Hash based on the file content generates a sufficiently unique filename for each website. This means when a change is made to the File's content the File's name is changes.

This ensures that every single Cache is Busted!

PreProcessor Engine Types

Langs p-r

Currently the following types of languages are fully supported by the PreProcessor Engines :

  • LessCSS

    Generate CSS files from LessCSS sources using the Less Compiler

  • JavaScript

    Concatenate, Minify & Obfuscate JavaScript files using UglifyJS

  • Handlebars

    Compile Handlebars template files into JavaScript using Handlebars.js

  • TypeScript

    Compile TypeScript files into JavaScript using TypeScript Compiler API

  • Sass

    Generate CSS files from Sass sources using the Sass Compiler

  • CoffeeScript

    Compile CoffeeScript files into JavaScript using CoffeeScript Compiler

  • EMCA6

    Compile EMCA6 files into JavaScript using babel

Automatic Execution

Whenever a file used by a PreProcessor is changed via the .dash editor any PreProcessor referencing the file is executed.

If the compilation fails, the Line Number, Char Position, Error message etc. are echoed to the developer after saving the file. - This makes fixing the error nice and easy.

When the compilation is successful, a new Cache-Busted file is generated and it's location recored for use with subsequent requests.

The next request for a page, that references the PreProcessor, then uses this new Cache-Busted file path in the HTML. Meaning that as soon as you save a change to a core source file it is reflected to the developer immediately.

This makes developing a breeze.

Creating a PreProcessor

To create a new PreProcessor, navigate to the Admin / PreProcessors page, at the end of the list an "Add" area :

Add PreProcessor

  1. Enter a name, such as app-css / app-handlebars / plugins-js.

  2. Select the appropriate PreProcessor Engine Type.

  3. Click Add

Selecting PreProcessor Files

The PreProcessor Engines need to know which files are used by each PreProcessor, these are defined as "Master Files". Depending on the Engine Type, depends on what you would include in each PreProcessor's Master Files List.

For example, when creating a JavaScipr PreProcessor, the engine must be told each file to concatenate & uglify, so you normally include multiple items in the "Master Files"

Whereas, the LessCSS or Sass Engines only require the top-level file; the languages contain import statements and only expect a single file to execute the engine's compiler.

Dependent Files & File Changes

In the case outlined above, where LessCSS / Sass engines support import statements, mean that the PreProcessor will reference additional files, these are known as "Dependent Files".

When an engine compiles the PreProcessor, it returns a list of files used by the engine during compilation. These additional files are then stored along with the PreProcessor definition.

These "Dependant Files" are used to insure that changes to referenced files, via the .dash editor, trigger the execution for the Engine for any PreProcessor that references the given file.

Chaining PreProcessors - Compile then Minify & Uglify

A PreProcessor's output can be used as a "Master File" for another PreProcessor, which allows for "Chaining" of PreProcessors.

A good example is a site which uses :

  • HandleBars - To define templates for the UI.

  • TypeScript - To define the logic for use with the tempaltes.

Both the HandleBars and the TypeScript PreProcessors generate JavaScript, but the generated JavaScript is not minified nor is it obfuscated / uglified.

Using these PreProcessors directly, while developing, is great. The developer tools make use of the exposed Source maps, allowing the developer to easy see the respective code while debugging.

However, when used in the wild, it's preferable to deliver Minified & Uglified script, rather than referencing multiple sources & need multiple request, it's better to bundle the different sources together.

To reference another PreProcessor output, in the "Master Files" of another, append the string : PP_ to the name of the referenced PreProcessor.

For example, given the following PreProcessors :

  • app-handlebars - HandleBars PreProcessor for UI HTML. Output = JavaScript

  • app-typescript - TypeScript PreProcessor for UI logic. Output = JavaScript

Another, JavaScript, PreProcessor can include these by using the following values for in the Master Files :

  • PP_app-handlebars
  • PP_app-typescript

This will output concatenated, minified & uglified content from the other PPs.

You can also include other files directly along side these PP includes.

Including a PreProcessor

As outlined earlier, each PreProcessor records the path of the Cache-Busting file. This is used to reference the file when you need to include it within your HTML.

The NetCanvas PageBase class exposes the a Method :

  • public string GetPreProcessedFilePath(string name)

The method receives a string parameter, contains the name of the required PreProcessor, for example "app-js".

The method returns a string, containing the Absolute Path of the Cache-Busted file.

Default Page CSS & JavaScript

Here's an example showing how the CSS and JavaScript can be referenced and then included in your HTML.

Some C# to expose the Cache-Busted Paths :

public string CSSFile 
{
  get { return GetPreProcessedFilePath ("app-css"); }
}

public string JSFile
{
  get { return GetPreProcessedFilePath ("examples-js"); }
}

Including the CSS in the <head> :

<link rel="stylesheet" href="<%=CSSFile%>" media="all">

At the bottom of the HTML we include the JavaScript using :

<script src="<%=JSFile%>"></script>

This ensures that every request always receives the most recent version of the PreProcessor output.

Source Maps

A PreProcessor, normally, takes a number of different files, processes them resulting in an output that is different to the Raw Source. This makes viewing the content within the browser's developer tools difficult to correlate with the respective Raw Sources.

A PreProcessor result can contain "SourceMaps" that allow the browser to automate the correlation between the output of the PreProcessor and the Raw Source files. Making development & debugging with the developer tools much easier.


Example CSS Video

Here's a video where I create a LessCSS PreProcessor example-css, add the top-level Less file & generate.

I then change a value within one of the file and show how the PreProcessor has been updated, showing the changes made to the sources.