< back

Theme Engine

The StoreBuilder Theme Engine is an extremely powerful component which allows for 100% control over the entire website markup, javascript and css and enabling StoreBuilder websites to be extremely fast.

StoreBuilder uses handlebars for page templating plus regular old industry standard JavaScript and CSS (and can capitalize on popular frameworks like jQuery and Twitter Bootstrap).

Theme Folder Structure

Your web project should contain one root folder within which all themes reside. Each theme will have its own file folder for organization. The default theme name and therefore folder name is 'default'.

  • ~/themes
    • /default
      • files for 'default' theme are located here, optionally organized with more sub folders
    • /customtheme
    • /some-other-theme

There is no mandatory folder structure for themes, however we recommend organizing themes by common areas.

  • ~/themes
    • /default
      • /everywhere
      • /home
      • /listing
      • /product
      • /cart
      • /checkout
    • /customtheme
    • /some-other-theme

The physical file folder structure for a theme is primarily intended for developer convenience and organization and should not affect your production website functionality or performance.

All theme resources will be compiled/combined/minified/optimized according to their Theme Engine meta data, usually supplied via a comment header at the beginning of the file.

Theme File Headers

All text based theme files (.css/.js/.hbs) can optionally have a comment header added to them which will control how the StoreBuilder Theme Engine handles that file. There are some slight differences between handlebars template headers, javascript file headers and css file headers, but they all share a common structure of key-value pairs of meta information.

Meta data headers should always be the first comment in the file (feel free to leave any additional comments after this header). By requiring the Theme Engine meta data comment to be first we can make the compile/combine/minify process much faster as we do not read the entire contents of any theme files during discovery and dependency resolution. This allows us to go through more files (and larger files) in less time.

StyleSheet (*.css) File Header

StyleSheets use /* ... */ notation for comments. All key-value pairs are optional, however the default behaviour will be to ignore CSS files which are either missing the Theme Engine comment header or have incomplete header information.

/*
Compile-Minify: true
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: magnific
Compile-Dependencies: bootstrap,overrides
*/

JavaScript (*.js) File Header

JavaScript also uses /* ... */ notation for comments. All key-value pairs are optional, however the default behaviour will be to ignore JS files which are either missing the Theme Engine comment header or have incomplete header information.

/*
Compile-Minify: true
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: my-js
Compile-Dependencies: jquery,storebuilder,bootstrap
*/

Handlebars Template (*.hbs) File Header

Handlebars uses {{!-- ... --}} notation for comments. All key-value pairs are optional, however the default behaviour will be to ignore handlebars template files which are either missing the Theme Engine comment header or have incomplete header information.

{{!--
Compile-Minify: true
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: cart.minicompare
Compile-Dependencies: handlebars
--}}

Theme Meta Data Definitions

Here is the list of built in meta data key-value pairs which affect how StoreBuilder ThemeEngine will handle your theme files.

Compile: true(default)/false

The "Compile" key-value pair indicates whether this text based theme resource will be compiled (.hbs) and/or combined (.js/.css) for use on the public facing website. If a file has "compile:false" added to it, the file will be ingored when combining/minifying website resource, but it will still be available on the file system directly or for use on the server side (such as a handlebars template only intended for use server side).

Compile-Minify: true(default)/false

The Compile-Minify key-value pair indicates whether this text based theme resource should be minified during combination with other resources. The default is true, but can be overridden in the case that you are supplying a pre-minified .js/.css file supplied by a 3rd party. It may often be a waste of resources to re-minify and already minified resource.

Compile-Area: everywhere|listing|product|cart|checkout

The Compile-Area key value pair is simply a string value used to group text based theme files together for compiling/combining/minifying. You can use any Compile-Area you want (including making up your own area for some functionality on your website that is not StoreBuilder related), but we have identified a few common areas that all ecommerce websites will have: everywhere, listing, product, cart, checkout.

All files of the same type (.js/.css) with the same compile area will be considered for combination.

Compile-OutputGroup: headinline|bodyendtag|onload

