• This repository has been archived on 20/Apr/2018
  • Stars
    star
    1,219
  • Rank 38,465 (Top 0.8 %)
  • Language
    JavaScript
  • License
    BSD 2-Clause "Sim...
  • Created almost 12 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

[UNMAINTAINED] Replaces references to non-optimized scripts or stylesheets into a set of HTML files (or any templates/views)

grunt-usemin Linux Build Status Windows Build status

Gitter

Replaces references from non-optimized scripts, stylesheets and other assets to their optimized version within a set of HTML files (or any templates/views).

Important

3.1.0 has a breaking change with uglify step renamed to uglify to be consistent with grunt-contrib-uglify task which name is uglify (and not uglifyjs).

Stick to 3.0.0 while we find a good solution to not have a breaking change while having name consistency.

Maintainer wanted

Notice

grunt-usemin is going under some major developments to tackle the long list of issues. As they might break with master they are merged into dev branch.

Currently what has been merged:

  • Support for a resolveSource function option
  • Warning for any missing files instead of silent errors
  • Migrate from regex to HTML parser
  • Support for multiple target (current)

Getting Started

If you haven't used grunt before, be sure to check out the Getting Started guide, as it explains how to create a gruntfile as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:

$ npm install grunt-usemin --save-dev

Tasks

usemin replaces the references of scripts, stylesheets and other assets within HTML files dynamically with optimized versions of them. To do this usemin exports 2 built-in tasks called useminPrepare and usemin and utilizes a couple of other Grunt plugins for the optimization process. usemin does this by generating the subtasks for these Grunt plugins dynamically.

The built-in tasks of usemin:

  • useminPrepare prepares the configuration to transform specific blocks in the scrutinized file into a single line, targeting an optimized version of the files. This is done by generating subtasks called generated for each of the optimization steps handled by the Grunt plugins listed below.
  • usemin replaces the blocks by the file they reference, and replaces all references to assets by their revisioned version if it is found on the disk. This target modifies the files it is working on.

Grunt plugins which usemin can use to optimize files:

  • concat concatenates files (usually JS or CSS).
  • uglify minifies JS files.
  • cssmin minifies CSS files.
  • filerev revisions static assets through a file content hash.

To install these plugins, run:

$ npm install grunt-contrib-concat grunt-contrib-uglify grunt-contrib-cssmin grunt-filerev --save-dev

Important: You still need to manually install and load these dependencies.

In a typical usemin setup you launch useminPrepare first, then call every optimization step you want through their generated subtask and call usemin in the end. It could look like this:

// simple build task
grunt.registerTask('build', [
  'useminPrepare',
  'concat:generated',
  'cssmin:generated',
  'uglify:generated',
  'filerev',
  'usemin'
]);

The useminPrepare task

useminPrepare task updates the grunt configuration to apply a configured transformation flow to tagged files (i.e. blocks). By default the transformation flow is composed of concat and uglify for JS files, but it can be configured.

Blocks

Blocks are expressed as:

<!-- build:<type>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
  • type: can be js, css or a custom type with a block replacement function defined
  • If another type, the block will be ignored. Useful for "development only" blocks that won't appear in your build
  • alternate search path: (optional) By default the input files are relative to the treated file. Alternate search path allows one to change that
  • path: the file path of the optimized file, the target output

An example of this in completed form can be seen below:

<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

Transformation flow

The transformation flow is made of sequential steps: each of the steps transform the file, and useminPrepare will modify the configuration in order for the described steps to be correctly performed.

By default the flow is: concat -> uglify. Additionally to the flow, at the end, some postprocessors can be launched to further alter the configuration.

Let's have an example, using the default flow (we're just going to look at the steps), app for input dir, dist for output dir, and the following block:

<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

The produced configuration will look like:

