UNPKG

@angular/common

Version:

Angular - commonly needed directives and services

75 lines 10.6 kB
/** * @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=