The Compile-OutputGroup key value pair is used to further define how static resources are combined. One of the key techniques for speeding up websites is to defer loading of lower priority things and prioritize loading of important things such as "above the fold" content the user will see right away. You might group your javascript into "mandatory must run asap" scripts and "progressive enhancement run after the page has loaded" type scripts in order to reduce the amount of javascript that needs to be loaded, parsed and executed during page load.

In order to achieve a perfect score in Google Page Speed Insights you must pay close attention to which resources should be included within the page markup inline, which resources should be loaded at the very end of the document before the closing body tag, and which resources can be loaded after initial page load.

Compile-Exports: {alias}

The Compile-Exports key-value pair defines an alias for this resource file. This string value is used as the template name when compiling handlebars templates, and is also used for dependency resolution between theme files (sorting prior to combination) as well as duplicate file resolution for both mistakes and for theme inheritance (one theme can inherit from another theme and override one or more files).

Compile-Dependencies: {dependency-1}, {dependency-2}

The Compile-Dependencies key-value pair is a comma separated list of dependencies this file requires. Dependencies are referenced via their declared Compile-Exports value. The StoreBuilder Theme Engine will ensure that all static resources are output in the correct order given the declared dependencies for each file.

Theme File Preprocessors

Theme files are processed in a particular order when being compiled/minified. Most notably, all pre-processors execute before standard .js/.css combination/minification. This allows pre-processors to output files which may be included in the final bundled .js/.css.

When a pre-processor compiles a resource which results in .js/.css output, the original meta data header is preserved on the output of the pre-processor.

For example the handlebars compiler will run before the javascript combination/minification, and any meta data header on the original handlebars template file will be copied into the compiled javascript output for that template file. In this way when the javascript combiner/minifier runs it will pick up any compiled handlebars templates to be considered in any combined/minified .js bundles.

Special Output Groups

While there is no technical limit to what strings you can specify for Compile-OutputGroup we believe there are only 3 which are necessary, 2 of which have special behaviours.

Compile-OutputGroup: headinline specifies that this resource will be combined and minified with other files in the same Compile-Area but be kept in memory to be written out within page markup within the HTML <head> element. This is used to prioritize CSS styles that absolutely must exist before the page can be viewed, while deferring all other CSS to be loaded later.

Compile-OutputGroup: headinline specifies that this resource will be loaded/executed at the end of the page markup just before the closing </body> tag. This is the most common best practice for all JavaScript unless you are able to further optimize by deferring some javascript to load even a bit later if it isn't likely useful within the first 1/2 second or 2 when a user lands on your page.

Compile-OutputGroup: onload specifies that this resource will be combined and minified with other files in the same Compile-Area and is intended to be deferred until the page initially loads. By separating your javascript into high priority and progressive enhancement type groups, you can make the website feel much faster without actually changing much at all.

Example of Static File Combination

If we have the following two CSS files.

CSS_File1.css

/*
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: header_styles
*/
.header {
    margin-top: 15px;
}

CSS_File2.css

/*
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: footer_styles
*/
footer {
    background: #515151;
}

StoreBuilder's ThemeEngine will notice these two files have the same Compile-Area and Compile-OutputGroup tags and will therefore combine these two files together to produce an output file like this:

.header {
    margin-top: 15px;
}
footer {
    background: #515151;
}

Example of Dependency Resolution

If we have the following two JS files.

JS_File1.js

/*
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: config_vars
*/
var foo = 'bar';

JS_File2.js

/*
Compile-Area: everywhere
Compile-OutputGroup: bodyendtag
Compile-Exports: awesome_sitecode
Compile-Dependencies: config_vars
*/
if(foo === 'bar'){
    foo = 'baz';
}

StoreBuilder's ThemeEngine will first notice these two files have the same Compile-Area and Compile-OutputGroup tags and will therefore combine these two files together. But ThemeEngine will also notice that the second file has a Compile-Dependencies tag which matches a Compile-Exports tag from the first file. Therefore when combining these files together, it will ensure the ordering is correct starting with JS_File1.js and then appending JS_File2.js.

var foo = 'bar';
if(foo === 'bar'){
    foo = 'baz';
}