Skip to content

Commit

Permalink
Merge pull request #179 from mikrostew/asset-cache-key
Browse files Browse the repository at this point in the history
Generate cache keys for sources and collections
  • Loading branch information
stefanpenner committed Mar 16, 2018
2 parents a729aca + d79d21d commit c1db1ec
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/assets/Assets.js
Expand Up @@ -14,6 +14,8 @@ function Assets(eyeglass, sass) {
this.eyeglass = eyeglass;
// create a master collection
this.collection = new AssetsCollection();
// and keep a list of module collections
this.moduleCollections = [];

// Expose these temporarily for back-compat reasons
function deprecate(method) {
Expand Down Expand Up @@ -57,6 +59,7 @@ Assets.prototype.addSource = function(src, opts) {
*/
Assets.prototype.export = function(src, opts) {
var assets = new AssetsCollection();
this.moduleCollections.push(assets);
return assets.addSource(src, opts);
};

Expand Down
10 changes: 10 additions & 0 deletions lib/assets/AssetsCollection.js
Expand Up @@ -52,4 +52,14 @@ AssetsCollection.prototype.asAssetImport = function (name) {
}, '@import "eyeglass/assets";\n');
};

/**
* Build a string suitable for caching an instance of this
* @returns {String} the cache key
*/
AssetsCollection.prototype.cacheKey = function(name) {
return this.sources.map(function(source) {
return source.cacheKey(name);
}).sort().join(":");
};

module.exports = AssetsCollection;
31 changes: 31 additions & 0 deletions lib/assets/AssetsSource.js
Expand Up @@ -6,6 +6,7 @@ var path = require("path");
var merge = require("lodash.merge");
var URI = require("../util/URI");
var fileUtils = require("../util/files");
var stringify = require("json-stable-stringify");

/* class AssetsSource
*
Expand Down Expand Up @@ -82,4 +83,34 @@ AssetsSource.prototype.toString = function() {
return this.srcPath + "/" + this.pattern;
};

// don't include these globOpts in the cacheKey
function skipSomeKeys(key, value) {
// these are set to this.srcPath, which is already included in the cacheKey
if (key === "cwd" || key === "root") {
return undefined;
}
// these are added inside glob and always set to true, which happens after this string
// is created when glob.sync() is run in #getAssets()
// (see #setopts() in glob/common.js)
if (key === "nonegate" || key === "nocomment") {
return undefined;
}
return value;
}

/**
* Build a string suitable for caching an instance of this
* @returns {String} the cache key
*/
AssetsSource.prototype.cacheKey = function(namespace) {
return "[" +
"httpPrefix=" + (this.httpPrefix ? this.httpPrefix : "") +
";name=" + (this.name ? this.name : (namespace ? namespace : "")) +
";srcPath=" + this.srcPath +
";pattern=" + this.pattern +
// json-stable-stringify orders keys when stringifying (JSON.stringify does not)
";opts=" + stringify(this.globOpts, {replacer: skipSomeKeys}) +
"]";
};

module.exports = AssetsSource;
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -34,6 +34,7 @@
"ensure-symlink": "^1.0.0",
"fs-extra": "^0.30.0",
"glob": "^7.1.0",
"json-stable-stringify": "^1.0.1",
"lodash.includes": "^4.3.0",
"lodash.merge": "^4.6.0",
"node-sass": "^4.0.0 || ^3.10.1",
Expand Down
158 changes: 158 additions & 0 deletions test/test_assets.js
Expand Up @@ -9,6 +9,7 @@ var glob = require("glob");

var Eyeglass = require("../lib");
var AssetsSource = require("../lib/assets/AssetsSource");
var AssetsCollection = require("../lib/assets/AssetsCollection");

function escapeBackslash(str) {
return str.replace(/\\/g, "\\\\");
Expand Down Expand Up @@ -874,6 +875,26 @@ describe("assets", function () {
testutils.assertCompiles(eg, expected, done);
});

it("should keep track of module collections", function() {
var rootDir = testutils.fixtureDirectory("app_assets");

var egMod = new Eyeglass({
// file containing '@import "mod-one/assets"'
file: path.join(rootDir, "sass", "uses_mod_1.scss"),
eyeglass: {
root: rootDir,
installWithSymlinks: installWithSymlinks,
engines: {
sass: sass
}
}
});

assert.ok(egMod.assets.moduleCollections !== undefined);
assert.ok(Array.isArray(egMod.assets.moduleCollections));
assert.equal(egMod.assets.moduleCollections.length, 1);
});

describe("path separator normalization", function() {
var originalEnv = process.env.EYEGLASS_NORMALIZE_PATHS;
var merge = require("lodash.merge");
Expand Down Expand Up @@ -983,6 +1004,143 @@ describe("assets", function () {
});
});
});

