Giter VIP home page Giter VIP logo

grunt-rev's Introduction

grunt-rev

Build Status Project Status: Unsupported - The project has reached a stable, usable state but the author(s) have ceased all work on it. A new maintainer may be desired.

Static file asset revisioning through content hashing

Getting Started

If you haven't used grunt before, be sure to check out the Getting Started guide.

From the same directory as your project's Gruntfile and package.json, install this plugin with the following command:

npm install grunt-rev --save-dev

Once that's done, add this line to your project's Gruntfile:

grunt.loadNpmTasks('grunt-rev');

If the plugin has been installed correctly, running grunt --help at the command line should list the newly-installed plugin's task or tasks. In addition, the plugin should be listed in package.json as a devDependency, which ensures that it will be installed whenever the npm install command is run.

The "rev" task

Use the rev task together with yeoman/grunt-usemin for cache busting of static files in your app. This allows them to be cached forever by the browser.

Overview

In your project's Gruntfile, add a section named rev to the data object passed into grunt.initConfig().

grunt.initConfig({
  rev: {
    options: {
      encoding: 'utf8',
      algorithm: 'md5',
      length: 8
    },
    assets: {
      files: [{
        src: [
          'img/**/*.{jpg,jpeg,gif,png}',
          'fonts/**/*.{eot,svg,ttf,woff}'
        ]
      }]
    }
  },
})

Options

options.encoding

Type: String Default value: 'utf8'

The encoding of the file contents.

options.algorithm

Type: String Default value: 'md5'

algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are 'sha1', 'md5', 'sha256', 'sha512', etc. On recent releases, openssl list-message-digest-algorithms will display the available digest algorithms.

options.length

Type: Number Default value: 8

The number of characters of the file content hash to prefix the file name with.

Usage Examples

Basic Asset Revving

This will rename app.js and app.css with an 8 character long hash prefix. For example js/9becff3a.app.js and css/ae35dd05.app.css. The hash value depends on the file contents.

grunt.initConfig({
  rev: {
    files: {
      src: ['scripts/app.js', 'css/app.css']
    }
  }
})

Custom Options

Change the algorithm or length to style the generated asset file names. Note that the usemin companion task requires at least one anycase hexadecimal character to prefix the file name.

grunt.initConfig({
  rev: {
    options: {
      algorithm: 'sha1',
      length: 4
    },
    files: {
      src: ['**/*.{js,css,png,jpg}']
    }
  }
})

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using grunt.

Release History

(Nothing yet)

grunt-rev's People

Contributors

michaellopez avatar sebdeckers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grunt-rev's Issues

Exeception files attribute

Don't know if the best approach is to create a new attribute to add exception files but here is my scenario:

  • I'm using Yo and Bower along with Grunt

  • I'm building a mobile first project and through the following code snippet I load the JS lib:

    <script>
        document.write('<script src="assets/js/vendor/' +
        ('__proto__' in {} ? 'zepto' : 'jquery') +
        '.js"><\/script>')
    </script>
    

I've also configured Gruntfile to place these files directly from Bower components to my "assets/js/vendor" folder.

    concat: {
        basic_and_extras: {
            files: {
                'dist/assets/js/vendor/jquery.js': 'app/bower_components/jquery/jquery.js',
                'dist/assets/js/vendor/zepto.js': 'app/bower_components/zeptojs/index.js',
                'dist/assets/js/vendor/fastclick.js': 'app/bower_components/fastclick/lib/fastclick.js'
            }
        }
    }

As I cannot rescue new revved filename and get it automatically replaced in my code snippet, I would like to avoid these files revving.
This use case would also suits for Modernizr.load() method.

Or is there any other way to achieve this?
Thanks in advance.

Grunt-Rev with data-src

Hi, I'm using some lazy/responsive loading scripts, such as https://github.com/BBC-News/Imager.js/ for tag creation at execution.

"Image" creation is done through <div> and data-src attribute. But rev does not alter those...

Before or after rev, I have :

<div style="width: 240px">
    <div class="delayed-image-load" data-src="http://placehold.it/{width}" data-alt="alternative text"></div>
</div>

Is there a way to configure rev to alter the HTML of my pages, modifying not only src but also data-src (or another data-* attribute).

After setting 'md5', 'utf8' and length:8 options, the hashed filename is not always same whilethe file content is always same.

The Gruntfile.js looks like this:

rev: {
    options: {
      encoding: 'utf8',
      algorithm: 'md5',
      length: 8
    },
    files: {
        src: [
          'assets/**/*'
        ]
    }
}

I got this on Sep 2:

-rw-rw-r-- 1 jiawzhang jiawzhang 166023 Sep 2 20:41 1ea21eb3.mdeditor.lib.min.css
-rw-rw-r-- 1 jiawzhang jiawzhang 421621 Sep 2 20:41 428a0363.mdeditor.lib.min.js
-rw-rw-r-- 1 jiawzhang jiawzhang 4516 Sep 2 20:41 be425dd2.mdeditor.min.css

And then I got this on Sep 3:

-rw-rw-r-- 1 jiawzhang jiawzhang 4516 Sep 3 09:40 1493dd1f.mdeditor.min.css
-rw-rw-r-- 1 jiawzhang jiawzhang 421621 Sep 3 09:40 3c69ae34.mdeditor.lib.min.js
-rw-rw-r-- 1 jiawzhang jiawzhang 166023 Sep 3 09:40 6343279f.mdeditor.lib.min.css

You could see the file size is same and I'm sure the content is same as well, but the hashed file name had been changed curiously.

Create one hash per "group" of assets (eg. for Retina/hidpi pairs)

There's a technique in the wild where you can use an in-browser HTML preprocessor to replace instances of "foo.png" with "[email protected]" depending on the client's display resolution. It's pretty awesome. It works like this (just imagine a string replacement on src rather than whatever's going on in that example).

Of course, asset hashing breaks this. There's no replacement I can perform on 3d15f.foo.png to end up with [email protected].

What's your opinion of a feature that would allow you to hash assets as a group? I would love it if grunt-rev would allow me to specify that files matching the pattern *.png and *@2x.png belong to a group of files that should all share the same hash.

Thoughts?

Postfix

@sleeper can you think of any reason why the format is 9e107d9d.default.txt instead of the more readable default.9e107d9d.txt? If not, we might consider switching.

Updating rev'ed file reference in JS files

I'm making web workers, and using grunt (yeoman setup) to copy and uglify and version my JS. The versioning works in the HTML index because it has the build comments. But the web workers are referenced inside a JS file. Is there a way to get these URL references in my JS to update with the rev'ed paths... or can I not use rev on the web workers because of this?

When building I get Error code: EISDIR during grunt-rev task

When I grunt build my angular app I grunt-rev has a problem dealing with the fonts. It creates the font folders just fine but does not place any fonts in them. Here is what it shows me.

Running "rev:dist" (rev) task
dist/scripts/scripts.js >> a3e641ec.scripts.js
dist/styles/main.css >> 970b8797.main.css
Warning: Unable to read "dist/fonts/Aller" file (Error code: EISDIR). Use --force to continue.

How to fix this?

Here is my Gruntfile.js

'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
  return connect.static(require('path').resolve(dir));
};

