The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mojolicious::Plugin::AssetPack::Guides::Tutorial - AssetPack tutorial

OVERVIEW

This guide will give detailed information about how to define assets and include them into your templates.

See "DESCRIPTION" in Mojolicious::Plugin::AssetPack for a short description of AssetPack.

GUIDE

Loading the plugin

The plugin need to be installed an loaded before any assets can be defined:

  $app->plugin(AssetPack => \%args);

Details about %args can be found under "register" in Mojolicious::Plugin::AssetPack, but there are one mandatory argument worth noting: "pipes". "pipes" need to be a list of all the pipes you need to process your assets. Example:

  $app->plugin(AssetPack => {pipes => [qw(Sass Css Combine)]});

Loading the plugin with the list above will enable AssetPack to process Sass and Css files, minify them and combine them into a aingle asset in production.

Optional dependencies

AssetPack only has optional dependencies. The reason for that is that the dependencies should only be required while developing, and not for running the application. See https://github.com/jhthorsen/mojolicious-plugin-assetpack/blob/v2/cpanfile for a complete list, but here are the current list:

Pipes

AssetPack does not do any heavy lifting itself: All the processing is left to the pipe objects.

Where to place source files

The source/input files that make up a virtual asset (topic) can come from either...

On disk

AssetPack will look for source files in the "assets" directory, relative to the application home. This directory is not shared on the internet like the "public" directory, but the generated assets will still be available thanks to a custom route.

Mojolicious::Plugin::AssetPack::Store is a sub class of Mojolicious::Static, allowing it to find files relative to "paths" in Mojolicious::Static. For example, to change asset search paths, you can do:

    $app->asset->store->paths(["/some/new/location", "/other/location"]);

DATA section

Mojolicious::Plugin::AssetPack::Store is a sub class of Mojolicious::Static, allowing it to look for files in DATA sections of "classes" in Mojolicious::Static.

The DATA section can also be used to lookup "@import" files. (Currently only supported by Mojolicious::Plugin::AssetPack::Pipe::Sass)

Web

Any file starting with "http" or "https" will be downloaded from web using "ua" in Mojolicious::Plugin::AssetPack.

It will also parse recursively "@import" files and download those as well. (Currently only supported by Mojolicious::Plugin::AssetPack::Pipe::Sass)

Assets from web will be cached locally to prevent downloading new and untested assets on each application startup.

Current Mojolicious application

Any "Web" asset with the hostname "local" will be routed to the current Mojolicious application. Example:

  http://local/some/resource
         ^^^^^

Process assets

Assets should be defined when you application starts. This can either be done using a definition file or inside you application.

Defining assets in the application

Assets can be defined using the "process" in Mojolicious::Plugin::AssetPack method:

  $app->asset->process(
    "app.css" => (
      "sass/bar.scss",
      "foo/bar.css",
      "https://github.com/Dogfalo/materialize/blob/master/sass/materialize.scss",
    )
  );

In the example above we have defined a topic named "app.css" which later can be included in templates. The list of files following are the source files which will make up the final asset.

Defining assets in a definition file

Moving the definition to an external file can be useful for keeping the application code tidy. The definition file can also be defined in the "DATA" section. The default file is called "assetpack.def" and will be looked up if "process" in Mojolicious::Plugin::AssetPack is called without arguments. Example file:

  ! app.css
  < sass/bar.scss
  << https://github.com/Dogfalo/materialize/blob/master/sass/materialize.scss
  < sass/main.scss

Empty lines and lines starting with "#" will be skipped. Each line starting with "!" will be used to define a topic (virtual asset name), and "<" will define a source file. This means that the file above will result in (almost) the same as in the example above.

The difference can be found on the line with a double "<": This results in the asset to be downloaded, but not included in the output asset. This is useful when you have something like "sass/main.scss" that depend on "materialize.scss", but "materialize.scss" itself should not be compiled.

It is also possible to add (EXPERIMENTAL) conditions:

  ! app.css
  < development.css [mode==development] [minify==0]
  < production.css  [mode!=development]

"development.css" will be processed if "mode" in Mojolicious is "development" and "minify" in Mojolicious::Plugin::AssetPack is "0". "production.css" will be processed if "mode" in Mojolicious is something else than "development". This is especially useful if you want to include a JavaScript with debug flags set while developing, but switch to a smaller version without debug in production.

Using assets

Any processed asset can be accessed by refering to a topic.

Template

An asset can be included in a template using the "asset" in Mojolicious::Plugin::AssetPack helper:

  <head>
    %= asset "app.css"
    %= asset "app.js"
  </head>

The "asset" in Mojolicious::Plugin::AssetPack helper takes additional arguments which will be passed on directly to either the "javascript" in Mojolicious::Plugin::TagHelpers helper or "stylesheet" in Mojolicious::Plugin::TagHelpers helper. Example:

    %= asset "app.css", media => "print"

In production mode, the helper above will just result in one "link" tag. On the other hand, if you are in "development" mode, it will result in on "link" tag per source asset.

Asset objects

It is also possible to retrieve the processed asset objects. The example below will retrieve a Mojo::Collection object holding zero or more Mojolicious::Plugin::AssetPack::Asset objects:

  my $collection = $app->asset->processed("app.css");
  print $collection->map("checksum")->join(", ");

This can also be used to inline assets in a template:

  %= stylesheet sub { asset->processed('app.css')->map('content')->join }

Application mode

The application mode will define if the assets should be combined and minified. The "minify" in Mojolicious::Plugin::AssetPack attribute can also be set manually if you have special needs.

Development

The assets will be processed, but not minifed/combined if MOJO_MODE or "mode" in Mojolicious is set to "development". This is to make it easier to map JavaScript or CSS bugs to a specific file and line. "development" is the default mode while running morbo:

  $ morbo -w assets/ -w lib/ -w templates/ script/myapp

Any other mode

Any "production" mode will result in one combined and minified asset. This will save bandwidth and roundtrip time to the server.

Caching

Processed assets will be cached to disk when possible. The process step is run so if such a processed asset exists, the process step will not be run again. This again only require external tools (less, coffee, ...) and modules (JavaScript::Minifier::XS, CSS::Sass) to be required while developing, but can be skipped when installing an already built application.

Assets without topics

One nifty feature is to use Mojolicious::Plugin::AssetPack for assets which does not have any pipe to process them. The reason why this comes in handy is to avoid cache issues, since changing the file on disk will generate a new URL.

These assets can also be defined directly in the templates, without having to be defined in the application startup process. Examples:

  # <img src="/asset/52e98718f0/foo.gif">
  %= asset "/image/foo.gif"

  # <img src="/asset/87652910af/baz.svg">
  %= asset "/image/baz.svg"

  # <link rel="icon" href="/asset/65428718f1/bar.ico">
  %= asset "/image/bar.ico"

  # <source src="/asset/87652718f0/baz.mp3" type="audio/mpeg">
  %= asset "/audio/baz.mp3"

  # <source src="/asset/52e87652f0/foo.mp4" type="video/mp4">
  %= asset "/video/foo.mp4"

  # <source src="/asset/52eaz7613a/bar.ogg" type="audio/ogg">
  %= asset "/audio/bar.ogg"

  # <source src="/asset/baf72618f1/foo.ogv" type="audio/ogv">
  %= asset "/video/foo.ogv"

  # <source src="/asset/92118711f0/bar.webm" type="audio/webm">
  %= asset "/video/bar.webm"

SEE ALSO

Mojolicious::Plugin::AssetPack and Mojolicious::Plugin::AssetPack::Guides::Cookbook.