mirror of https://github.com/status-im/metro.git
Replace the ETag header by the Last-Modified to improve performance
Reviewed By: mjesun Differential Revision: D5823545 fbshipit-source-id: 57eac5548e626eeed05f9b454e3f54b114193eb0
This commit is contained in:
parent
b64a07e38b
commit
0a1e79a820
|
@ -29,6 +29,7 @@ class DeltaPatcher {
|
||||||
};
|
};
|
||||||
_initialized = false;
|
_initialized = false;
|
||||||
_lastNumModifiedFiles = 0;
|
_lastNumModifiedFiles = 0;
|
||||||
|
_lastModifiedDate = new Date();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a Delta Bundle to the current bundle.
|
* Applies a Delta Bundle to the current bundle.
|
||||||
|
@ -55,6 +56,10 @@ class DeltaPatcher {
|
||||||
this._lastNumModifiedFiles =
|
this._lastNumModifiedFiles =
|
||||||
deltaBundle.pre.size + deltaBundle.post.size + deltaBundle.delta.size;
|
deltaBundle.pre.size + deltaBundle.post.size + deltaBundle.delta.size;
|
||||||
|
|
||||||
|
if (this._lastNumModifiedFiles > 0) {
|
||||||
|
this._lastModifiedDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
this._patchMap(this._lastBundle.pre, deltaBundle.pre);
|
this._patchMap(this._lastBundle.pre, deltaBundle.pre);
|
||||||
this._patchMap(this._lastBundle.post, deltaBundle.post);
|
this._patchMap(this._lastBundle.post, deltaBundle.post);
|
||||||
this._patchMap(this._lastBundle.modules, deltaBundle.delta);
|
this._patchMap(this._lastBundle.modules, deltaBundle.delta);
|
||||||
|
@ -72,6 +77,10 @@ class DeltaPatcher {
|
||||||
return this._lastNumModifiedFiles;
|
return this._lastNumModifiedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLastModifiedDate(): Date {
|
||||||
|
return this._lastModifiedDate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the current delta bundle to a standard string bundle, ready to
|
* Converts the current delta bundle to a standard string bundle, ready to
|
||||||
* be interpreted by any JS VM.
|
* be interpreted by any JS VM.
|
||||||
|
|
|
@ -21,6 +21,7 @@ const DeltaTransformer = require('../DeltaTransformer');
|
||||||
const DeltaBundler = require('../');
|
const DeltaBundler = require('../');
|
||||||
|
|
||||||
describe('DeltaBundler', () => {
|
describe('DeltaBundler', () => {
|
||||||
|
const OriginalDate = global.Date;
|
||||||
let deltaBundler;
|
let deltaBundler;
|
||||||
let bundler;
|
let bundler;
|
||||||
const initialTransformerResponse = {
|
const initialTransformerResponse = {
|
||||||
|
@ -31,6 +32,10 @@ describe('DeltaBundler', () => {
|
||||||
reset: true,
|
reset: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function setCurrentTime(time: number) {
|
||||||
|
global.Date = jest.fn(() => new OriginalDate(time));
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
DeltaTransformer.prototype.getDelta = jest
|
DeltaTransformer.prototype.getDelta = jest
|
||||||
.fn()
|
.fn()
|
||||||
|
@ -42,6 +47,8 @@ describe('DeltaBundler', () => {
|
||||||
|
|
||||||
bundler = new Bundler();
|
bundler = new Bundler();
|
||||||
deltaBundler = new DeltaBundler(bundler, {});
|
deltaBundler = new DeltaBundler(bundler, {});
|
||||||
|
|
||||||
|
setCurrentTime(1482363367000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new transformer to build the initial bundle', async () => {
|
it('should create a new transformer to build the initial bundle', async () => {
|
||||||
|
|
|
@ -14,11 +14,20 @@
|
||||||
|
|
||||||
const DeltaPatcher = require('../DeltaPatcher');
|
const DeltaPatcher = require('../DeltaPatcher');
|
||||||
|
|
||||||
|
const INITIAL_TIME = 1482363367000;
|
||||||
|
|
||||||
describe('DeltaPatcher', () => {
|
describe('DeltaPatcher', () => {
|
||||||
|
const OriginalDate = global.Date;
|
||||||
let deltaPatcher;
|
let deltaPatcher;
|
||||||
|
|
||||||
|
function setCurrentTime(time: number) {
|
||||||
|
global.Date = jest.fn(() => new OriginalDate(time));
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
deltaPatcher = new DeltaPatcher();
|
deltaPatcher = new DeltaPatcher();
|
||||||
|
|
||||||
|
setCurrentTime(INITIAL_TIME);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if received a non-reset delta as the initial one', () => {
|
it('should throw if received a non-reset delta as the initial one', () => {
|
||||||
|
@ -117,4 +126,44 @@ describe('DeltaPatcher', () => {
|
||||||
// A deleted module counts as a modified file.
|
// A deleted module counts as a modified file.
|
||||||
expect(deltaPatcher.getLastNumModifiedFiles()).toEqual(2);
|
expect(deltaPatcher.getLastNumModifiedFiles()).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return the time it was last modified', () => {
|
||||||
|
deltaPatcher
|
||||||
|
.applyDelta({
|
||||||
|
reset: 1,
|
||||||
|
pre: new Map([[1, {code: 'pre'}]]),
|
||||||
|
post: new Map([[2, {code: 'post'}]]),
|
||||||
|
delta: new Map([[3, {code: 'middle'}]]),
|
||||||
|
})
|
||||||
|
.stringifyCode();
|
||||||
|
|
||||||
|
expect(deltaPatcher.getLastModifiedDate().getTime()).toEqual(INITIAL_TIME);
|
||||||
|
setCurrentTime(INITIAL_TIME + 1000);
|
||||||
|
|
||||||
|
// Apply empty delta
|
||||||
|
deltaPatcher
|
||||||
|
.applyDelta({
|
||||||
|
reset: 1,
|
||||||
|
pre: new Map(),
|
||||||
|
post: new Map(),
|
||||||
|
delta: new Map(),
|
||||||
|
})
|
||||||
|
.stringifyCode();
|
||||||
|
|
||||||
|
expect(deltaPatcher.getLastModifiedDate().getTime()).toEqual(INITIAL_TIME);
|
||||||
|
setCurrentTime(INITIAL_TIME + 2000);
|
||||||
|
|
||||||
|
deltaPatcher
|
||||||
|
.applyDelta({
|
||||||
|
reset: 1,
|
||||||
|
pre: new Map(),
|
||||||
|
post: new Map([[2, {code: 'newpost'}]]),
|
||||||
|
delta: new Map(),
|
||||||
|
})
|
||||||
|
.stringifyCode();
|
||||||
|
|
||||||
|
expect(deltaPatcher.getLastModifiedDate().getTime()).toEqual(
|
||||||
|
INITIAL_TIME + 2000,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ Object {
|
||||||
;module3
|
;module3
|
||||||
;another
|
;another
|
||||||
;post",
|
;post",
|
||||||
|
"lastModified": 2016-12-21T23:36:07.000Z,
|
||||||
"numModifiedFiles": 4,
|
"numModifiedFiles": 4,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -18,6 +19,7 @@ Object {
|
||||||
;post
|
;post
|
||||||
;bananas
|
;bananas
|
||||||
;apples",
|
;apples",
|
||||||
|
"lastModified": 2016-12-21T23:36:07.000Z,
|
||||||
"numModifiedFiles": 5,
|
"numModifiedFiles": 5,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -113,7 +113,7 @@ class DeltaBundler {
|
||||||
|
|
||||||
async buildFullBundle(
|
async buildFullBundle(
|
||||||
options: FullBuildOptions,
|
options: FullBuildOptions,
|
||||||
): Promise<{bundle: string, numModifiedFiles: number}> {
|
): Promise<{bundle: string, numModifiedFiles: number, lastModified: Date}> {
|
||||||
const deltaPatcher = await this._getDeltaPatcher(options);
|
const deltaPatcher = await this._getDeltaPatcher(options);
|
||||||
let bundle = deltaPatcher.stringifyCode();
|
let bundle = deltaPatcher.stringifyCode();
|
||||||
|
|
||||||
|
@ -123,6 +123,7 @@ class DeltaBundler {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bundle,
|
bundle,
|
||||||
|
lastModified: deltaPatcher.getLastModifiedDate(),
|
||||||
numModifiedFiles: deltaPatcher.getLastNumModifiedFiles(),
|
numModifiedFiles: deltaPatcher.getLastNumModifiedFiles(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -923,14 +923,13 @@ class Server {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let bundle;
|
let result;
|
||||||
let numModifiedFiles;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
({bundle, numModifiedFiles} = await this._deltaBundler.buildFullBundle({
|
result = await this._deltaBundler.buildFullBundle({
|
||||||
...options,
|
...options,
|
||||||
deltaBundleId: this.optionsHash(options),
|
deltaBundleId: this.optionsHash(options),
|
||||||
}));
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._handleError(res, this.optionsHash(options), error);
|
this._handleError(res, this.optionsHash(options), error);
|
||||||
|
|
||||||
|
@ -942,18 +941,24 @@ class Server {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const etag = crypto.createHash('md5').update(bundle).digest('hex');
|
if (
|
||||||
|
// We avoid parsing the dates since the client should never send a more
|
||||||
if (req.headers['if-none-match'] === etag) {
|
// recent date than the one returned by the Delta Bundler (if that's the
|
||||||
|
// case it's fine to return the whole bundle).
|
||||||
|
req.headers['if-modified-since'] === result.lastModified.toUTCString()
|
||||||
|
) {
|
||||||
debug('Responding with 304');
|
debug('Responding with 304');
|
||||||
res.writeHead(304);
|
res.writeHead(304);
|
||||||
res.end();
|
res.end();
|
||||||
} else {
|
} else {
|
||||||
res.setHeader(FILES_CHANGED_COUNT_HEADER, String(numModifiedFiles));
|
res.setHeader(
|
||||||
|
FILES_CHANGED_COUNT_HEADER,
|
||||||
|
String(result.numModifiedFiles),
|
||||||
|
);
|
||||||
res.setHeader('Content-Type', 'application/javascript');
|
res.setHeader('Content-Type', 'application/javascript');
|
||||||
res.setHeader('ETag', etag);
|
res.setHeader('Last-Modified', result.lastModified.toUTCString());
|
||||||
res.setHeader('Content-Length', String(Buffer.byteLength(bundle)));
|
res.setHeader('Content-Length', String(Buffer.byteLength(result.bundle)));
|
||||||
res.end(bundle);
|
res.end(result.bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._reporter.update({
|
this._reporter.update({
|
||||||
|
@ -964,7 +969,7 @@ class Server {
|
||||||
debug('Finished response');
|
debug('Finished response');
|
||||||
log({
|
log({
|
||||||
...createActionEndEntry(requestingBundleLogEntry),
|
...createActionEndEntry(requestingBundleLogEntry),
|
||||||
outdated_modules: numModifiedFiles,
|
outdated_modules: result.numModifiedFiles,
|
||||||
bundler: 'delta',
|
bundler: 'delta',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue