ericclemmons / grunt-angular-templates

Grunt build task to concatenate & pre-load your AngularJS templates
MIT License
711 stars 108 forks source link

grunt-angular-templates

Build Status Dependencies devDependencies

Speed up your AngularJS app by automatically minifying, combining, and automatically caching your HTML templates with $templateCache.

Here's an example of the output created by this task from multiple .html files:

angular.module('app').run(["$templateCache", function($templateCache) {
  $templateCache.put("home.html",
    // contents for home.html ...
  );
  ...
  $templateCache.put("src/app/templates/button.html",
    // contents for button.html
  );
}]);

Then, when you use ng-include or templateUrl with $routeProvider, the template is already loaded without an extra AJAX request!

Table of Contents

Installation

This plugin requires Grunt ~0.4.0

Usemin integration requires grunt-usemin ~2.0.0

Install the plugin:

$ npm install grunt-angular-templates --save-dev

Enable the plugin within your Gruntfile:

grunt.loadNpmTasks('grunt-angular-templates');

Options

angular

Global namespace for Angular.

If you use angular.noConflict(), then set this value to whatever you re-assign angular to. Otherwise, it defaults to angular.

bootstrap

Callback to modify the bootstraper that registers the templates with $templateCache.

By default, the bootstrap script wraps function($templateCache) { ... } with:

angular.module('app').run(['$templateCache', ... ]);

If you want to create your own wrapper so you register the templates as an AMD or CommonJS module, set the bootstrap option to something like:

bootstrap: function(module, script) {
  return 'module.exports[module] = ' + script + ';';
}

concat

Name of concat target to append the compiled template path to.

This is especially handy if you combine your scripts using grunt-contrib-concat or grunt-usemin.

htmlmin

Object containing htmlmin options that will significantly reduce the filesize of the compiled templates.

Without this, the HTML (whitespace and all) will be faithfully compiled down into the final .js file. Minifying that file will only cut down on the Javascript code, not the HTML within the strings.

Note - this does incur a performance cost. Simply leave out this option to prevent minificaiton.

I recommend using the following settings for production:

htmlmin: {
  collapseBooleanAttributes:      true,
  collapseWhitespace:             true,
  keepClosingSlash:               true, // Only if you are using SVG in HTML
  removeAttributeQuotes:          true,
  removeComments:                 true, // Only if you don't use comment directives!
  removeEmptyAttributes:          true,
  removeRedundantAttributes:      true,
  removeScriptTypeAttributes:     true,
  removeStyleLinkTypeAttributes:  true
}

module

String of the angular.module to register templates with.

If not specified, it will automatically be the name of the ngtemplates subtask (e.g. app, based on the examples below).

prefix

String to prefix template URLs with. Defaults to ''

If you need to use absolute urls:

ngtemplates: {
  app: {
    options: {
      prefix: '/'
    }
  }
}

If you serve static assets from another directory, you specify that as well.

source

Callback to modify the template's source code.

If you would like to prepend a comment, strip whitespace, or do post-processing on the HTML that ngtemplates doesn't otherwise do, use this function.

append

Boolean to indicate the templates should be appended to dest instead of replacing it. Normally grunt-angular-templates creates a new file at dest. This option makes it append the compiled templates to the dest file rather than replace its contents. This is just a useful alternative to creating a temporary dest file and concatting it to your application.

standalone

Boolean indicated if the templates are part of an existing module or a standalone. Defaults to false.

url

Callback to modify the template's $templateCache URL.

Normally, this isn't needed as specifying your files with cwd ensures that URLs load via both AJAX and $templateCache.

usemin

Path to <!-- build:js [path/to/output.js] --> usemin target

This should be the output path of the compiled JS indicated in your HTML, such as path/to/output.js shown here.

quotes

Use single or double quotes to wrap the template strings

Defaults to 'double', other option is 'single'

Usage

Compiling HTML Templates

After configuring your ngtemplates task, you can either run the task directly:

$ grunt ngtemplates

Or, bake it into an existing task:

grunt.registerTask('default', [ 'jshint', 'ngtemplates', 'concat' ]);

Including Compiled Templates

Finally, you have to load the compiled templates' .js file into your application.

Using HTML

<script src="https://github.com/ericclemmons/grunt-angular-templates/raw/master/templates.js"></script>

Using Grunt's concat task:

This is my personal preference, since you don't have to worry about what the destination file is actually called.

concat:   {
  app:    {
    src:  [ '**.js', '<%= ngtemplates.app.dest %>' ],
    dest: [ 'app.js' ]
  }
}

Using grunt-usemin

Using the following HTML as an example:

<!-- build:js dist/vendors.js -->
<script src="https://github.com/ericclemmons/grunt-angular-templates/raw/master/bower_components/angular/angular.js"></script>
<script src="https://github.com/ericclemmons/grunt-angular-templates/raw/master/bower_components/angular-resource/angular-resource.js"></script>
<!-- endbuild -->

Do not use the concat option, even though grunt-usemin generates a concat.generated object behind the scenes. Instead, use the usemin option to indicate the anticipated output filepath from grunt-usemin.

ngtemplates:  {
  app:        {
    src:      '**.html',
    dest:     'template.js',
    options:  {
      usemin: 'dist/vendors.js' // <~~ This came from the <!-- build:js --> block
    }
  }
}

Note: Earlier versions of grunt-usemin (correctly, in my opinion) would have generated a concat['dist/vendors.js'] object for each build section in the HTML. Now, because there's a single concat.generated object with all JS/CSS files within it, I'm back-tracking the proper concat target for you.

Examples

Register HTML Templates in app Module

ngtemplates:  {
  app:        {
    src:      '**.html',
    dest:     'templates.js'
  }
}

Register Relative Template URLs

Normally, your app, templates, & server are in separate folders, which means that the template URL is different from the file path.

ngtemplates:  {
  app:        {
    cwd:      'src/app',
    src:      'templates/**.html',
    dest:     'build/app.templates.js'
  }
}

This will store the template URL as templates/home.html instead of src/app/templates/home.html, which would cause a 404.

Minify Template HTML

Simply pass the same options as the htmlmin task:

ngtemplates:    {
  app:          {
    src:        '**.html',
    dest:       'templates.js',
    options:    {
      htmlmin:  { collapseWhitespace: true, collapseBooleanAttributes: true }
    }
  }
}

Or, if you already have an existing htmlmin task, you can reference it:

ngtemplates:    {
  app:          {
    src:        '**.html',
    dest:       'templates.js',
    options:    {
      htmlmin:  '<%= htmlmin.app %>'
    }
  }
}

Customize Template URL

Suppose you only use ngtemplates when on production, but locally you serve templates via Node, sans the .html extension.

You can specify a url callback to further customize the registered URL:

ngtemplates:  {
  app:        {
    src:      '**.html',
    dest:     'templates.js',
    options:  {
      url:    function(url) { return url.replace('.html', ''); }
    }
  }
}

Customize Output

Some people like AMD & RequireJS and would like wrap the output in AMD or something else (don't ask me why!):

ngtemplates:      {
  app:            {
    src:          '**.html',
    dest:         'templates.js',
    options:      {
      bootstrap:  function(module, script) {
        return 'define(' + module + ', [], function() { return { init: ' + script + ' }; });';
      }
    }
  }
}

You will be able to custom everything surrounding $templateCache.put(...).

Changelog

License

Copyright (c) 2013 Eric Clemmons Licensed under the MIT license.

Bitdeli Badge