@angular/common
Version:
Angular - commonly needed directives and services
75 lines • 10.6 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { inject, Injectable, ɵRuntimeError as RuntimeError } from '@angular/core';
import { DOCUMENT } from '../../dom_tokens';
import { DEFAULT_PRELOADED_IMAGES_LIMIT, PRELOADED_IMAGES } from './tokens';
import * as i0 from "@angular/core";
/**
* @description Contains the logic needed to track and add preload link tags to the `<head>` tag. It
* will also track what images have already had preload link tags added so as to not duplicate link
* tags.
*
* In dev mode this service will validate that the number of preloaded images does not exceed the
* configured default preloaded images limit: {@link DEFAULT_PRELOADED_IMAGES_LIMIT}.
*/
export class PreloadLinkCreator {
constructor() {
this.preloadedImages = inject(PRELOADED_IMAGES);
this.document = inject(DOCUMENT);
}
/**
* @description Add a preload `<link>` to the `<head>` of the `index.html` that is served from the
* server while using Angular Universal and SSR to kick off image loads for high priority images.
*
* The `sizes` (passed in from the user) and `srcset` (parsed and formatted from `ngSrcset`)
* properties used to set the corresponding attributes, `imagesizes` and `imagesrcset`
* respectively, on the preload `<link>` tag so that the correctly sized image is preloaded from
* the CDN.
*
* {@link https://web.dev/preload-responsive-images/#imagesrcset-and-imagesizes}
*
* @param renderer The `Renderer2` passed in from the directive
* @param src The original src of the image that is set on the `ngSrc` input.
* @param srcset The parsed and formatted srcset created from the `ngSrcset` input
* @param sizes The value of the `sizes` attribute passed in to the `<img>` tag
*/
createPreloadLinkTag(renderer, src, srcset, sizes) {
if (ngDevMode) {
if (this.preloadedImages.size >= DEFAULT_PRELOADED_IMAGES_LIMIT) {
throw new RuntimeError(2961 /* TOO_MANY_PRELOADED_IMAGES */, ngDevMode &&
`The \`NgOptimizedImage\` directive has detected that more than ` +
`${DEFAULT_PRELOADED_IMAGES_LIMIT} images were marked as priority. ` +
`This might negatively affect an overall performance of the page. ` +
`To fix this, remove the "priority" attribute from images with less priority.`);
}
}
if (this.preloadedImages.has(src)) {
return;
}
this.preloadedImages.add(src);
const preload = renderer.createElement('link');
renderer.setAttribute(preload, 'as', 'image');
renderer.setAttribute(preload, 'href', src);
renderer.setAttribute(preload, 'rel', 'preload');
renderer.setAttribute(preload, 'fetchpriority', 'high');
if (sizes) {
renderer.setAttribute(preload, 'imageSizes', sizes);
}
if (srcset) {
renderer.setAttribute(preload, 'imageSrcset', srcset);
}
renderer.appendChild(this.document.head, preload);
}
}
PreloadLinkCreator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PreloadLinkCreator, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
PreloadLinkCreator.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PreloadLinkCreator, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PreloadLinkCreator, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: function () { return []; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlbG9hZC1saW5rLWNyZWF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vc3JjL2RpcmVjdGl2ZXMvbmdfb3B0aW1pemVkX2ltYWdlL3ByZWxvYWQtbGluay1jcmVhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFhLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFM0YsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzFDLE9BQU8sRUFBQyw4QkFBOEIsRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLFVBQVUsQ0FBQzs7QUFFMUU7Ozs7Ozs7R0FPRztBQUVILE1BQU0sT0FBTyxrQkFBa0I7SUFJN0I7UUFDRSxJQUFJLENBQUMsZUFBZSxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxvQkFBb0IsQ0FBQyxRQUFtQixFQUFFLEdBQVcsRUFBRSxNQUFlLEVBQUUsS0FBYztRQUNwRixJQUFJLFNBQVMsRUFBRTtZQUNiLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLElBQUksOEJBQThCLEVBQUU7Z0JBQy9ELE1BQU0sSUFBSSxZQUFZLHVDQUVsQixTQUFTO29CQUNMLGlFQUFpRTt3QkFDN0QsR0FBRyw4QkFBOEIsbUNBQW1DO3dCQUNwRSxtRUFBbUU7d0JBQ25FLDhFQUE4RSxDQUFDLENBQUM7YUFDN0Y7U0FDRjtRQUVELElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDakMsT0FBTztTQUNSO1FBRUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFOUIsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxRQUFRLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDOUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzVDLFFBQVEsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNqRCxRQUFRLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFeEQsSUFBSSxLQUFLLEVBQUU7WUFDVCxRQUFRLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDckQ7UUFFRCxJQUFJLE1BQU0sRUFBRTtZQUNWLFFBQVEsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUN2RDtRQUVELFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDcEQsQ0FBQzs7MEhBM0RVLGtCQUFrQjs4SEFBbEIsa0JBQWtCLGNBRE4sTUFBTTtzR0FDbEIsa0JBQWtCO2tCQUQ5QixVQUFVO21CQUFDLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge2luamVjdCwgSW5qZWN0YWJsZSwgUmVuZGVyZXIyLCDJtVJ1bnRpbWVFcnJvciBhcyBSdW50aW1lRXJyb3J9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICcuLi8uLi9kb21fdG9rZW5zJztcbmltcG9ydCB7UnVudGltZUVycm9yQ29kZX0gZnJvbSAnLi4vLi4vZXJyb3JzJztcblxuaW1wb3J0IHtERUZBVUxUX1BSRUxPQURFRF9JTUFHRVNfTElNSVQsIFBSRUxPQURFRF9JTUFHRVN9IGZyb20gJy4vdG9rZW5zJztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29udGFpbnMgdGhlIGxvZ2ljIG5lZWRlZCB0byB0cmFjayBhbmQgYWRkIHByZWxvYWQgbGluayB0YWdzIHRvIHRoZSBgPGhlYWQ+YCB0YWcuIEl0XG4gKiB3aWxsIGFsc28gdHJhY2sgd2hhdCBpbWFnZXMgaGF2ZSBhbHJlYWR5IGhhZCBwcmVsb2FkIGxpbmsgdGFncyBhZGRlZCBzbyBhcyB0byBub3QgZHVwbGljYXRlIGxpbmtcbiAqIHRhZ3MuXG4gKlxuICogSW4gZGV2IG1vZGUgdGhpcyBzZXJ2aWNlIHdpbGwgdmFsaWRhdGUgdGhhdCB0aGUgbnVtYmVyIG9mIHByZWxvYWRlZCBpbWFnZXMgZG9lcyBub3QgZXhjZWVkIHRoZVxuICogY29uZmlndXJlZCBkZWZhdWx0IHByZWxvYWRlZCBpbWFnZXMgbGltaXQ6IHtAbGluayBERUZBVUxUX1BSRUxPQURFRF9JTUFHRVNfTElNSVR9LlxuICovXG5ASW5qZWN0YWJsZSh7cHJvdmlkZWRJbjogJ3Jvb3QnfSlcbmV4cG9ydCBjbGFzcyBQcmVsb2FkTGlua0NyZWF0b3Ige1xuICBwcml2YXRlIHJlYWRvbmx5IHByZWxvYWRlZEltYWdlcztcbiAgcHJpdmF0ZSByZWFkb25seSBkb2N1bWVudDtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnByZWxvYWRlZEltYWdlcyA9IGluamVjdChQUkVMT0FERURfSU1BR0VTKTtcbiAgICB0aGlzLmRvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkIGEgcHJlbG9hZCBgPGxpbms+YCB0byB0aGUgYDxoZWFkPmAgb2YgdGhlIGBpbmRleC5odG1sYCB0aGF0IGlzIHNlcnZlZCBmcm9tIHRoZVxuICAgKiBzZXJ2ZXIgd2hpbGUgdXNpbmcgQW5ndWxhciBVbml2ZXJzYWwgYW5kIFNTUiB0byBraWNrIG9mZiBpbWFnZSBsb2FkcyBmb3IgaGlnaCBwcmlvcml0eSBpbWFnZXMuXG4gICAqXG4gICAqIFRoZSBgc2l6ZXNgIChwYXNzZWQgaW4gZnJvbSB0aGUgdXNlcikgYW5kIGBzcmNzZXRgIChwYXJzZWQgYW5kIGZvcm1hdHRlZCBmcm9tIGBuZ1NyY3NldGApXG4gICAqIHByb3BlcnRpZXMgdXNlZCB0byBzZXQgdGhlIGNvcnJlc3BvbmRpbmcgYXR0cmlidXRlcywgYGltYWdlc2l6ZXNgIGFuZCBgaW1hZ2VzcmNzZXRgXG4gICAqIHJlc3BlY3RpdmVseSwgb24gdGhlIHByZWxvYWQgYDxsaW5rPmAgdGFnIHNvIHRoYXQgdGhlIGNvcnJlY3RseSBzaXplZCBpbWFnZSBpcyBwcmVsb2FkZWQgZnJvbVxuICAgKiB0aGUgQ0ROLlxuICAgKlxuICAgKiB7QGxpbmsgaHR0cHM6Ly93ZWIuZGV2L3ByZWxvYWQtcmVzcG9uc2l2ZS1pbWFnZXMvI2ltYWdlc3Jjc2V0LWFuZC1pbWFnZXNpemVzfVxuICAgKlxuICAgKiBAcGFyYW0gcmVuZGVyZXIgVGhlIGBSZW5kZXJlcjJgIHBhc3NlZCBpbiBmcm9tIHRoZSBkaXJlY3RpdmVcbiAgICogQHBhcmFtIHNyYyBUaGUgb3JpZ2luYWwgc3JjIG9mIHRoZSBpbWFnZSB0aGF0IGlzIHNldCBvbiB0aGUgYG5nU3JjYCBpbnB1dC5cbiAgICogQHBhcmFtIHNyY3NldCBUaGUgcGFyc2VkIGFuZCBmb3JtYXR0ZWQgc3Jjc2V0IGNyZWF0ZWQgZnJvbSB0aGUgYG5nU3Jjc2V0YCBpbnB1dFxuICAgKiBAcGFyYW0gc2l6ZXMgVGhlIHZhbHVlIG9mIHRoZSBgc2l6ZXNgIGF0dHJpYnV0ZSBwYXNzZWQgaW4gdG8gdGhlIGA8aW1nPmAgdGFnXG4gICAqL1xuICBjcmVhdGVQcmVsb2FkTGlua1RhZyhyZW5kZXJlcjogUmVuZGVyZXIyLCBzcmM6IHN0cmluZywgc3Jjc2V0Pzogc3RyaW5nLCBzaXplcz86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChuZ0Rldk1vZGUpIHtcbiAgICAgIGlmICh0aGlzLnByZWxvYWRlZEltYWdlcy5zaXplID49IERFRkFVTFRfUFJFTE9BREVEX0lNQUdFU19MSU1JVCkge1xuICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFxuICAgICAgICAgICAgUnVudGltZUVycm9yQ29kZS5UT09fTUFOWV9QUkVMT0FERURfSU1BR0VTLFxuICAgICAgICAgICAgbmdEZXZNb2RlICYmXG4gICAgICAgICAgICAgICAgYFRoZSBcXGBOZ09wdGltaXplZEltYWdlXFxgIGRpcmVjdGl2ZSBoYXMgZGV0ZWN0ZWQgdGhhdCBtb3JlIHRoYW4gYCArXG4gICAgICAgICAgICAgICAgICAgIGAke0RFRkFVTFRfUFJFTE9BREVEX0lNQUdFU19MSU1JVH0gaW1hZ2VzIHdlcmUgbWFya2VkIGFzIHByaW9yaXR5LiBgICtcbiAgICAgICAgICAgICAgICAgICAgYFRoaXMgbWlnaHQgbmVnYXRpdmVseSBhZmZlY3QgYW4gb3ZlcmFsbCBwZXJmb3JtYW5jZSBvZiB0aGUgcGFnZS4gYCArXG4gICAgICAgICAgICAgICAgICAgIGBUbyBmaXggdGhpcywgcmVtb3ZlIHRoZSBcInByaW9yaXR5XCIgYXR0cmlidXRlIGZyb20gaW1hZ2VzIHdpdGggbGVzcyBwcmlvcml0eS5gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcmVsb2FkZWRJbWFnZXMuaGFzKHNyYykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnByZWxvYWRlZEltYWdlcy5hZGQoc3JjKTtcblxuICAgIGNvbnN0IHByZWxvYWQgPSByZW5kZXJlci5jcmVhdGVFbGVtZW50KCdsaW5rJyk7XG4gICAgcmVuZGVyZXIuc2V0QXR0cmlidXRlKHByZWxvYWQsICdhcycsICdpbWFnZScpO1xuICAgIHJlbmRlcmVyLnNldEF0dHJpYnV0ZShwcmVsb2FkLCAnaHJlZicsIHNyYyk7XG4gICAgcmVuZGVyZXIuc2V0QXR0cmlidXRlKHByZWxvYWQsICdyZWwnLCAncHJlbG9hZCcpO1xuICAgIHJlbmRlcmVyLnNldEF0dHJpYnV0ZShwcmVsb2FkLCAnZmV0Y2hwcmlvcml0eScsICdoaWdoJyk7XG5cbiAgICBpZiAoc2l6ZXMpIHtcbiAgICAgIHJlbmRlcmVyLnNldEF0dHJpYnV0ZShwcmVsb2FkLCAnaW1hZ2VTaXplcycsIHNpemVzKTtcbiAgICB9XG5cbiAgICBpZiAoc3Jjc2V0KSB7XG4gICAgICByZW5kZXJlci5zZXRBdHRyaWJ1dGUocHJlbG9hZCwgJ2ltYWdlU3Jjc2V0Jywgc3Jjc2V0KTtcbiAgICB9XG5cbiAgICByZW5kZXJlci5hcHBlbmRDaGlsZCh0aGlzLmRvY3VtZW50LmhlYWQsIHByZWxvYWQpO1xuICB9XG59XG4iXX0=