{"id":35728,"date":"2024-09-18T07:00:00","date_gmt":"2024-09-18T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=35728"},"modified":"2025-05-16T13:10:06","modified_gmt":"2025-05-16T20:10:06","slug":"using-ngoptimizedimage-with-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary","title":{"rendered":"Using NgOptimizedImage With Cloudinary"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>While Cloudinary provides an <a href=\"https:\/\/cloudinary.com\/documentation\/angular_integration\">extensive Angular SDK<\/a>, which also includes the <code>CloudinaryImageComponent<\/code> that you can use to display your Cloudinary images, a little-known fact is that Angular exposes a <a href=\"https:\/\/angular.dev\/api\/common\/provideCloudinaryLoader\">Cloudinary image loader provider<\/a> you can use with the <a href=\"https:\/\/angular.dev\/guide\/image-optimization\">NgOptimizedImage directive<\/a>.<\/p>\n<p>That means if you don\u2019t want to install the Cloudinary Angular SDK, or if you\u2019re an Angular purist and prefer to use Angular\u2019s built-in features as much as possible, you can still conveniently load Cloudinary images using Angular\u2019s <code>img<\/code> tag and the <code>NgOptimizedImage<\/code> directive.<\/p>\n<h2>How Does the NgOptimizedImage Directive Work?<\/h2>\n<p>The <code>NgOptimizedImage<\/code> directive in Angular wraps the HTML <code>img<\/code> element while adhering to best practices for image loading performance, such as automatically setting the <code>fetchpriority<\/code> attribute on the <code>&lt;img&gt;<\/code> tag, lazy loading non-priority images by default, generating preconnect links, generating <code>srcset<\/code> attributes to request images at appropriate sizes based on the viewport, or providing preload hints when using server-side rendering (SSR). It also enforces specifying images with <code>width<\/code> and <code>height<\/code> attributes to prevent layout shifts and warns you of incorrect dimensions or potential visual distortion.<\/p>\n<p>The <code>NgOptimizedImage<\/code> directive can also automatically utilize low-resolution placeholders when using a CDN such as Cloudinary and custom placeholders via base64 data URLs.<\/p>\n<p>To begin, import the directive from <code>@angular\/common<\/code> and include it in your component or module imports:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { NgOptimizedImage } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@angular\/common'<\/span>;\n@Component({\n  <span class=\"hljs-attr\">selector<\/span>: <span class=\"hljs-string\">'app-component'<\/span>,\n  <span class=\"hljs-attr\">imports<\/span>: &#91;NgOptimizedImage], <span class=\"hljs-comment\">\/\/ Import the directive<\/span>\n  <span class=\"hljs-attr\">templateURL<\/span>: <span class=\"hljs-string\">'.\/app.component.html'<\/span>,\n})\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And then, in your HTML template, you can use the <code>NgOptimizedImage<\/code> directive by specifying the <code>ngSrc<\/code> attribute in your <code>img<\/code> tag:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">ngSrc<\/span>=<span class=\"hljs-string\">\"public\/my-image.jpg\"<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span> \/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>If you need the image to load first, you can use the <code>priority<\/code> attribute:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">ngSrc<\/span>=<span class=\"hljs-string\">\"public\/my-image.jpg\"<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">priority<\/span> \/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>If you need the image to fill the container, you can use the <code>fill<\/code> attribute and omit the <code>width<\/code> and <code>height<\/code> attributes. The fill mode allows it to behave like a background image, adjusting to the container\u2019s dimensions.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"position: relative; width: 500px; height: 250px\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">ngSrc<\/span>=<span class=\"hljs-string\">\"public\/my-image.jpg\"<\/span> <span class=\"hljs-attr\">fill<\/span> \/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>For more details about the <code>NgOptimizedImage<\/code> directive, check out the <a href=\"https:\/\/angular.dev\/guide\/image-optimization\">Angular documentation<\/a>.<\/p>\n<h2>Using the Cloudinary Image Loader With NgOptimizedImage<\/h2>\n<p>As mentioned, you can use the built-in <code>provideCloudinaryLoader<\/code> function to integrate your Cloudinary instance with your Angular application. To use it, you need to provide the <code>provideCloudinaryLoader<\/code> function in your application\u2019s providers array:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ app.config.ts<\/span>\n<span class=\"hljs-keyword\">import<\/span> { cloudinaryCloudName } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/environments\/environment\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { ApplicationConfig, provideZoneChangeDetection } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/core\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { provideRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/router\"<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> { routes } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/app.routes\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { provideClientHydration } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/platform-browser\"<\/span>;\n\n<span class=\"hljs-comment\">\/\/ Import the provideCloudinaryLoader function<\/span>\n<span class=\"hljs-keyword\">import<\/span> { provideCloudinaryLoader } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/common\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> appConfig: ApplicationConfig = {\n  <span class=\"hljs-attr\">providers<\/span>: &#91;\n    provideZoneChangeDetection({ <span class=\"hljs-attr\">eventCoalescing<\/span>: <span class=\"hljs-literal\">true<\/span> }),\n    provideRouter(routes),\n    provideClientHydration(),\n    <span class=\"hljs-comment\">\/\/ Provide the Cloudinary loader with your Cloudinary URL<\/span>\n    provideCloudinaryLoader(<span class=\"hljs-string\">`https:\/\/res.cloudinary.com\/<span class=\"hljs-subst\">${cloudinaryCloudName}<\/span>`<\/span>),\n  ],\n};\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You can then use the <code>NgOptimizedImage<\/code> directive with the <code>ngSrc<\/code> attribute to load your Cloudinary images:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ cld-sample.jpg is an image that should exist in your Cloudinary account<\/span>\n&lt;img ngSrc=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span> width=<span class=\"hljs-string\">\"500\"<\/span> height=<span class=\"hljs-string\">\"500\"<\/span> priority \/&gt;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You can also add the <code>placeholder<\/code> attribute to automatically download a low-resolution placeholder image first before the full image is loaded:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">ngSrc<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">priority<\/span> <span class=\"hljs-attr\">placeholder<\/span> \/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>That\u2019s it! You should now see your image loaded when you run your Angular application with <code>ng serve<\/code> and navigate to <a href=\"http:\/\/localhost:4200\">localhost:4200<\/a>. The rendered <code>html<\/code> should look something like this:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n  <span class=\"hljs-attr\">_ngcontent-ng-c1071307065<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ngsrc<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">priority<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-ng-src<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-height<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-priority<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-placeholder<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">loading<\/span>=<span class=\"hljs-string\">\"eager\"<\/span>\n  <span class=\"hljs-attr\">fetchpriority<\/span>=<span class=\"hljs-string\">\"high\"<\/span>\n  <span class=\"hljs-attr\">ng-img<\/span>=<span class=\"hljs-string\">\"true\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto\/cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">srcset<\/span>=<span class=\"hljs-string\">\"\n    https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto,w_500\/cld-sample.jpg  1x,\n    https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto,w_1000\/cld-sample.jpg 2x\n  \"<\/span>\n  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n\/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Using Angular\u2019s Built-in Cloudinary Image Loader<\/h2>\n<p>Angular provides a built-in Cloudinary image loader, but it isn\u2019t widely adopted because of its basic capabilities. The loader\u2019s <a href=\"https:\/\/github.com\/angular\/angular\/blob\/main\/packages\/common\/src\/directives\/ng_optimized_image\/image_loaders\/cloudinary_loader.ts\">current implementation<\/a> lacks the flexibility to fully leverage Cloudinary\u2019s powerful features, such as resizing, transformations, and optimizations, which are key to maximizing the platform\u2019s potential.<\/p>\n<h2>The Solution<\/h2>\n<p>The most convenient solution is to use the <a href=\"https:\/\/cloudinary.com\/documentation\/angular_integration\">Cloudinary Angular SDK<\/a>, which provides a comprehensive set of features and options for working with Cloudinary images.<\/p>\n<p>However, you may still want to use the <code>NgOptimizedImage<\/code> directive. In that case, you can create a <a href=\"https:\/\/angular.dev\/guide\/image-optimization#custom-loaders\">custom image loader<\/a> that integrates with Cloudinary\u2019s URL API to generate image URLs with the desired transformations.<\/p>\n<p>You can also use some features of the @cloudinary\/url-gen SDK to generate the transformation string in your loader based on the specified <a href=\"https:\/\/angular.dev\/guide\/image-optimization#the-loaderparams-property\">loaderParams<\/a>.<\/p>\n<p>First, you\u2019ll need to install the <code>@cloudinary\/url-gen<\/code> package:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-keyword\">@cloudinary<\/span>\/url-gen\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Then, you can create a custom Cloudinary loader function that generates the Cloudinary URL based on the provided <code>ImageLoaderConfig<\/code> and <code>loaderParams<\/code>. Here\u2019s an example of a custom Cloudinary loader function that generates a Cloudinary URL with the specified transformations:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { cloudinaryCloudName } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/environments\/environment\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { ImageLoaderConfig } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/common\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { transformationStringFromObject } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/index\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { LegacyTransformation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/types\/types\"<\/span>;\n\n<span class=\"hljs-comment\">\/\/ Reexport the type from the Cloudinary SDK for the transformation config<\/span>\n<span class=\"hljs-keyword\">export<\/span> type TransformationConfig = LegacyTransformation;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">customCloudinaryLoader<\/span>(<span class=\"hljs-params\">config: ImageLoaderConfig<\/span>) <\/span>{\n  <span class=\"hljs-comment\">\/\/ Specify your Cloudinary URL here<\/span>\n  <span class=\"hljs-keyword\">const<\/span> path = <span class=\"hljs-string\">`https:\/\/res.cloudinary.com\/<span class=\"hljs-subst\">${cloudinaryCloudName}<\/span>`<\/span>;\n\n  <span class=\"hljs-comment\">\/\/ For a placeholder image, we use the lowest image setting available to reduce the load time<\/span>\n  <span class=\"hljs-comment\">\/\/ else we use the auto size<\/span>\n  <span class=\"hljs-keyword\">const<\/span> quality = config.isPlaceholder ? <span class=\"hljs-string\">\"q_auto:low\"<\/span> : <span class=\"hljs-string\">\"q_auto\"<\/span>;\n\n  <span class=\"hljs-keyword\">let<\/span> params = <span class=\"hljs-string\">`<span class=\"hljs-subst\">${quality}<\/span>`<\/span>;\n  <span class=\"hljs-keyword\">if<\/span> (config.width) {\n    params += <span class=\"hljs-string\">`,w_<span class=\"hljs-subst\">${config.width}<\/span>`<\/span>;\n  }\n  <span class=\"hljs-keyword\">if<\/span> (config.loaderParams &amp;&amp; config.loaderParams&#91;<span class=\"hljs-string\">\"transformation\"<\/span>]) {\n    <span class=\"hljs-comment\">\/\/ Generate the transformation string from the loaderParams object using the Cloudinary SDK<\/span>\n    params += <span class=\"hljs-string\">`,<span class=\"hljs-subst\">${transformationStringFromObject(\n      config.loaderParams&#91;<span class=\"hljs-string\">\"transformation\"<\/span>]\n    )}<\/span>`<\/span>;\n  }\n\n  <span class=\"hljs-comment\">\/\/ Return the Cloudinary URL with the specified transformations<\/span>\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`<span class=\"hljs-subst\">${path}<\/span>\/image\/upload\/<span class=\"hljs-subst\">${params}<\/span>\/<span class=\"hljs-subst\">${config.src}<\/span>`<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You can then provide this custom loader function in your application\u2019s <code>providers<\/code> array instead of the built-in Cloudinary loader:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { ApplicationConfig, provideZoneChangeDetection } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/core\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { provideRouter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/router\"<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> { routes } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/app.routes\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { provideClientHydration } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/platform-browser\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { IMAGE_LOADER } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@angular\/common\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { customCloudinaryLoader } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/custom-cloudinary-loader\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> appConfig: ApplicationConfig = {\n  <span class=\"hljs-attr\">providers<\/span>: &#91;\n    provideZoneChangeDetection({ <span class=\"hljs-attr\">eventCoalescing<\/span>: <span class=\"hljs-literal\">true<\/span> }),\n    provideRouter(routes),\n    provideClientHydration(),\n    <span class=\"hljs-comment\">\/\/ Provide the custom loader<\/span>\n    {\n      <span class=\"hljs-attr\">provide<\/span>: IMAGE_LOADER,\n      <span class=\"hljs-attr\">useValue<\/span>: customCloudinaryLoader,\n    },\n  ],\n};\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And specify the transformations you want to apply to the image in your component as the <code>loaderParams<\/code> object:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { TransformationConfig } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/custom-cloudinary-loader\"<\/span>;\n\n@Component({\n  <span class=\"hljs-attr\">selector<\/span>: <span class=\"hljs-string\">\"app-root\"<\/span>,\n  <span class=\"hljs-attr\">standalone<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">imports<\/span>: &#91;RouterOutlet, NgOptimizedImage],\n  <span class=\"hljs-attr\">templateUrl<\/span>: <span class=\"hljs-string\">\".\/app.component.html\"<\/span>,\n  <span class=\"hljs-attr\">styleUrl<\/span>: <span class=\"hljs-string\">\".\/app.component.scss\"<\/span>,\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AppComponent<\/span> <\/span>{\n  <span class=\"hljs-attr\">loaderParams<\/span>: {\n    <span class=\"hljs-attr\">transformation<\/span>: TransformationConfig;\n  } = {\n    <span class=\"hljs-comment\">\/\/ Specify the transformations you want to apply to the image as an object<\/span>\n    <span class=\"hljs-attr\">transformation<\/span>: &#91;\n      { <span class=\"hljs-attr\">gravity<\/span>: <span class=\"hljs-string\">\"face\"<\/span>, <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">500<\/span>, <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">500<\/span>, <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"thumb\"<\/span> },\n      { <span class=\"hljs-attr\">radius<\/span>: <span class=\"hljs-number\">100<\/span> },\n    ],\n  };\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And finally, use the <code>loaderParams<\/code> object in your <code>NgOptimizedImage<\/code> directive:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n  <span class=\"hljs-attr\">ngSrc<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">priority<\/span>\n  <span class=\"hljs-attr\">placeholder<\/span>\n  &#91;<span class=\"hljs-attr\">loaderParams<\/span>]=<span class=\"hljs-string\">\"loaderParams\"<\/span>\n\/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You should now see the transformations applied to your <a href=\"https:\/\/cloudinary.com\/products\/image\">Cloudinary image<\/a> when you navigate to your Angular application in the browser. The rendered <code>html<\/code> should look like this:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n  <span class=\"hljs-attr\">_ngcontent-ng-c3913398994<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ngsrc<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">priority<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-ng-src<\/span>=<span class=\"hljs-string\">\"cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-height<\/span>=<span class=\"hljs-string\">\"500\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-priority<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-placeholder<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n  <span class=\"hljs-attr\">ng-reflect-loader-params<\/span>=<span class=\"hljs-string\">\"&#91;object Object]\"<\/span>\n  <span class=\"hljs-attr\">loading<\/span>=<span class=\"hljs-string\">\"eager\"<\/span>\n  <span class=\"hljs-attr\">fetchpriority<\/span>=<span class=\"hljs-string\">\"high\"<\/span>\n  <span class=\"hljs-attr\">ng-img<\/span>=<span class=\"hljs-string\">\"true\"<\/span>\n  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto,c_thumb,g_face,h_500,w_500\/r_100\/cld-sample.jpg\"<\/span>\n  <span class=\"hljs-attr\">srcset<\/span>=<span class=\"hljs-string\">\"\n    https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto,w_500,c_thumb,g_face,h_500,w_500\/r_100\/cld-sample.jpg  1x,\n    https:\/\/res.cloudinary.com\/&#91;my-cloud-name]\/image\/upload\/q_auto,w_1000,c_thumb,g_face,h_500,w_500\/r_100\/cld-sample.jpg 2x\n  \"<\/span>\n  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n\/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>That way, you can use the <code>NgOptimizedImage<\/code> directive with Cloudinary images, including transformations, in your Angular application.<\/p>\n<h2>Conclusion<\/h2>\n<p>The <code>NgOptimizedImage<\/code> directive in Angular provides a convenient way to optimize image loading performance in your Angular applications. While the built-in Cloudinary image loader is limited, you can create a custom loader function that integrates with Cloudinary\u2019s URL API to generate the image URLs with the desired transformations.<\/p>\n<p>Is the custom loader function worth the effort? In most cases, probably not. The Cloudinary Angular SDK provides a much more comprehensive set of features and options for working with Cloudinary images, and is generally easier to use than creating a custom loader function.<\/p>\n<p>However, this exercise can provide a good learning experience and a deeper understanding of how image loading optimization works in Angular, and if you\u2019re an Angular purist or have another reason not to fully use the Cloudinary SDK, the <code>NgOptimizedImage<\/code> directive with a custom Cloudinary loader can be a viable option.<\/p>\n<p><a href=\"https:\/\/cloudinary.com\/\">Sign up<\/a> for a free Cloudinary account today to optimize your visual assets. And if you found this post helpful and would like to learn more, feel free to join the <a href=\"https:\/\/community.cloudinary.com\/\">Cloudinary Community forum<\/a> and its associated <a href=\"https:\/\/discord.com\/invite\/cloudinary\">Discord<\/a>.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":87,"featured_media":35730,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[332,227],"class_list":["post-35728","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-api","tag-performance-optimization"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Using NgOptimizedImage With Cloudinary<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using NgOptimizedImage With Cloudinary\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-09-18T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-16T20:10:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Using NgOptimizedImage With Cloudinary\",\"datePublished\":\"2024-09-18T14:00:00+00:00\",\"dateModified\":\"2025-05-16T20:10:06+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\"},\"wordCount\":4,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA\",\"keywords\":[\"API\",\"Performance Optimization\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2024\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\",\"url\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\",\"name\":\"Using NgOptimizedImage With Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA\",\"datePublished\":\"2024-09-18T14:00:00+00:00\",\"dateModified\":\"2025-05-16T20:10:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using NgOptimizedImage With Cloudinary\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using NgOptimizedImage With Cloudinary","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary","og_locale":"en_US","og_type":"article","og_title":"Using NgOptimizedImage With Cloudinary","og_url":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary","og_site_name":"Cloudinary Blog","article_published_time":"2024-09-18T14:00:00+00:00","article_modified_time":"2025-05-16T20:10:06+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog-jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Using NgOptimizedImage With Cloudinary","datePublished":"2024-09-18T14:00:00+00:00","dateModified":"2025-05-16T20:10:06+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary"},"wordCount":4,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA","keywords":["API","Performance Optimization"],"inLanguage":"en-US","copyrightYear":"2024","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary","url":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary","name":"Using NgOptimizedImage With Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA","datePublished":"2024-09-18T14:00:00+00:00","dateModified":"2025-05-16T20:10:06+00:00","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/using-ngoptimizedimage-with-cloudinary#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using NgOptimizedImage With Cloudinary"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1726270986\/NgOptimizedImage-blog\/NgOptimizedImage-blog.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35728","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=35728"}],"version-history":[{"count":3,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35728\/revisions"}],"predecessor-version":[{"id":37660,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/35728\/revisions\/37660"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/35730"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=35728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=35728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=35728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}