Skip to content
This repository has been archived by the owner on Oct 27, 2020. It is now read-only.

Commit

Permalink
feat(compare-func): pass cacheData to the compare() function
Browse files Browse the repository at this point in the history
Also added caching the source file.
  • Loading branch information
pat841 committed Jan 29, 2020
1 parent 4e0e3ae commit b5762ff
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports = {
| **`cacheKey`** | `{Function(options, request) -> {String}}` | `undefined` | Allows you to override default cache key generator |
| **`cacheDirectory`** | `{String}` | `findCacheDir({ name: 'cache-loader' }) or os.tmpdir()` | Provide a cache directory where cache items should be stored (used for default read/write implementation) |
| **`cacheIdentifier`** | `{String}` | `cache-loader:{version} {process.env.NODE_ENV}` | Provide an invalidation identifier which is used to generate the hashes. You can use it for extra dependencies of loaders (used for default read/write implementation) |
| **`compare`** | `{Function(stats, dep) -> {Boolean}}` | `undefined` | Allows you to override default comparison function between the cached dependency and the one is being read. Return `true` to use the cached resource |
| **`compare`** | `{Function(stats, dep, cacheData) -> {Boolean}}` | `undefined` | Allows you to override default comparison function between the cached dependency and the one is being read. Return `true` to use the cached resource |
| **`precision`** | `{Number}` | `0` | Round `mtime` by this number of milliseconds both for `stats` and `dep` before passing those params to the comparing function |
| **`read`** | `{Function(cacheKey, callback) -> {void}}` | `undefined` | Allows you to override default read cache data from file |
| **`readOnly`** | `{Boolean}` | `false` | Allows you to override default value and make the cache read only (useful for some environments where you don't want the cache to be updated, only read from it) |
Expand Down
15 changes: 8 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function roundMs(mtime, precision) {
// right before writing. Every other internal steps with the paths
// should be accomplish over absolute paths. Otherwise we have the risk
// to break watchpack -> chokidar watch logic over webpack@4 --watch
function loader(...args) {
function loader(source, ...args) {
const options = Object.assign({}, defaults, getOptions(this));

validateOptions(schema, options, {
Expand All @@ -70,7 +70,7 @@ function loader(...args) {
// In case we are under a readOnly mode on cache-loader
// we don't want to write or update any cache file
if (readOnly) {
this.callback(null, ...args);
this.callback(null, source, ...args);
return;
}

Expand Down Expand Up @@ -117,11 +117,11 @@ function loader(...args) {
],
(err, taskResults) => {
if (err) {
callback(null, ...args);
callback(null, source, ...args);
return;
}
if (!cache) {
callback(null, ...args);
callback(null, source, ...args);
return;
}
const [deps, contextDeps] = taskResults;
Expand All @@ -132,13 +132,14 @@ function loader(...args) {
options.cacheContext,
data.remainingRequest
),
source,
dependencies: deps,
contextDependencies: contextDeps,
result: args,
result: [source, ...args],
},
() => {
// ignore errors here
callback(null, ...args);
callback(null, source, ...args);
}
);
}
Expand Down Expand Up @@ -228,7 +229,7 @@ function pitch(remainingRequest, prevRequest, dataInput) {

// If the compare function returns false
// we not read from cache
if (compareFn(compStats, compDep) !== true) {
if (compareFn(compStats, compDep, cacheData) !== true) {
eachCallback(true);
return;
}
Expand Down
12 changes: 12 additions & 0 deletions test/__snapshots__/cacheContext-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ exports[`cacheContext option should generate relative paths to the project root:
"[
{
\\"remainingRequest\\": \\"test/fixtures/basic/file_1.js\\",
\\"source\\": {
\\"type\\": \\"Buffer\\",
\\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KY29uc29sZS5sb2coJ2ZpbGVfMScpOwo=\\"
},
\\"dependencies\\": [
{
\\"path\\": \\"test/fixtures/basic/file_1.js\\",
Expand All @@ -30,6 +34,10 @@ exports[`cacheContext option should generate relative paths to the project root:
},
{
\\"remainingRequest\\": \\"test/fixtures/basic/file_2.js\\",
\\"source\\": {
\\"type\\": \\"Buffer\\",
\\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KY29uc29sZS5sb2coJ2ZpbGVfMicpOwo=\\"
},
\\"dependencies\\": [
{
\\"path\\": \\"test/fixtures/basic/file_2.js\\",
Expand All @@ -50,6 +58,10 @@ exports[`cacheContext option should generate relative paths to the project root:
},
{
\\"remainingRequest\\": \\"test/fixtures/basic/index.js\\",
\\"source\\": {
\\"type\\": \\"Buffer\\",
\\"data\\": \\"base64:LyogZXNsaW50LWRpc2FibGUgKi8KcmVxdWlyZSgnLi9maWxlXzEuanMnKTsKcmVxdWlyZSgnLi9maWxlXzIuanMnKTsKCmNvbnNvbGUubG9nKCdiYXNpY19lbnRyeScpOwo=\\"
},
\\"dependencies\\": [
{
\\"path\\": \\"test/fixtures/basic/index.js\\",
Expand Down
8 changes: 4 additions & 4 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validate options error (pitch) 1`] = `
"Invalid options object. Cache Loader (Pitch) has been initialised using an options object that does not match the API schema.
"Invalid options object. Cache Loader (Pitch) has been initialized using an options object that does not match the API schema.
- options.cacheIdentifier should be a string.
-> Provide an invalidation identifier which is used to generate the hashes. You can use it for extra dependencies of loaders (used for default read/write implementation)."
`;

exports[`validate options error 1`] = `
"Invalid options object. Cache Loader has been initialised using an options object that does not match the API schema.
"Invalid options object. Cache Loader has been initialized using an options object that does not match the API schema.
- options.cacheIdentifier should be a string.
-> Provide an invalidation identifier which is used to generate the hashes. You can use it for extra dependencies of loaders (used for default read/write implementation)."
`;

exports[`validate options unknown (pitch) 1`] = `
"Invalid options object. Cache Loader (Pitch) has been initialised using an options object that does not match the API schema.
"Invalid options object. Cache Loader (Pitch) has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { cacheContext?, cacheKey?, cacheIdentifier?, cacheDirectory?, compare?, precision?, read?, readOnly?, write? }"
`;
exports[`validate options unknown 1`] = `
"Invalid options object. Cache Loader has been initialised using an options object that does not match the API schema.
"Invalid options object. Cache Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { cacheContext?, cacheKey?, cacheIdentifier?, cacheDirectory?, compare?, precision?, read?, readOnly?, write? }"
`;
20 changes: 14 additions & 6 deletions test/compare-option.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const mockWebpackConfig = {
loader: {
options: {
cacheDirectory: mockRandomTmpDir,
compare: (stats, dep) => {
mockCacheLoaderCompareFn(stats, dep);
compare: (stats, dep, cacheData) => {
mockCacheLoaderCompareFn(stats, dep, cacheData);
return true;
},
},
Expand All @@ -26,8 +26,8 @@ const mockRelativeWebpackConfig = {
options: {
cacheContext: path.resolve('./'),
cacheDirectory: mockRandomTmpDir,
compare: (stats, dep) => {
mockCacheLoaderCompareOnRelativeFn(stats, dep);
compare: (stats, dep, cacheData) => {
mockCacheLoaderCompareOnRelativeFn(stats, dep, cacheData);
return true;
},
},
Expand All @@ -50,12 +50,12 @@ describe('compare option', () => {
expect(mockCacheLoaderCompareFn).toHaveBeenCalled();
});

it('should call compare function with 2 args', async () => {
it('should call compare function with 3 args', async () => {
const testId = './basic/index.js';
await webpack(testId, mockWebpackConfig);
await webpack(testId, mockWebpackConfig);
expect(mockCacheLoaderCompareFn).toHaveBeenCalled();
expect(mockCacheLoaderCompareFn.mock.calls[0].length).toBe(2);
expect(mockCacheLoaderCompareFn.mock.calls[0].length).toBe(3);
});

it('should call compare function with correct args', async () => {
Expand All @@ -68,11 +68,19 @@ describe('compare option', () => {
const stats = mockCacheLoaderCompareFn.mock.calls[0][0];
// eslint-disable-next-line
const dep = mockCacheLoaderCompareFn.mock.calls[0][1];
// eslint-disable-next-line
const cacheData = mockCacheLoaderCompareFn.mock.calls[0][2];
expect(stats).toBeDefined();
expect(stats instanceof fs.Stats);
expect(dep).toBeDefined();
expect(dep.mtime).toBeDefined();
expect(dep.path).toBeDefined();
expect(cacheData).toBeDefined();
expect(cacheData.remainingRequest).toBeDefined();
expect(cacheData.source).toBeDefined();
expect(cacheData.dependencies).toBeDefined();
expect(cacheData.contextDependencies).toBeDefined();
expect(cacheData.result).toBeDefined();
});

it('should call compare with contextualized dep', async () => {
Expand Down

0 comments on commit b5762ff

Please sign in to comment.