Skip to content

Instantly share code, notes, and snippets.

@ovcharik
Last active May 4, 2016 20:18
Show Gist options
  • Save ovcharik/4b230e103b584c864ddb038ec6c2b7ea to your computer and use it in GitHub Desktop.
Save ovcharik/4b230e103b584c864ddb038ec6c2b7ea to your computer and use it in GitHub Desktop.
Persistent cache for grunt browserify

About

Persistent cache for grunt-browserify.

Usage

grunt.initConfig
  # ...
  
  browserify:
    dev:
      # ...
      configure: (browserifyInstance) ->
        pathToCacheFile = "/path/to/browserify-cache.json"
        gbpc = require('/path/to/grunt-browserify-persistent-cache.coffee')
        gbpc(pathToCacheFile, browserifyInstance)
fs = require 'fs'
# Structure of cache file:
#
# {
# "path/to/output/file/1": {
# "cache": {
# "path/to/source/file/1": {
# "size" : <file size>,
# "mtime": <file modified time in ms>,
# "data" : <file cache object from "browserify">
# }[, <other source files...>]
# },
# "packageCache": { <such as "cache" property> }
# }[, <other output files...>]
# }
# To invalidate the cache entry used by the file size and file modification time
getFileStat = (file) ->
try
stat = fs.statSync(file)
stat.mtime = stat.mtime.getTime()
catch e
stat = { size: 0, mtime: 0 }
return {
size : stat.size
mtime: stat.mtime
}
# Restore "browserify" cache from file of cache.
# Some records of cache can become outdated at the time of recovery.
# They will not be restored.
restoreFromCache = (from, to, browserify) ->
for file, value of from
s = getFileStat(file)
# Validate record of cache
if s.size == value.size && s.mtime == value.mtime
to[file] = value.data
# Listening file hook for watchify, when it loaded from cache
browserify.emit 'file', file
return
# Transform cache of "browserify" into format for the cache file.
saveToCache = (data) ->
result = {}
for file, value of data
fileStat = getFileStat(file)
result[file] =
data : value
size : fileStat.size,
mtime: fileStat.mtime
return result
readCacheFile = (filePath) ->
try
cache = JSON.parse(fs.readFileSync(filePath))
catch e
cache = {}
return cache
module.exports = (cacheFilePath, browserify) ->
cache = readCacheFile(cacheFilePath)
# Only the first entry in the "browserify", because "grunt-browserify" creates
# "browserify" instance for each output file.
# This will not work in a general case for "browserify",
# but in this case works without problems.
entry = browserify._options.entries[0]
cache[entry] ?= { cache: {}, packageCache: {} }
restoreFromCache cache[entry].cache, browserify._options.cache, browserify
restoreFromCache cache[entry].packageCache, browserify._options.packageCache, browserify
# Updating cache file for every build of "browserify"
browserify.on 'bundle', (bundle) ->
bundle.on 'end', ->
# Reading actual cache file is necessary to prevent wrong merging,
# when using multiple output files.
cache = readCacheFile(cacheFilePath)
cache[entry] =
cache : saveToCache(browserify._options.cache)
packageCache: saveToCache(browserify._options.packageCache)
fs.writeFileSync cacheFilePath, JSON.stringify(cache), 'utf8'
var fs, getFileStat, readCacheFile, restoreFromCache, saveToCache;
fs = require('fs');
getFileStat = function(file) {
var e, error, stat;
try {
stat = fs.statSync(file);
stat.mtime = stat.mtime.getTime();
} catch (error) {
e = error;
stat = {
size: 0,
mtime: 0
};
}
return {
size: stat.size,
mtime: stat.mtime
};
};
restoreFromCache = function(from, to, browserify) {
var file, s, value;
for (file in from) {
value = from[file];
s = getFileStat(file);
if (s.size === value.size && s.mtime === value.mtime) {
to[file] = value.data;
browserify.emit('file', file);
}
}
};
saveToCache = function(data) {
var file, fileStat, result, value;
result = {};
for (file in data) {
value = data[file];
fileStat = getFileStat(file);
result[file] = {
data: value,
size: fileStat.size,
mtime: fileStat.mtime
};
}
return result;
};
readCacheFile = function(filePath) {
var cache, e, error;
try {
cache = JSON.parse(fs.readFileSync(filePath));
} catch (error) {
e = error;
cache = {};
}
return cache;
};
module.exports = function(cacheFilePath, browserify) {
var cache, entry;
cache = readCacheFile(cacheFilePath);
entry = browserify._options.entries[0];
if (cache[entry] == null) {
cache[entry] = {
cache: {},
packageCache: {}
};
}
restoreFromCache(cache[entry].cache, browserify._options.cache, browserify);
restoreFromCache(cache[entry].packageCache, browserify._options.packageCache, browserify);
return browserify.on('bundle', function(bundle) {
return bundle.on('end', function() {
cache = readCacheFile(cacheFilePath);
cache[entry] = {
cache: saveToCache(browserify._options.cache),
packageCache: saveToCache(browserify._options.packageCache)
};
return fs.writeFileSync(cacheFilePath, JSON.stringify(cache), 'utf8');
});
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment