|
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' |