module.exports = function (grunt) {
  // load all grunt tasks
  require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

  // configurable paths
  var yeomanConfig = {
    app: 'app',
    dist: 'dist'
  };

  try {
    yeomanConfig.app = require('./component.json').appPath || yeomanConfig.app;
  } catch (e) {}

  grunt.initConfig({
    yeoman: yeomanConfig,
    watch: {
      coffee: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
        tasks: ['coffee:dist']
      },
      coffeeTest: {
        files: ['test/spec/{,*/}*.coffee'],
        tasks: ['coffee:test']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass']
      },
      livereload: {
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
          '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ],
        tasks: ['livereload']
      }
    },
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost'
      },
      livereload: {
        options: {
          middleware: function (connect) {
            return [
              lrSnippet,
              mountFolder(connect, '.tmp'),
              mountFolder(connect, yeomanConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          middleware: function (connect) {
            return [
              mountFolder(connect, '.tmp'),
              mountFolder(connect, 'test')
            ];
          }
        }
      }
    },
    open: {
      server: {
        url: 'http://localhost:<%= connect.options.port %>'
      }
    },
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: [
        'Gruntfile.js',
        '<%= yeoman.app %>/scripts/{,*/}*.js'
      ]
    },
    karma: {
      unit: {
        configFile: 'karma.conf.js',
        singleRun: true
      }
    },
    coffee: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/scripts',
          src: '{,*/}*.coffee',
          dest: '.tmp/scripts',
          ext: '.js'
        }]
      },
      test: {
        files: [{
          expand: true,
          cwd: 'test/spec',
          src: '{,*/}*.coffee',
          dest: '.tmp/spec',
          ext: '.js'
        }]
      }
    },
    compass: {
      options: {
        require: 'susy',
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/fonts',
        importPath: '<%= yeoman.app %>/components',
        relativeAssets: true
      },
      dist: {},
      server: {
        options: {
          debugInfo: true
        }
      }
    },
    concat: {
      dist: {
        files: {
          '<%= yeoman.dist %>/scripts/scripts.js': [
            '.tmp/scripts/{,*/}*.js',
            '<%= yeoman.app %>/scripts/{,*/}*.js'
          ]
        }
      }
    },
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>'
      }
    },
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        dirs: ['<%= yeoman.dist %>']
      }
    },
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },
    cssmin: {
      dist: {
        files: {
          '<%= yeoman.dist %>/styles/main.css': [
            '.tmp/styles/{,*/}*.css',
            '<%= yeoman.app %>/styles/{,*/}*.css'
          ]
        }
      }
    },
    htmlmin: {
      dist: {
        options: {
          /*removeCommentsFromCDATA: true,
          // https://github.com/yeoman/grunt-usemin/issues/44
          //collapseWhitespace: true,
          collapseBooleanAttributes: true,
          removeAttributeQuotes: true,
          removeRedundantAttributes: true,
          useShortDoctype: true,
          removeEmptyAttributes: true,
          removeOptionalTags: true*/
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>',
          src: ['*.html', 'views/*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },
    ngmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>/scripts',
          src: '*.js',
          dest: '<%= yeoman.dist %>/scripts'
        }]
      }
    },
    uglify: {
      dist: {
        files: {
          '<%= yeoman.dist %>/scripts/scripts.js': [
            '<%= yeoman.dist %>/scripts/scripts.js'
          ]
        }
      }
    },
    rev: {
      dist: {
        files: {
          src: [
            '<%= yeoman.dist %>/scripts/{,*/}*.js',
            '<%= yeoman.dist %>/styles/{,*/}*.css',
            '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
            '<%= yeoman.dist %>/fonts/*'
          ]
        }
      }
    },
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,txt}',
            '.htaccess',
            'components/**/*',
            'images/{,*/}*.{gif,webp}',
            'fonts/*'
          ]
        }]
      }
    }
  });

  grunt.renameTask('regarde', 'watch');

  grunt.registerTask('server', [
    'clean:server',
    'coffee:dist',
    'compass:server',
    'livereload-start',
    'connect:livereload',
    'open',
    'watch'
  ]);

  grunt.registerTask('test', [
    'clean:server',
    'coffee',
    'compass',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'jshint',
    'test',
    'coffee',
    'compass:dist',
    'useminPrepare',
    'imagemin',
    'cssmin',
    'htmlmin',
    'concat',
    'copy',
    'cdnify',
    'ngmin',
    'uglify',
    'rev',
    'usemin'
  ]);

  grunt.registerTask('default', ['build']);
};

The current npm package is old

Hi,

I am using grunt-rev in one of my projects and ran into the problem that the md5-method does not use utf-8 as encoding. I checked the latest version here on github and here the bug is already fixed.

But when I am using npm to install this package I still get an old version which does not work correctly.

It would be very nice if you could update the npm package on npmjs.org.

Regards, Sebastian

webfont.eot?#iefix doesn't get it's reference within CSS changed