{
  concat: {
    generated: {
      files: [
        {
          dest: '.tmp/concat/js/app.js',
          src: [
            'app/js/app.js',
            'app/js/controllers/thing-controller.js',
            'app/js/models/thing-model.js',
            'app/js/views/thing-view.js'
          ]
        }
      ]
    }
  },
  uglify: {
    generated: {
      files: [
        {
          dest: 'dist/js/app.js',
          src: [ '.tmp/concat/js/app.js' ]
        }
      ]
    }
  }
}

Directories

Internally, the task parses your HTML markup to find each of these blocks, and initializes the corresponding Grunt config for the concat / uglify tasks when type=js, the concat / cssmin tasks when type=css.

One doesn't need to specify a concat/uglify/cssmin configuration anymore.

It uses only one target: html, with a list of the concerned files. For example, in your Gruntfile.js:

By default, it will consider the directory where the looked-at file is located as the 'root' filesystem. Each relative path (for example to a JavaScript file) will be resolved from this path. Same goes for the absolute ones. If you need to change the 'root' dir, use the root option (see below).

useminPrepare: {
  html: 'index.html'
}

Targets can also be configured using the grunt src-dest files syntax http://gruntjs.com/configuring-tasks#files, e.g.

useminPrepare: {
  foo: {
    src: ['index.html', 'another.html']
  },
  bar: {
    src: 'index.html'
  }
}

Options

dest

Type: string
Default: nil

Base directory where the transformed files should be output.

staging

Type: string
Default: .tmp

Base directory where the temporary files should be output (e.g. concatenated files).

root

Type: string, array
Default: null

The root directory from which your files will be resolved.

flow

Type: object
Default: { steps: { js: ['concat', 'uglify'], css: ['concat', 'cssmin'] }, post: {} }

This allow you to configure the workflow, either on a per-target basis, or for all the targets. You can change the steps or the post-processors (post) separately.

For example:

  • to change the js steps and post for the target html:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      html: {
        steps: {
          js: ['uglify']
        },
        post: {}
      }
    }
  }
}
  • to change the js steps and post for all targets:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      steps: {
        js: ['uglify']
      },
      post: {}
    }
  }
}
  • to customize the generated configuration via post-processors:
useminPrepare: {
  html: 'index.html',
  options: {
    flow: {
      steps: {
        js: ['uglify']
      },
      post: {
        js: [{
          name: 'uglify',
          createConfig: function (context, block) {
            var generated = context.options.generated;
            generated.options = {
              foo: 'bar'
            };
          }
        }]
      }
    }
  }
}

The given steps or post-processors may be specified as strings (for the default steps and post-processors), or as an object (for the user-defined ones).

User-defined steps and post-processors

User-defined steps and post-processors must have 2 attributes:

  • name: name of the Gruntfile attribute that holds the corresponding config
  • createConfig which is a 2 arguments function ( a context and the treated block)

For an example of steps/post-processors, you can have a look at concat and uglify in the lib/config directory of this repository.

createConfig

The createConfig function is responsible for creating (or updating) the configuration associated to the current step/post-processor. It takes 2 arguments ( a context and the treated block), and returns a configuration object.

context

The context object represent the current context the step/post-processor is running in. As the step/post-processor is a step of a flow, it must be listed in the input files and directory it must write a configuration for, potentially the already existing configuration. It must also indicate to the other steps/post-processor which files it will output in which directory. All this information is held by the context object. Attributes:

  • inDir: the directory where the input file for the step/post-processors will be
  • inFiles: the list of input file to take care of
  • outDir: where the files created by the step/post-processors will be
  • outFiles: the files that are going to be created
  • last: whether or not we're the last step of the flow
  • options: options of the Gruntfile.js for this step (e.g. if the step is named foo, holds configuration of the Gruntfile.js associated to the attribute foo)
block

The actual looked-at block, parsed and put in a structure.

Example: The following block

<!-- build:js scripts/site.js -->',
<script src="foo.js"></script>',
<script src="bar.js"></script>',
<script src="baz.js"></script>',
<!-- endbuild -->'

is parsed as, and given to createConfig as:

