Merge pull request #25 from mozilla/issue_24_hash_in_url

Allow development resources to contain fragment identifiers.
This commit is contained in:
Austin King 2013-01-23 13:41:52 -08:00
Родитель ada022e23c fd49baf2a7
Коммит ea11e6e6ba
2 изменённых файлов: 45 добавлений и 18 удалений

Просмотреть файл

@ -120,20 +120,27 @@ exports.setup = function (assets, options) {
* foo.js -> a998d8e98f/foo.js * foo.js -> a998d8e98f/foo.js
* http://example.com/foo.js -> http://example.com/foo.js * http://example.com/foo.js -> http://example.com/foo.js
*/ */
var hashify = function (filename, hash) { var hashify = function (resource, hash) {
if (typeof filename !== 'string') if (typeof resource !== 'string')
throw "cachify ERROR, expected string for filename, got " + filename; throw "cachify ERROR, expected string for resource, got " + resource;
if (filename.indexOf('://') !== -1) { if (resource.indexOf('://') !== -1) {
return filename; return resource;
} }
if (! hash && opts.global_hash) { if (! hash && opts.global_hash) {
hash = opts.global_hash; hash = opts.global_hash;
} }
if (opts.production !== true && if (opts.production !== true &&
opts.debug === false) { opts.debug === false) {
return filename; return resource;
} }
// fragment identifiers on URLs are never sent to the server and they
// should not exist on the filename. When looking up the resource on
// disk, do so without the fragment identifier.
var filename = resource.replace(/#.*$/, '');
if (hash) { if (hash) {
// No-op, specifing a hash skips all this craziness // No-op, specifing a hash skips all this craziness
} else if (_cache[filename] && _cache[filename].hash) { } else if (_cache[filename] && _cache[filename].hash) {
@ -144,22 +151,24 @@ var hashify = function (filename, hash) {
var md5 = crypto.createHash('md5'); var md5 = crypto.createHash('md5');
try { try {
var data = fs.readFileSync(path.join(opts.root, filename)); var data = fs.readFileSync(path.join(opts.root, filename));
md5.update(data); md5.update(data);
// Expensive, maintain in-memory cache // Expensive, maintain in-memory cache
if (! _cache[filename]) _cache[filename] = {exists: true}; if (! _cache[filename]) _cache[filename] = {exists: true};
hash = _cache[filename].hash = md5.digest('hex').slice(0, 10); hash = _cache[filename].hash = md5.digest('hex').slice(0, 10);
} catch (e) { } catch (e) {
// Not intersting to cache, programmer error? // Not intersting to cache, programmer error?
exports.uncached_resources.push(resource);
console.error('Cachify bailing on hash... no such file ' + filename ); console.error('Cachify bailing on hash... no such file ' + filename );
console.error(e); console.error(e);
return filename; return resource;
} }
} }
if (opts.prefix.indexOf('://') === -1 && if (opts.prefix.indexOf('://') === -1 &&
filename[0] === '/') { resource[0] === '/') {
return format('/%s%s%s', opts.prefix, hash, filename); return format('/%s%s%s', opts.prefix, hash, resource);
} else { } else {
return format('%s%s%s%s', opts.prefix, hash, filename[0] === '/' ? '' : '/', filename); return format('%s%s%s%s', opts.prefix, hash, resource[0] === '/' ? '' : '/', resource);
} }
}; };
@ -207,3 +216,5 @@ var no_url = function (prefix) {
var escape_regex = function (str) { var escape_regex = function (str) {
return str.replace('/', '\/'); return str.replace('/', '\/');
}; };
exports.uncached_resources = [];

Просмотреть файл

@ -15,8 +15,10 @@ var resetConfig = function () {
var make_assets = function () { return { var make_assets = function () { return {
"/js/main.min.js": [ "/js/main.min.js": [
"/js/lib/jquery.js", "/js/lib/jquery-foomatic.js", "/js/lib/jquery.js",
"/js/main.js" "/js/lib/jquery-foomatic.js",
"/js/main.js",
"/js/font-loader.js#with_fragment_id"
]}; }; ]}; };
exports.setup = nodeunit.testCase({ exports.setup = nodeunit.testCase({
@ -39,6 +41,9 @@ exports.setup = nodeunit.testCase({
function (err) { function (err) {
fs.writeFile('/tmp/js/main.js', "", "utf8", this); fs.writeFile('/tmp/js/main.js', "", "utf8", this);
}, },
function (err) {
fs.writeFile('/tmp/js/font-loader.js', "", "utf8", this);
},
function (err) { function (err) {
cb(); cb();
} }
@ -48,13 +53,16 @@ exports.setup = nodeunit.testCase({
step( step(
fs.unlink('/tmp/js/main.js', this), fs.unlink('/tmp/js/main.js', this),
function (err) { function (err) {
fs.unlink('/tmp/js/lib/jquery-foomatic.js', this); fs.unlink('/tmp/js/main.min.js', this);
}, },
function (err) { function (err) {
fs.unlink('/tmp/js/lib/jquery.js', this); fs.unlink('/tmp/js/lib/jquery.js', this);
}, },
function (err) { function (err) {
fs.unlink('/tmp/js/main.min.js', this); fs.unlink('/tmp/js/lib/jquery-foomatic.js', this);
},
function (err) {
fs.unlink('/tmp/js/font-loader.js', this);
}, },
function (err) { function (err) {
fs.rmdir('/tmp/js/lib', this); fs.rmdir('/tmp/js/lib', this);
@ -76,10 +84,12 @@ exports.setup = nodeunit.testCase({
files, files,
links, links,
mddlwr; mddlwr;
mddlwr = cachify.setup(assets, { mddlwr = cachify.setup(assets, {
root: '/tmp', root: '/tmp',
production: false, production: false,
debug: true}); debug: true});
links = cachify.cachify_js("/js/main.min.js").split('\n'); links = cachify.cachify_js("/js/main.min.js").split('\n');
test.equal(links[0], '<script src="/d41d8cd98f/js/lib/jquery.js"></script>', test.equal(links[0], '<script src="/d41d8cd98f/js/lib/jquery.js"></script>',
"debug option puts hash in all urls"); "debug option puts hash in all urls");
@ -112,11 +122,17 @@ exports.setup = nodeunit.testCase({
production: false production: false
}); });
var links = cachify.cachify_js("/js/main.min.js").split('\n'); var links = cachify.cachify_js("/js/main.min.js").split('\n');
test.ok(links.length, "Multiple script tags"); test.equal(links.length, assets["/js/main.min.js"].length,
"All script tags created");
test.equal(links[0], '<script src="/js/lib/jquery.js"></script>', test.equal(links[0], '<script src="/js/lib/jquery.js"></script>',
"No hashes in all urls during development"); "No hashes in all urls during development");
test.equal(links[3], '<script src="/js/font-loader.js#with_fragment_id"></script>',
"Fragment identifier in URL is preserved");
test.equal(cachify.uncached_resources.indexOf("/js/font-loader.js#with_fragment_id"), -1,
"Fragment identifiers are never sent to server, search on disk for resource by removing fragment id");
var files = cachify.cachify("/js/main.min.js").split('\n'); var files = cachify.cachify("/js/main.min.js").split('\n');
test.ok(files.length, "Multiple script tags"); test.equal(files.length, assets["/js/main.min.js"].length,
"All urls created");
test.equal(files[0], '/js/lib/jquery.js', test.equal(files[0], '/js/lib/jquery.js',
"No hashes in all urls during development"); "No hashes in all urls during development");
mddlwr(req, resp, function () { mddlwr(req, resp, function () {