describe("cache keys", function() {
var rootDir = testutils.fixtureDirectory("app_assets");
var rootDir2 = testutils.fixtureDirectory("app_assets_odd_names");

it("Assets.cacheKey includes httpPrefix", function() {
var source1 = new AssetsSource(rootDir, {
httpPrefix: "foo",
});
var source2 = new AssetsSource(rootDir, {
httpPrefix: "foo",
});
var source3 = new AssetsSource(rootDir, {
httpPrefix: "bar",
});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.notEqual(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey includes name", function() {
var source1 = new AssetsSource(rootDir, {
name: "foo",
});
var source2 = new AssetsSource(rootDir, {
name: "foo",
});
var source3 = new AssetsSource(rootDir, {
name: "bar",
});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.notEqual(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey includes namespace", function() {
var source1 = new AssetsSource(rootDir, {});
var source2 = new AssetsSource(rootDir, {});
assert.equal(source1.cacheKey("foo"), source2.cacheKey("foo"));
assert.notEqual(source1.cacheKey("foo"), source2.cacheKey("bar"));
});

it("Assets.cacheKey includes srcPath", function() {
var source1 = new AssetsSource(rootDir, {});
var source2 = new AssetsSource(rootDir, {});
var source3 = new AssetsSource(rootDir2, {});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.notEqual(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey includes pattern", function() {
var source1 = new AssetsSource(rootDir, {
pattern: "images/**/*",
});
var source2 = new AssetsSource(rootDir, {
pattern: "images/**/*",
});
var source3 = new AssetsSource(rootDir, {
pattern: "images/**/*.jpg",
});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.notEqual(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey includes globOpts", function() {
var source1 = new AssetsSource(rootDir, {});
var source2 = new AssetsSource(rootDir, {});
var source3 = new AssetsSource(rootDir, {
globOpts: {
dot: true
}
});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.notEqual(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey ignores globOpts that are overridden", function() {
var source1 = new AssetsSource(rootDir, {});
var source2 = new AssetsSource(rootDir, {
globOpts: {
nonegate: false
}
});
var source3 = new AssetsSource(rootDir, {
globOpts: {
nonegate: true
}
});
assert.equal(source1.cacheKey(), source2.cacheKey());
assert.equal(source1.cacheKey(), source3.cacheKey());
});

it("Assets.cacheKey globOpts order doesn't matter", function() {
var source1 = new AssetsSource(rootDir, {
globOpts: {
dot: true,
nonull: true
}
});
var source2 = new AssetsSource(rootDir, {
globOpts: {
nonull: true,
dot: true
}
});
assert.equal(source1.cacheKey(), source2.cacheKey());
});

it("AssetsCollection.cacheKey includes collection sources", function() {
var collection1 = new AssetsCollection();
var collection2 = new AssetsCollection();
var collection3 = new AssetsCollection();
var collection4 = new AssetsCollection();

collection1.addSource(rootDir);
collection2.addSource(rootDir);
collection3.addSource(rootDir2);
collection4.addSource(rootDir);
collection4.addSource(rootDir2);

assert.equal(collection1.cacheKey(), collection2.cacheKey());
assert.notEqual(collection1.cacheKey(), collection3.cacheKey());
assert.notEqual(collection1.cacheKey(), collection4.cacheKey());
});

it("AssetsCollection.cacheKey source order doesn't matter", function() {
var collection1 = new AssetsCollection();
var collection2 = new AssetsCollection();

collection1.addSource(rootDir);
collection1.addSource(rootDir2);

collection2.addSource(rootDir2);
collection2.addSource(rootDir);

assert.equal(collection1.cacheKey(), collection2.cacheKey());
});

});
});
});
});

0 comments on commit c1db1ec

Please sign in to comment.