Skip to content

Commit

Permalink
fix(common): rename rawSrc -> ngSrc in NgOptimizedImage directive (
Browse files Browse the repository at this point in the history
…#47362)

As an ongoing effort to stabilize the NgOptimizedImage API before existing the Developer Preview, this commit renames the `rawSrc` attribute used for the NgOptimizedImage selector matching to `ngSrc`. The `rawSrcset` is also renamed to `ngSrcset` for consistency.

The motivation for this change is to align the attribute name better with other built-in directives, such as `ngFor`, `ngIf`, `ngClass`, `ngStyle`, etc.

Note: this is technically a breaking change, but since the NgOptimizedImage directive is in the Developer Preview mode, we land the change in a patch branch.

PR Close #47362
  • Loading branch information
AndrewKushnir authored and dylhunn committed Sep 9, 2022
1 parent 710d1da commit ca7bf65
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 256 deletions.
2 changes: 1 addition & 1 deletion aio/content/guide/image-directive-setup.md
Expand Up @@ -93,4 +93,4 @@ providers: [

A loader function for the `NgOptimizedImage` directive takes an object with the `ImageLoaderConfig` type (from `@angular/common`) as its argument and returns the absolute URL of the image asset. The `ImageLoaderConfig` object contains the `src`and `width` properties.

Note: a custom loader must support requesting images at various widths in order for `rawSrcset` to work properly.
Note: a custom loader must support requesting images at various widths in order for `ngSrcset` to work properly.
18 changes: 9 additions & 9 deletions aio/content/guide/image-directive.md
Expand Up @@ -25,11 +25,11 @@ You will need to import the directive into your application. In addition, you wi

### Overview

To activate the `NgOptimizedImage` directive, replace your image's `src` attribute with `rawSrc`.
To activate the `NgOptimizedImage` directive, replace your image's `src` attribute with `ngSrc`.

<code-example format="typescript" language="typescript">

&lt;img rawSrc="cat.jpg" width="400" height="200"&gt;
&lt;img ngSrc="cat.jpg" width="400" height="200"&gt;

</code-example>

Expand All @@ -43,7 +43,7 @@ Always mark the [LCP image](https://web.dev/lcp/#what-elements-are-considered) o

<code-example format="typescript" language="typescript">

&lt;img rawSrc="cat.jpg" width="400" height="200" priority&gt;
&lt;img ngSrc="cat.jpg" width="400" height="200" priority&gt;

</code-example>

Expand Down Expand Up @@ -84,21 +84,21 @@ You can typically fix this by adding `height: auto` or `width: auto` to your ima

### Handling `srcset` attributes

If your `<img>` tag defines a `srcset` attribute, replace it with `rawSrcset`.
If your `<img>` tag defines a `srcset` attribute, replace it with `ngSrcset`.

<code-example format="html" language="html">

&lt;img rawSrc="hero.jpg" rawSrcset="100w, 200w, 300w"&gt;
&lt;img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w"&gt;

</code-example>

If the `rawSrcset` attribute is present, `NgOptimizedImage` generates and sets the [`srcset` attribute](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset) using the configured image loader. Do not include image file names in `rawSrcset` - the directive infers this information from `rawSrc`. The directive supports both width descriptors (e.g. `100w`) and density descriptors (e.g. `1x`) are supported.
If the `ngSrcset` attribute is present, `NgOptimizedImage` generates and sets the [`srcset` attribute](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset) using the configured image loader. Do not include image file names in `ngSrcset` - the directive infers this information from `ngSrc`. The directive supports both width descriptors (e.g. `100w`) and density descriptors (e.g. `1x`) are supported.

You can also use `rawSrcset` with the standard image [`sizes` attribute](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes).
You can also use `ngSrcset` with the standard image [`sizes` attribute](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes).

<code-example format="html" language="html">

&lt;img rawSrc="hero.jpg" rawSrcset="100w, 200w, 300w" sizes="50vw"&gt;
&lt;img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w" sizes="50vw"&gt;

</code-example>

Expand All @@ -108,7 +108,7 @@ By default, `NgOptimizedImage` sets `loading=lazy` for all images that are not m

<code-example format="html" language="html">

&lt;img rawSrc="cat.jpg" width="400" height="200" loading="eager"&gt;
&lt;img ngSrc="cat.jpg" width="400" height="200" loading="eager"&gt;

</code-example>

Expand Down
8 changes: 5 additions & 3 deletions goldens/public-api/common/index.md
Expand Up @@ -545,16 +545,18 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
ngOnDestroy(): void;
// (undocumented)
ngOnInit(): void;
ngSrc: string;
ngSrcset: string;
set priority(value: string | boolean | undefined);
// (undocumented)
get priority(): boolean;
rawSrc: string;
rawSrcset: string;
// @deprecated
set rawSrc(value: string);
set width(value: string | number | undefined);
// (undocumented)
get width(): number | undefined;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<NgOptimizedImage, "img[rawSrc]", never, { "rawSrc": "rawSrc"; "rawSrcset": "rawSrcset"; "width": "width"; "height": "height"; "loading": "loading"; "priority": "priority"; "src": "src"; "srcset": "srcset"; }, {}, never, never, true, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<NgOptimizedImage, "img[ngSrc],img[rawSrc]", never, { "rawSrc": "rawSrc"; "ngSrc": "ngSrc"; "ngSrcset": "ngSrcset"; "width": "width"; "height": "height"; "loading": "loading"; "priority": "priority"; "src": "src"; "srcset": "srcset"; }, {}, never, never, true, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<NgOptimizedImage, never>;
}
Expand Down
Expand Up @@ -7,8 +7,8 @@
*/

// Assembles directive details string, useful for error messages.
export function imgDirectiveDetails(rawSrc: string, includeRawSrc = true) {
const rawSrcInfo =
includeRawSrc ? `(activated on an <img> element with the \`rawSrc="${rawSrc}"\`) ` : '';
return `The NgOptimizedImage directive ${rawSrcInfo}has detected that`;
export function imgDirectiveDetails(ngSrc: string, includeNgSrc = true) {
const ngSrcInfo =
includeNgSrc ? `(activated on an <img> element with the \`ngSrc="${ngSrc}"\`) ` : '';
return `The NgOptimizedImage directive ${ngSrcInfo}has detected that`;
}
Expand Up @@ -118,10 +118,10 @@ function throwUnexpectedAbsoluteUrlError(path: string, url: string): never {
throw new RuntimeError(
RuntimeErrorCode.INVALID_LOADER_ARGUMENTS,
ngDevMode &&
`Image loader has detected a \`<img>\` tag with an invalid \`rawSrc\` attribute: ${
`Image loader has detected a \`<img>\` tag with an invalid \`ngSrc\` attribute: ${
url}. ` +
`This image loader expects \`rawSrc\` to be a relative URL - ` +
`This image loader expects \`ngSrc\` to be a relative URL - ` +
`however the provided value is an absolute URL. ` +
`To fix this, provide \`rawSrc\` as a path relative to the base URL ` +
`To fix this, provide \`ngSrc\` as a path relative to the base URL ` +
`configured for this loader (\`${path}\`).`);
}
Expand Up @@ -27,7 +27,7 @@ import {getUrl} from './url';
*/
@Injectable({providedIn: 'root'})
export class LCPImageObserver implements OnDestroy {
// Map of full image URLs -> original `rawSrc` values.
// Map of full image URLs -> original `ngSrc` values.
private images = new Map<string, string>();
// Keep track of images for which `console.warn` was produced.
private alreadyWarned = new Set<string>();
Expand Down Expand Up @@ -65,8 +65,8 @@ export class LCPImageObserver implements OnDestroy {
// Exclude `data:` and `blob:` URLs, since they are not supported by the directive.
if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:')) return;

const imgRawSrc = this.images.get(imgSrc);
if (imgRawSrc && !this.alreadyWarned.has(imgSrc)) {
const imgNgSrc = this.images.get(imgSrc);
if (imgNgSrc && !this.alreadyWarned.has(imgSrc)) {
this.alreadyWarned.add(imgSrc);
logMissingPriorityWarning(imgSrc);
}
Expand All @@ -75,9 +75,9 @@ export class LCPImageObserver implements OnDestroy {
return observer;
}

registerImage(rewrittenSrc: string, rawSrc: string) {
registerImage(rewrittenSrc: string, originalNgSrc: string) {
if (!this.observer) return;
this.images.set(getUrl(rewrittenSrc, this.window!).href, rawSrc);
this.images.set(getUrl(rewrittenSrc, this.window!).href, originalNgSrc);
}

unregisterImage(rewrittenSrc: string) {
Expand All @@ -93,8 +93,8 @@ export class LCPImageObserver implements OnDestroy {
}
}

function logMissingPriorityWarning(rawSrc: string) {
const directiveDetails = imgDirectiveDetails(rawSrc);
function logMissingPriorityWarning(ngSrc: string) {
const directiveDetails = imgDirectiveDetails(ngSrc);
console.warn(formatRuntimeError(
RuntimeErrorCode.LCP_IMG_MISSING_PRIORITY,
`${directiveDetails} this image is the Largest Contentful Paint (LCP) ` +
Expand Down

0 comments on commit ca7bf65

Please sign in to comment.