Skip to content

Instantly share code, notes, and snippets.

@sixlettervariables
Created August 6, 2014 19:19
Show Gist options
  • Save sixlettervariables/0d38509bce76382e00bd to your computer and use it in GitHub Desktop.
Save sixlettervariables/0d38509bce76382e00bd to your computer and use it in GitHub Desktop.
DustJS Helper: CDN URL Rewriting
/// Copyright (c) 2014 Christopher A. Watford
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
var url = require('url'),
path = require('path'),
crypto = require('crypto'),
ReadStream = require('fs').ReadStream,
_ = require('lodash');
var kPublicDirectory = '/public/';
var kProductionDirectory = './.build';
var kCdnHost = 'cdn.yourdomain.com';
var cache = {},
md5 = {};
/** Adds the CDN related helpers to DustJS.
*
* @param {Object} [dust] A reference to the DustJS engine being configured.
*/
module.exports = function AddHelpers(dust, options) {
// See krakenjs/adaro/pull/22
options = _.extend({
"env": process.env.NODE_ENV,
"public": kPublicDirectory,
"build": kProductionDirectory,
"cdn": kCdnHost
}, options || {});
var IS_DEV = options.env === 'development';
/** Rewires a resource to use a CDN host. In production it applies cache-busting as well (?v={MD5SUM}).
*
* @param {Object} [chunk] The current DustJS template chunk.
* @param {Object} [ctx] The current DustJS rendering context.
* @param {Array} [bodies] Any body text contained within the template (UNUSED).
* @param {Object} [params] The parameters passed to the helper.
* @param {String} [params.src] The source URL to rewire to use a CDN host.
* @param {String} [params.type] The extension of the file if not given (useful for RequireJS setups).
*/
function Helper_LoadFromCdn(chunk, ctx, bodies, params) {
var src = dust.helpers.tap(params.src, chunk, ctx);
var type = dust.helpers.tap(params.type, chunk, ctx);
if (IS_DEV) {
return chunk.write(src);
}
else {
if (!_.has(cache, src)) {
console.log('uncached CDN reference');
cache[src] = src; // fallthrough for non-cached URL's
var parsed = url.parse(src);
if (parsed.pathname.indexOf(kPublicDirectory) === 0) {
parsed.host = kCdnHost;
if (!IS_DEV) {
if (!_.has(md5, src)) {
return chunk.map(function (chunk) {
var md5sum = crypto.createHash('md5');
var fn = parsed.pathname.substr(kPublicDirectory.length);
if (!path.extname(fn) && type) {
fn += '.' + type;
}
var stream = ReadStream(path.join(kProductionDirectory, fn));
stream.on('data', function (data) {
md5sum.update(data);
});
stream.on('error', function (error) {
console.error(error);
chunk.setError(error);
return chunk.end();
});
stream.on('end', function () {
parsed.search = '?v=' + md5sum.digest('hex');
cache[src] = url.format(parsed);
chunk.write(cache[src]);
return chunk.end();
});
});
}
else {
parsed.search = '?v=' + md5[src];
cache[src] = url.format(parsed);
}
}
}
}
return chunk.write(cache[src]);
}
}
dust.helpers.cdn = Helper_LoadFromCdn;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment