23

I deploy my project by building source files with gulp right on the server. To prevent caching issues, the best practice could be adding a unique number to request url, see: Preventing browser caching on web application upgrades;

In npm repositories, I couldn't find a tool for automatically adding version number to request. I'm asking if someone has invented such tool before.

Possible implementation could be the following:

I have a file index.html in src/ folder, with following script tag

 <script src="js/app.js<!-- %nocache% -->"></script>

During build it is copied to dist/ folder, and comment is replaced by autoincrement number

 <script src="js/app.js?t=1234"></script>
Community
  • 1
  • 1
Dan
  • 55,715
  • 40
  • 116
  • 154
  • how are u replacing comment with the version number? – vini Nov 18 '16 at 11:03
  • @vini, Gulp has injection tasks that can search for the hardcoded `` in the index.html and then inject the desired string. This can be quite useful in combination with hashing the js files' version. (For each component, we include it's own javascript reference) ` ` This allows the client to cache as much JS as possible and only force re-load IF there is a hash change (file updated) – isaacdre Sep 29 '18 at 19:09

5 Answers5

27

You can use gulp-version-number for this. It can add version numbers to linked scripts, stylesheets, and other files in you HTML documents, by appending an argument to the URLs. For example:

<link rel="stylesheet" href="main.css">

becomes:

<link rel="stylesheet" href="main.css?v=474dee2efac59e2dcac7bf6c37365ed0">

You don't even have to specify a placeholder, like you showed in your example implementation. And it's configurable.

Example usage:

const $ = gulpLoadPlugins();
const versionConfig = {
  'value': '%MDS%',
  'append': {
    'key': 'v',
    'to': ['css', 'js'],
  },
};

gulp.task('html', () => {
  return gulp.src('src/**/*.html')
    .pipe($.htmlmin({collapseWhitespace: true}))
    .pipe($.versionNumber(versionConfig))
    .pipe(gulp.dest('docroot'));
});

NOTE:

I can no longer recommend this plugin. It is no longer maintained and there are some issues with it. I created a pull request some time ago, but there is no response from the author.

Serrano
  • 1,457
  • 20
  • 17
6

You can use the gulp-rev module. This will append a version number to the files, the version is a hash of the file content, so it will only change if the file changes.

You then output a manifest file containing the mapping between the file e.g. Scripts.js to Scripts-8wrefhn.js.

Then use a helper function when returning the page content to map the correct values.

I have used the above process. However there's another module gulp-rev-all which is an forked extension of gulp-rev which does a little more, e.g. automatic updating of file references in pages.

Documentation here:

Jack
  • 15,614
  • 19
  • 67
  • 92
4

I worked onto writing an regex, which in use along with gulp-replace works just fine.

Please find the code below. Following is a quick code for the image and css for views files codeigniter framework. But it should work fine for all the kinds of files given the source folder specified correctly.

You may customize the code as per your use.

You can call the tasks altogether, using gulp default or individual task at a time.

'use strict';

var gulp = require('gulp');
var replace = require('gulp-replace');

function makeid() {
  return (Math.random() + 1).toString(36).substring(7);
}



gulp.task('versioningCss', () => {
  return gulp.src('application/modules/**/views/*.php')
    .pipe(replace(/(.*)\.css\?(_v=.+&)*(.*)/g, '$1.css?_v='+makeid()+'&$3'))
    .pipe(replace(/(.*)\.css\"(.*)/g, '$1.css?_v='+makeid()+'"$2'))
    .pipe(replace(/(.*)\.css\'(.*)/g, '$1.css?_v='+makeid()+'\'$2'))
    .pipe(gulp.dest('application/modules'));
});

gulp.task('versioningJs', () => {
  return gulp.src('application/modules/**/views/*.php')
    .pipe(replace(/(.*)\.js\?(_v=.+&)*(.*)/g, '$1.js?_v='+makeid()+'&$3'))
    .pipe(replace(/(.*)\.js\"(.*)/g, '$1.js?_v='+makeid()+'"$2'))
    .pipe(replace(/(.*)\.js\'(.*)/g, '$1.js?_v='+makeid()+'\'$2'))
    .pipe(gulp.dest('application/modules'));
});

gulp.task('versioningImage', () => {
  return gulp.src('application/modules/**/views/*.php')
    .pipe(replace(/(.*)\.(png|jpg|jpeg|gif)\?(_v=.+&)*(.*)/g, '$1.$2?_v='+makeid()+'&$4'))
    .pipe(replace(/(.*)\.(png|jpg|jpeg|gif)\"(.*)/g, '$1.$2?_v='+makeid()+'"$3'))
    .pipe(replace(/(.*)\.(png|jpg|jpeg|gif)\'(.*)/g, '$1.$2?_v='+makeid()+'\'$3'));
});

gulp.task('default', [ 'versioningCss', 'versioningJs', 'versioningImage']);
Metro Smurf
  • 37,266
  • 20
  • 108
  • 140
Satys
  • 2,319
  • 1
  • 20
  • 26
  • 1
    Glad that it does, but I would suggest to be careful and do a test once before sending your code to production. This does not contain exhaustive regex! – Satys Aug 23 '19 at 10:22
3

It looks like you may have quite a few options.

https://www.npmjs.com/package/gulp-cachebust https://www.npmjs.com/package/gulp-buster

Hope this helps.

  • 2
    I looked at gulp-cachebust but it seems like this will actually append a hash to the filename then change the references to that file to match the newly hash-named version. This would work well if it the task is being run as a server side build script (after git). But if you are running this as a pre-deploy script to test then committing and uploading to your server, you will have every hashed version of the script in your git repo. Why would this cachebust use this method instead of OP's suggested method? – Brian McCall Apr 06 '16 at 19:10
-3

You can use

<script type="text/javascript" src="js/app.js?seq=<%=DateTime.Now.Ticks%>"></script>

or

<script type="text/javascript" src="js/app.js?seq=<%=DateTime.Now.ToString("yyyyMMddHHmm") %>"></script>

Pritam Jyoti Ray
  • 320
  • 1
  • 8
  • 12
  • 1
    that is unaware of the deploy process, and will always invalidate the cache every minute – zedling Jul 18 '18 at 07:42
  • 1
    This is not wise. This will invalidate all browser cache, and browser cache is very important for performance. – Paul Jan 09 '19 at 14:52