mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
perf(http): reduce data transfer when using HTTP caching (#52347)
This commit reduces the property size in the http transfer cache to reduce the page payload.
Before
```html
<script id="ng-state" type="application/json">
{
"4155228514": {
"body": "....",
"headers": {},
"status": 200,
"statusText": "OK",
"url": "http://foo.com/assets/media.json",
"responseType": "json"
},
}
</script>
```
Now
```html
<script id="ng-state" type="application/json">
{
"4155228514": {
"b": "....",
"h": {},
"s": 200,
"st": "OK",
"u": "http://foo.com/assets/media.json",
"rt": "json"
},
}
</script>
```
PR Close #52347
This commit is contained in:
@@ -35,13 +35,31 @@ export type HttpTransferCacheOptions = {
|
||||
includePostRequests?: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Keys within cached response data structure.
|
||||
*/
|
||||
|
||||
export const BODY = 'b';
|
||||
export const HEADERS = 'h';
|
||||
export const STATUS = 's';
|
||||
export const STATUS_TEXT = 'st';
|
||||
export const URL = 'u';
|
||||
export const RESPONSE_TYPE = 'rt';
|
||||
|
||||
|
||||
interface TransferHttpResponse {
|
||||
body: any;
|
||||
headers: Record<string, string[]>;
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
url?: string;
|
||||
responseType?: HttpRequest<unknown>['responseType'];
|
||||
/** body */
|
||||
[BODY]: any;
|
||||
/** headers */
|
||||
[HEADERS]: Record<string, string[]>;
|
||||
/** status */
|
||||
[STATUS]?: number;
|
||||
/** statusText */
|
||||
[STATUS_TEXT]?: string;
|
||||
/** url */
|
||||
[URL]?: string;
|
||||
/** responseType */
|
||||
[RESPONSE_TYPE]?: HttpRequest<unknown>['responseType'];
|
||||
}
|
||||
|
||||
interface CacheOptions extends HttpTransferCacheOptions {
|
||||
@@ -82,22 +100,30 @@ export function transferCacheInterceptorFn(
|
||||
}
|
||||
|
||||
if (response) {
|
||||
const {
|
||||
[BODY]: undecodedBody,
|
||||
[RESPONSE_TYPE]: responseType,
|
||||
[HEADERS]: httpHeaders,
|
||||
[STATUS]: status,
|
||||
[STATUS_TEXT]: statusText,
|
||||
[URL]: url
|
||||
} = response;
|
||||
// Request found in cache. Respond using it.
|
||||
let body: ArrayBuffer|Blob|string|undefined = response.body;
|
||||
let body: ArrayBuffer|Blob|string|undefined = undecodedBody;
|
||||
|
||||
switch (response.responseType) {
|
||||
switch (responseType) {
|
||||
case 'arraybuffer':
|
||||
body = new TextEncoder().encode(response.body).buffer;
|
||||
body = new TextEncoder().encode(undecodedBody).buffer;
|
||||
break;
|
||||
case 'blob':
|
||||
body = new Blob([response.body]);
|
||||
body = new Blob([undecodedBody]);
|
||||
break;
|
||||
}
|
||||
|
||||
// We want to warn users accessing a header provided from the cache
|
||||
// That HttpTransferCache alters the headers
|
||||
// The warning will be logged a single time by HttpHeaders instance
|
||||
let headers = new HttpHeaders(response.headers);
|
||||
let headers = new HttpHeaders(httpHeaders);
|
||||
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
||||
// Append extra logic in dev mode to produce a warning when a header
|
||||
// that was not transferred to the client is accessed in the code via `get`
|
||||
@@ -110,9 +136,9 @@ export function transferCacheInterceptorFn(
|
||||
new HttpResponse({
|
||||
body,
|
||||
headers,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
url: response.url,
|
||||
status,
|
||||
statusText,
|
||||
url,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -123,12 +149,12 @@ export function transferCacheInterceptorFn(
|
||||
tap((event: HttpEvent<unknown>) => {
|
||||
if (event instanceof HttpResponse) {
|
||||
transferState.set<TransferHttpResponse>(storeKey, {
|
||||
body: event.body,
|
||||
headers: getFilteredHeaders(event.headers, headersToInclude),
|
||||
status: event.status,
|
||||
statusText: event.statusText,
|
||||
url: event.url || '',
|
||||
responseType: req.responseType,
|
||||
[BODY]: event.body,
|
||||
[HEADERS]: getFilteredHeaders(event.headers, headersToInclude),
|
||||
[STATUS]: event.status,
|
||||
[STATUS_TEXT]: event.statusText,
|
||||
[URL]: event.url || '',
|
||||
[RESPONSE_TYPE]: req.responseType,
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -14,7 +14,7 @@ import {withBody} from '@angular/private/testing';
|
||||
import {BehaviorSubject} from 'rxjs';
|
||||
|
||||
import {HttpClient, HttpResponse, provideHttpClient} from '../public_api';
|
||||
import {withHttpTransferCache} from '../src/transfer_cache';
|
||||
import {BODY, HEADERS, RESPONSE_TYPE, STATUS, STATUS_TEXT, URL, withHttpTransferCache} from '../src/transfer_cache';
|
||||
import {HttpTestingController, provideHttpClientTesting} from '../testing';
|
||||
|
||||
interface RequestParams {
|
||||
@@ -84,7 +84,7 @@ describe('TransferCache', () => {
|
||||
makeRequestAndExpectOne('/test', 'foo');
|
||||
const key = makeStateKey('432906284');
|
||||
const transferState = TestBed.inject(TransferState);
|
||||
expect(transferState.get(key, null)).toEqual(jasmine.objectContaining({body: 'foo'}));
|
||||
expect(transferState.get(key, null)).toEqual(jasmine.objectContaining({[BODY]: 'foo'}));
|
||||
});
|
||||
|
||||
it('should stop storing HTTP calls in `TransferState` after application becomes stable',
|
||||
@@ -101,20 +101,20 @@ describe('TransferCache', () => {
|
||||
const transferState = TestBed.inject(TransferState);
|
||||
expect(JSON.parse(transferState.toJson()) as Record<string, unknown>).toEqual({
|
||||
'3706062792': {
|
||||
'body': 'foo',
|
||||
'headers': {},
|
||||
'status': 200,
|
||||
'statusText': 'OK',
|
||||
'url': '/test-1',
|
||||
'responseType': 'json'
|
||||
[BODY]: 'foo',
|
||||
[HEADERS]: {},
|
||||
[STATUS]: 200,
|
||||
[STATUS_TEXT]: 'OK',
|
||||
[URL]: '/test-1',
|
||||
[RESPONSE_TYPE]: 'json'
|
||||
},
|
||||
'3706062823': {
|
||||
'body': 'buzz',
|
||||
'headers': {},
|
||||
'status': 200,
|
||||
'statusText': 'OK',
|
||||
'url': '/test-2',
|
||||
'responseType': 'json'
|
||||
[BODY]: 'buzz',
|
||||
[HEADERS]: {},
|
||||
[STATUS]: 200,
|
||||
[STATUS_TEXT]: 'OK',
|
||||
[URL]: '/test-2',
|
||||
[RESPONSE_TYPE]: 'json'
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user