Asset building

Getting started

Create your source directory

First, create a directory for your source files. Let’s say you’re making a WordPress theme - you would create a subdirectory named src/ in your theme as follows:

$ mkdir www/wp-content/themes/mytheme/src/

Configuration

Next, add the following to the awe.yaml configuration file, replacing the paths as necessary:

ASSETS:

    default:
        src:          www/wp-content/themes/mytheme/src/
        dest:         www/wp-content/themes/mytheme/build/
        bower:        false
        autoprefixer: false

Warning

The build/ directory should not be an existing directory – anything inside it will be deleted.

Tip

The src/ directory can be outside the document root if you prefer. e.g. The recommended configuration for Laravel 5 is:

ASSETS:

    default:
        src:          resources/assets/    # app/assets/ in Laravel 4
        dest:         public/assets/

Be aware that the original source code will still be made public (in the source maps), so this is not a way to hide it.

Create your source files

All your source files should go into the src/ directory you created above. For now, let’s imagine you have these files:

src/
├── img/
│   └── logo.png
├── sample1.css
├── sample2.js
└── subdirectory/
    ├── A.css
    └── B.js

Run the build command

Finally, run the build command to generate the build/ directory:

$ awe build

Or run the watch command to generate it and then wait for further changes:

$ awe watch

Since there are no special files in the list above, you will get exactly the same structure:

build/
├── img/
│   └── logo.png
├── sample1.css
├── sample2.js
└── subdirectory/
    ├── A.css
    └── B.js

However, read on to see what Awe can do!

Autoprefixer

Autoprefixer automatically adds vendor prefixes (-webkit-, -moz-, etc.) to your CSS files. Simply enable it in the config:

ASSETS:

    default:
        src:          www/wp-content/themes/mytheme/src/
        dest:         www/wp-content/themes/mytheme/build/
        bower:        false
        autoprefixer: true

For more details about how it works, and how to selectively disable it, see the Autoprefixer documentation.

CoffeeScript

CoffeeScript is “a little language that compiles into JavaScript”. It has a very simple 1-to-1 mapping of input files (.coffee) to output files (.js). For example, these source files:

src/
├── sample.coffee
└── subdirectory/
    └── A.coffee

Would result in this output:

build/
├── sample.js
└── subdirectory/
    └── A.js

Tip

It will also generate source maps – sample.js.map and subdirectory/A.js.map – but these are not shown for simplicity.

For more details see the CoffeeScript documentation.

Sass

Sass is an extension to CSS, and compiles .scss files to .css. For example, these source files:

src/
├── sample.scss
└── subdirectory/
    └── A.scss

Would result in this output:

build/
├── sample.css
└── subdirectory/
    └── A.css

For more details see the Sass documentation.

Note

Only the SCSS format is supported by Awe, not the original Sass indented format (i.e. .sass files), because it’s easier for people used to regular CSS to pick up.

Ignored files (partials)

Awe ignores all files and directories that start with an underscore (_). In Sass this is used to @import partials – for example, this directory structure:

src/
├── _partials/
│   └── reset.scss
├── _vars.scss
└── styles.scss

Will result in this output:

build/
└── styles.css

Note

Although this is mostly used for Sass partials, Awe will ignore any file or directory that starts with an underscore.

Compass

Compass is a popular CSS framework built on top of Sass. To use it, simply @import the file shown in the Compass documentation at the top of your .scss file. For example:

@import 'compass/typography/links/unstyled-link';

.footer a {
    @include unstyled-link;
}

This is compiled to:

.footer a {
    color: inherit;
    text-decoration: inherit;
    cursor: inherit;
}

.footer a:active, .footer a:focus {
    outline: none;
}

Tip

While it is possible to use @import 'compass'; as a short-hand, this is noticably slower to build than importing only the specific features required.

Tip

Many of the Compass mixins simply add vendor prefixes for CSS3. Instead of using these, I recommend enabling autoprefixer.

Note

You may need to be aware of the following Compass configuration options that Awe uses:

images_path      = 'src/img/'                     # used by image-url(), inline-image(), etc.
fonts_path       = 'src/fonts/'                   # used by font-url(), inline-font-files(), etc.
sprite_load_path = ['src/img/', 'src/_sprites/']  # used for sprite generation (see below)

This means images should be kept in a folder called img/, font files in fonts/ and sprites in _sprites/.

Sprites

Compass has the ability to take several small icons and combine them into a single image, then use that as a sprite in your CSS.

To do this, first create a directory inside src/_sprites/ with the name of the sprite – e.g. src/_sprites/navbar/. Inside that directory create a PNG image for each icon. You can also have variants ending with _hover, _active and _target which map to :hover, :active and :target in the CSS. So, for example, you may have a directory structure like this:

src/
├── _sprites/
│   └── navbar/
│       ├── edit.png
│       ├── edit_hover.png
│       ├── ...
│       ├── save.png
│       └── save_hover.png
└── sample.scss

Then in the SCSS file enter the following:

@import 'compass/utilities/sprites';
@import 'navbar/*.png';              // This path is relative to the _sprites/ directory
@include all-navbar-sprites;         // Replace 'navbar' with the directory name

This will generate a directory structure similar to the following:

build/
├── _generated/
│   └── navbar-s71af1c7425.png
└── sample.css

And the following classes will appear in the output file, ready for you to use in your HTML:

/* Replace 'navbar' with the directory name */
.navbar-delete       { ... }
.navbar-delete:hover { ... }
.navbar-edit         { ... }
.navbar-edit:hover   { ... }
.navbar-new          { ... }
.navbar-new:hover    { ... }
.navbar-save         { ... }
.navbar-save:hover   { ... }