var block = {
  type: 'js',
  dest: 'scripts/site.js',
  src: [
    'foo.js',
    'bar.js',
    'baz.js'
  ],
  raw: [
    '    <!-- build:js scripts/site.js -->',
    '    <script src="foo.js"></script>',
    '    <script src="bar.js"></script>',
    '    <script src="baz.js"></script>',
    '    <!-- endbuild -->'
  ]
};

The usemin task

The usemin task has 2 actions:

  • First it replaces all the blocks with a single "summary" line, pointing to a file creating by the transformation flow.
  • Then it looks for references to assets (i.e. images, scripts, ...), and tries to replace them with their revved version if it can find one on disk

Finding assets

By default usemin will look for a map object created by grunt-filerev, located in grunt.filerev.summary. If it does not find it it will revert to disk lookup which is longer.

Note that by using the options.revmap (see below), you can furnish a map object.

On directories

When usemin tries to replace referenced assets with their revved version it has to look at a collection of directories (asset search paths): for each of the directories of this collection it will look at the below tree, and try to find the revved version. This asset search directories collection is by default set to the location of the file that is scrutinized but can be modified (see Options below).

Example 1: file dist/html/index.html has the following content:

<link rel="stylesheet" href="styles/main.css">
<img src="../images/test.png">

By default usemin will look under dist/html for revved versions of:

  • styles/main.css: a revved version of main.css will be looked at under the dist/html/styles directory. For example a file dist/html/styles/main.1234.css will match (although dist/html/main.1234.css won't: the path of the referenced file is important)
  • ../images/test.png: it basically means that a revved version of test.png will be looked for under the dist/images directory

Example 2: file dist/html/index.html has the following content:

<link rel="stylesheet" href="/styles/main.css">
<img src="/images/test.png">

By default usemin will look under dist/html for revved versions of styles/main.css and images/test.png. Now let's suppose our assets are scattered in dist/assets. By changing the asset search path list to ['dist/assets'], the revved versions of the files will be searched for under dist/assets (and thus, for example, dist/assets/images/test.875487.png and dist/assets/styles/main.98090.css) will be found.

Options

assetsDirs

Type: array
Default: Single item array set to the value of the directory where the currently looked at file is.

List of directories where we should start to look for revved version of the assets referenced in the currently looked at file.

Example:

usemin: {
  html: 'build/index.html',
  options: {
    assetsDirs: ['foo/bar', 'bar']
  }
}

Suppose in index.html you have a reference to /images/foo.png, usemin will search for the revved version of /images/foo.png, say /images/foo.12345678.png in any directories in assetsDirs options.

In others words, given the configuration above, usemin will search for the existence of one of these files:

  • foo/bar/images/foo.12345678.png
  • bar/images/foo.12345678.png

patterns

Type: object
Default: {}

Allows for user defined pattern to replace reference to files. For example, let's suppose that you want to replace all references to 'image.png' in your Javascript files by the revved version of image.png found below the directory images.

By specifying something along the lines of:

usemin: {
  js: '*.js',
  options: {
    assetsDirs: 'images',
    patterns: {
      js: [
        [/(image\.png)/, 'Replacing reference to image.png']
      ]
    }
  }
}

So in short:

  • key in pattern should match the target (e.g js key for the target js)
  • Each pattern is an array of arrays. These arrays are composed of 4 items (last 2 are optional):
    • First one if the regexp to use. The first group is the one that is supposed to represent the file reference to replace
    • Second one is a logging string
    • A function which behaves like a filter-in. Receives the matched group and must return the file path of the asset. Great functionality when you have a compiled file by a template engine.
    • A function which behaves like a filter-out. It receives the revved path of the asset and must return it as an url from it will be reached from web server.

blockReplacements

Type: 'Object'
Default: { css: function (block) { ... }, js: function (block) { ... } }

This lets you define how blocks get their content replaced. Useful to have block types other that css and js.

  • Object key matches a block type
  • Value is the replacement function for that block type.
    • The replacement function gets called with a single argument: a block object.
    • Must return a String, the "summary" line that will replace the block content.

For example, to create a less block you could define its replacement function like this:

usemin: {
  html: 'index.html',
  options: {
    blockReplacements: {
      less: function (block) {
          return '<link rel="stylesheet" href="' + block.dest + '">';
      }
    }
  }
}

revmap

Type: string
Default: ''

Indicate the location of a map file, as produced by grunt-filerev for example. This map file is a simple JSON file, holding an object which attributes are the original file and associated value is the transformed file. For example:

{
  "foo.png": "foo.1234.png"
}

This map will be used instead of looking for file on the disk.

On directories

The main difference to be kept in mind, regarding directories and tasks, is that for useminPrepare, the directories needs to indicate the input, transient and output path needed to output the right configuration for the processors pipeline, whereas in the case of usemin it only reflects the output paths, as all the needed assets should have been output to the destination dir (either transformed or just copied)

useminPrepare

useminPrepare is trying to prepare the right configuration for the pipeline of actions that are going to be applied on the blocks (for example concatenation and uglify-cation). As such it needs to have the input directory, temporary directories (staging) and destination directory. The files referenced in the block are either absolute or relative (/images/foo.png or ../../images/foo.png). Absolute files references are looked in a given set of search path (input), which by default is set to the directory where the html/css file examined is located (can be overridden per block, or more generally through root option). Relative files references are also looked at from location of the examined file, unless stated otherwise.

usemin

usemin target replaces references to images, scripts, css, ... in the furnished files (html, css, ...). These references may be either absolute (i.e. /images/foo.png) or relative (i.e. image/foo.png or ../images/foo.png). When the reference is absolute a set of asset search paths should be looked at under the destination directory (for example, using the previous example, and searchpath equal to ['assets'], usemin would try to find either a revved version of the image of the image below the assets directory: for example dest/assets/images/foo.1223443.png). When the reference is relative, by default the referenced item is looked in the path relative to the current file location in the destination directory (e.g. with the preceding example, if the file is build/bar/index.html, then transformed index.html will be in dist/bar, and usemin will look for dist/bar/../images/foo.32323.png).

Use cases

Simple one

|
+- app
|   +- index.html
|   +- assets
|       +- js
|          +- foo.js
|          +- bar.js
+- dist

We want to optimize foo.js and bar.js into optimized.js, referenced using relative path. index.html should contain the following block:

<!-- build:js assets/js/optimized.js -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->

We want our files to be generated in the dist directory.

By using the following useminPrepare config:

{
  useminPrepare: {
    html: 'app/index.html',
    options: {
      dest: 'dist'
    }
  }
}

This will, on the fly, generate the following configuration:

{
  concat: {
    '.tmp/concat/assets/js/optimized.js': [
      'app/assets/js/foo.js',
      'app/assets/js/bar.js'
    ]
  },

  uglify: {
    'dist/assets/js/optimized.js': ['.tmp/concat/assets/js/optimized.js']
  }
}

HTML file and asset files in sibling directories

app
|
+- html
|   +- index.html
+- assets
|   +- js
|      +- foo.js
|      +- bar.js
+- dist

We want to optimize foo.js and bar.js into optimized.js, referenced using absolute path. index.html should contain the following block:

<!-- build:js /assets/js/optimized.js -->
<script src="/assets/js/foo.js"></script>
<script src="/assets/js/bar.js"></script>
<!-- endbuild -->

We want our files to be generated in the dist directory.

By using the following useminPrepare config:

{
  useminPrepare: {
    html: 'html/index.html',
    options: {
      root: 'app',
      dest: 'dist'
    }
  }
}

This will, on the fly, generate the following configuration:

{
  concat:
  {
    '.tmp/concat/assets/js/optimized.js': [
      'app/assets/js/foo.js',
      'app/assets/js/bar.js'
    ]
  },

  uglify:
  {
    'dist/assets/js/optimized.js': ['.tmp/concat/assets/js/optimized.js']
  }
}

License

BSD license and copyright Google

More Repositories

1

yeoman

Yeoman - a set of tools for automating development workflow
10,081
star
2

generator-angular

Yeoman generator for AngularJS
JavaScript
5,729
star
3

yo

CLI tool for running Yeoman generators
JavaScript
3,835
star
4

generator-webapp

A gulp.js generator for modern webapps
JavaScript
3,770
star
5

generator-chrome-extension

Scaffold out a Chrome extension
JavaScript
2,617
star
6

update-notifier

Update notifications for your CLI app
JavaScript
1,762
star
7

generator-generator

Generate a Yeoman generator
JavaScript
1,223
star
8

generator

Rails-inspired generator system that provides scaffolding for your apps
TypeScript
1,204
star
9

yeoman-app

A desktop app that scaffolds projects using Yeoman
JavaScript
988
star
10

generator-webapp_DEPRECATED

Yeoman generator that scaffolds out a front-end web app
JavaScript
974
star
11

generator-polymer

Scaffold out a Polymer project
JavaScript
926
star
12

generator-mobile

Scaffold out a mobile project based on Web Starter Kit
JavaScript
918
star
13

configstore

Easily load and persist config without having to think about where and how
JavaScript
866
star
14

yeoman.io

Yeoman website
CSS
790
star
15

generator-backbone

Scaffold out a Backbone.js project
JavaScript
638
star
16

generator-node

Create a Node.js module
JavaScript
577
star
17

insight

Node.js module to help you understand how your tool is being used by anonymously reporting usage metrics to Google Analytics
JavaScript
557
star
18

bower-requirejs

[DEPRECATED] Automagically wire-up installed Bower components into your RequireJS config
JavaScript
375
star
19

generator-chromeapp

Scaffold out a Chrome app
JavaScript
310
star
20

stringify-object

Stringify an object/array like JSON.stringify just without all the double-quotes
JavaScript
307
star
21

grunt-filerev

[DEPRECATED] File revving
JavaScript
260
star
22

yosay

Tell Yeoman what to say
JavaScript
206
star
23

grunt-bower-requirejs

[DEPRECATED] Grunt task - Automagically wire-up installed Bower components into your RequireJS config
JavaScript
198
star
24

generator-bootstrap

Yeoman generator for Bootstrap
JavaScript
186
star
25

generator-karma

Yeoman generator for Karma
JavaScript
172
star
26

environment

Yeoman runtime environment
JavaScript
127
star
27

generator-jquery

Generate a jQuery plugin
JavaScript
85
star
28

generator-gruntfile

Create a basic Gruntfile with yo.
JavaScript
74
star
29

doctor

Detect potential issues with users system that could prevent Yeoman from working correctly
JavaScript
61
star
30

yeoman-assert

Assert utility from yeoman
JavaScript
53
star
31

yeoman-generator-list

JavaScript
52
star
32

yeoman-test

Test utilities for Yeoman generators
TypeScript
44
star
33

generator-mocha

Yeoman generator for Mocha
JavaScript
41
star
34

generator-gruntplugin

Create a gruntplugin module with yo, including Nodeunit unit tests.
JavaScript
35
star
35

generator-jasmine

Yeoman generator for Jasmine
JavaScript
34
star
36

yeoman-character

The Yeoman character in your CLI. Like wat.
JavaScript
21
star
37

yeoman-welcome

Yeoman welcome message used in generators
JavaScript
19
star
38

media

Yeoman logo and artwork
16
star
39

generator-commonjs

Generate a CommonJS module
JavaScript
16
star
40

insight-dashboard

[DEPRECATED] Insight into Yeoman
CSS
11
star
41

Hackathons

Running a Yeoman hackathon? Start here for ideas, tips, and goals
10
star
42

html-wiring

[DEPRECATED] Set of utilities to update HTML files
JavaScript
10
star
43

cli-list

Parse comma-separated argument lists.
JavaScript
9
star
44

yeoman-remote

Fetch packages and archives from remote resources with cache support
JavaScript
8
star
45

generator-dummytest

JavaScript
3
star
46

generator-dummy

Dummy generator used for unit testing purpose
JavaScript
2
star
47

yeoman-api

TypeScript
1
star