So the revisions are added to all of my font files, and the references inside my CSS file are all changed.... except for the references with ?#iefix on the end (font code created by Compass v1 alpha)

The output:

@font-face {
    font-family: Titillium;
    src: url(/fonts/90b0c102.titillium-regular-webfont.eot);
    src: url(/fonts/titillium-regular-webfont.eot?#iefix) format('embedded-opentype'),
         url(/fonts/90b0c102.titillium-regular-webfont.eot) format('embedded-opentype'),
         url(/fonts/a7eeebd4.titillium-regular-webfont.woff) format('woff'),
         url(/fonts/293a2e2e.titillium-regular-webfont.ttf) format('truetype'),
         url(/fonts/686d139d.titillium-regular-webfont.svg) format('svg');
}

a conflict against ng-src

If I put ng-src after src in an <img> tag, the grunt-rev task will just ignore the src path but never rev the image loading.gif.

<img src="loading.gif" ng-src="{% xxx %}"/>

However codes below make grunt-dev work well

<img ng-src="{% xxx %}" src="loading.gif"/>

.

Error: Unable to read .js file (Error code: EISDIR).

Hi all,

It seems the grunt rev section in its current form can't distinguish between a directory ending in ".js" and a .js file. Grunt-rev (and subsequently usemin) will fail with

Warning: Unable to read "dist/public/bower_components/spin.js" file (Error code:
 EISDIR). Use --force to continue.

Aborted due to warnings.

In the below Gruntfile.js section, I fixed the problem by singling out each .js/ directory (spin.js is a project name and a .js file, for example) and excluding it. If you can tell me a more general way to do it by regex I would appreciate it.

    // Renames files for browser caching purposes
    rev: {
      dist: {
        files: {
            src: [
                '<%= yeoman.dist %>/public/**/*.js',
                '<%= yeoman.dist %>/public/**/*.css',
                '<%= yeoman.dist %>/public/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
                '<%= yeoman.dist %>/public/assets/fonts/{,*/}*.ttf',
                '!<%= yeoman.dist %>/public/bower_components/openlayers/tests/node.js',
                '!<%= yeoman.dist %>/public/bower_components/spin.js'
          ]
        }
      }
    },

Hash is wrong if the file is "big"

On "big" files (I am having this problem on a Js file just slightly bigger than 1MB) the calculated hash is definitely wrong.

With smaller files no problem though.
Is it possible that if a file is big enough only a chunk of the file is used?

On my file, for example, these are the results:

  • Using grunt-rev (options: {algorithm: md5, length: 32}): 9e494b97b63d7e67833df32376b4bb2b
  • Using cat scripts.min.js | openssl md5: 36cd285cd1271348628d496c3735b179

rev won't parse <img> tags

Hi.

I have several images in img tags (technically angular's ng-src)
and for some reason the rev task changes the file itself but won't update the html, causing a missing image.

It does work on css and js files though.

What am I missing?

Thank you.

Should specify usemin v.2.0

Spent 15min trying to figure out why usemin wouldn't work with grunt-rev.

Current version needed is under dev. So specify 2.0 on docs?

Thank you! Good work! Best lib I could find for this task

Can’t ignore a directory

Wanted to do something like this:

rev:
  dist:
    files:
      src: [
        "!<%= yeoman.dist %>/images/norev/*"
        "<%= yeoman.dist %>/images/**/*.{png,jpg,jpeg,gif,webp}"
      ]

But it doesn’t seem to be working. I want rev to ignore everything in the norev directory. I want to ignore those files because usemin fails when trying to process a javascript file optimised by r.js that contains HTML underscore templates in it.

Need for a summary file

In order to speed up work from, from example grunt-usemin (and also ease work ;)), it would be great to have grunt-rev outputting a summary of the actions it has performed (i.e. a map of source -> revved file).

Adding a manifest option

It would be nice to have a manifest option there to output a manifest.json file with all the mapping of source files without fingerprint to destination files with fingerprint. We use require.js with require.css and it's required to get the fingerprinted file name to load on-demand assets according to requirements.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.