Advanced spriting

If you require more control over the classes that are generated, there are several other ways to create them. For example:

@import 'compass/utilities/sprites';

$navbar-map: sprite-map('navbar/*.png');

.navbar {
    background: $navbar-map;
}

@each $sprite in sprite-names($navbar-map) {
    .navbar-#{$sprite} {
        @include sprite($navbar-map, $sprite, true);
    }
}

For more details, please see the Compass spriting documentation, options and mixins.

Note

The Compass documentation uses images/ as the base directory, whereas Awe recommends using _sprites/. You can also put them in the img/ directory if you prefer, but in that case the source images will be copied to the build directory as well.

Combining files

Awe can automatically combine multiple CSS/JavaScript files into a single file, allowing you to split the source files up neatly while reducing the number of downloads for end users.

Simply create a directory with a name that ends .css or .js and all the files within that directory will be concatenated (in alphabetical/numerical order) into a single output file. For example:

src/
└── combined.css/
    ├── 1.css
    ├── 2/
    │   ├── A.css
    │   └── B.scss
    └── 3.scss

First the .scss files will be compiled to CSS, then all 4 files will be combined (in the order 1.css, 2/A.css, 2/B.scss, 3.scss) into a single combined.css file:

build/
└── combined.css

Simple as that!

Caution

It is best to avoid mixing subdirectories and files, as some programs display all subdirectories first which may be confusing:

  • subdirectory/ (2)
  • file.css (1)
  • vendor.css (3)

Import files

Another way to combine multiple files is to create an import file – this is a YAML file with the extension .css.yaml or .js.yaml containing a list of files to import. This is mostly useful for importing vendor files:

src/
└── vendor.js.yaml

vendor/
├── chosen.js
└── jquery.js

Where vendor.js.yaml contains:

- ../vendor/jquery.js
- ../vendor/chosen.js

Will compile to:

build/
└── vendor.js

To import files from Bower (see below), simply prefix the filename with bower::

- bower: jquery/jquery.js
- bower: jquery-ui/ui/jquery-ui.js

Bower support

Bower is a package manager for third-party assets. It makes it easier to install and upgrade frontend dependencies such as jQuery and Bootstrap.

Create bower.json

Make sure you have a bower.json file – if not, run this to create one:

$ cd /path/to/repo
$ echo '{"name":"app","private":true}' > bower.json

Future Plans

I plan to add a command to generate this file, e.g. awe init bower, because bower init asks far more questions than are necessary!

Find packages

To find a package on Bower, run:

$ bower search <name>

Or use the online package search.

Install the packages you want

To install a package, run this:

$ bower install --save <name>

Sometimes you may need to specify a version number – e.g. jQuery will default to the 2.x branch which does not support IE8:

$ bower install --save jquery#1.x

This will create a bower_components/ directory in the project root (same directory as awe.yaml) containing the package and any dependencies.

Tip

If the package you want is not registered with Bower, you can install it from another source:

$ bower install --save user/repo                        # From GitHub
$ bower install --save http://example.com/script.js     # From a URL
$ bower install --save http://example.com/package.zip   # From a zip

For more details, please see the Bower install documentation.

Note

The installed packages should be checked into the Git repository, not ignored, to ensure the same version is installed on the live site. This advice may change in the future when bower.lock is implemented (and/or awe deploy is ready).

Update the config file

Update awe.yaml with the path to the Bower components directory:

ASSETS:

    default:
        src:          www/wp-content/themes/mytheme/src/
        dest:         www/wp-content/themes/mytheme/build/
        bower:        bower_components/
        autoprefixer: false

Import the files you need

Create a .js.yaml or .css.yaml import file (e.g. src/jquery.js.yaml), for example:

- bower: jquery/jquery.js

This will be compiled to build/jquery.js.

Note

An alternative is to load the file you need directly in your HTML, using the _bower/ symlink that is created:

<script src="/assets/_bower/jquery/jquery.min.js"></script>

Combining Bower and non-Bower files

You can easily combine Bower files with custom files, as described above. For example:

src/
├── app.css/
│   ├── 1-import.css.yaml   ==>   - bower: jquery-ui/themes/smoothness/jquery-ui.css
│   └── 2-custom.scss
└── app.js/
    ├── 1-import.js.yaml    ==>   - bower: jquery/jquery.js
    │                             - bower: jquery-ui/ui/jquery-ui.js
    └── 2-custom.coffee

Will result in:

build/
├── _bower/  ->  ..../bower_components/
├── app.css
└── app.js

(-> indicates a symlink.)

The URLs from jquery-ui.css (now in app.css) will automatically be rewritten to url(_bower/jquery-ui/themes/smoothness/<filename>).

Updating packages

To check for outdated dependencies:

$ bower list

To update them, first update bower.json if necessary (if you have specified a particular version to use), then run:

$ bower update

For more details, please see the Bower documentation.

Multiple asset groups

To compile assets in multiple directories, simply add another group with a different name:

ASSETS:

    theme:
        src:          www/wp-content/themes/mytheme/src/
        dest:         www/wp-content/themes/mytheme/build/
        bower:        false
        autoprefixer: false

    plugin:
        src:          www/wp-content/plugins/myplugin/src/
        dest:         www/wp-content/plugins/myplugin/build/
        bower:        false
        autoprefixer: true

Reasons to do this include:

  • Multiple themes/plugins in a single project
  • Different config settings for different assets
  • Speed up watch builds by only rebuilding one directory at a time

The group name must be alphanumeric ([a-zA-Z0-9]+).

Future Plans

The group name is not currently used anywhere, but in the future it may be possible to build individual directories (e.g. awe build theme).