Repository: nuxt/image
Pull request #1096 (2023-11-07 22:44:10)

chore(deps): update devdependency @types/node to ^20.9.0
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped)) | [`^20.8.10` -> `^20.9.0`](https://renovatebot.com/diffs/npm/@types%2fnode/20.8.10/20.9.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.8.10/20.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.8.10/20.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/nuxt/image).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40Ni4wIiwidXBkYXRlZEluVmVyIjoiMzcuNDYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->


cloudflare-pages[bot]: ## Deploying with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>e7efdcc</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>⚡️&nbsp; Build in progress...</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/nuxt-image/6fd8fff1-ab50-469c-b7f5-ed7f2e729b31)

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/nuxt/image/pull/1096?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`cdc8c2e`)](https://app.codecov.io/gh/nuxt/image/commit/cdc8c2e6a2090540367faf1beb5f358702b7576a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt) 89.94% compared to head [(`e7efdcc`)](https://app.codecov.io/gh/nuxt/image/pull/1096?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt) 89.94%.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #1096   +/-   ##
=======================================
  Coverage   89.94%   89.94%           
=======================================
  Files          45       45           
  Lines        3044     3044           
  Branches      335      335           
=======================================
  Hits         2738     2738           
  Misses        305      305           
  Partials        1        1           
```




</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/nuxt/image/pull/1096?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nuxt).


Patch:
diff --git a/docs/content/3.providers/aliyun.md b/docs/content/3.providers/aliyun.md
new file mode 100644
index 0000000..78489b4
--- /dev/null
+++ b/docs/content/3.providers/aliyun.md
@@ -0,0 +1,60 @@
+---
+title: Aliyun
+description: Nuxt Image has first class integration with Aliyun.
+links:
+  - label: Source
+    icon: i-simple-icons-github
+    to: https://github.com/nuxt/image/blob/main/src/runtime/providers/aliyun.ts
+    size: xs
+---
+
+Integration between [Aliyun CDN](https://cdn.console.aliyun.com/) and the image module.
+
+To use this provider you just need to specify the base url (zone) of your service:
+
+```ts [nuxt.config.ts]
+export default defineNuxtConfig({
+  image: {
+    aliyun: {
+      baseURL: "https://that-test.site",
+    },
+  },
+});
+```
+
+**Example:**
+
+```vue
+<NuxtImg
+  provider="aliyun"
+  src="/burger.jpeg"
+  height="300"
+  :modifiers="{ fit: 'contain' }"
+/>
+```
+
+## Options
+
+### `baseURL`
+
+Default: `/`
+
+Your deployment's domain (zone).
+
+## modifiers
+
+**Example:**
+
+```js
+{
+  resize: {
+    fw: 900,
+    fh: 200
+  },
+  rotate:180,
+  bright:50
+  ...
+}
+```
+
+For more modifiers configuration items, see [aliyun cdn docs](https://help.aliyun.com/zh/cdn/user-guide/image-editing/)
diff --git a/docs/package.json b/docs/package.json
index e2d7390..212e044 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -27,7 +27,7 @@
   "devDependencies": {
     "@antfu/eslint-config": "^1.1.0",
     "@nuxt/devtools": "^1.0.0",
-    "@types/node": "^20.8.10",
+    "@types/node": "^20.9.0",
     "eslint": "^8.53.0"
   }
 }
diff --git a/package.json b/package.json
index 9b5d620..ef7877e 100755
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
     "@nuxt/module-builder": "0.5.3",
     "@nuxt/test-utils": "^3.8.1",
     "@nuxtjs/eslint-config-typescript": "^12.1.0",
-    "@types/node": "^20.8.10",
+    "@types/node": "^20.9.0",
     "@vitest/coverage-v8": "0.34.4",
     "@vue/test-utils": "^2.4.1",
     "changelogen": "^0.5.5",
diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts
index b7c18fb..32b62b6 100644
--- a/playground/nuxt.config.ts
+++ b/playground/nuxt.config.ts
@@ -25,6 +25,9 @@ export default defineNuxtConfig({
       unsplash: 'https://images.unsplash.com', // ipx
       blog: '/remote/nuxt-org/blog' // cloudinary
     },
+    aliyun: {
+      baseURL: 'https://assets.yanbot.tech'
+    },
     twicpics: {
       baseURL: 'https://demo.twic.pics/'
     },
diff --git a/playground/providers.ts b/playground/providers.ts
index 4231c0c..683a523 100644
--- a/playground/providers.ts
+++ b/playground/providers.ts
@@ -79,6 +79,36 @@ export const providers: Provider[] = [
       }
     ]
   },
+  // Aliyun
+  {
+    name: 'aliyun',
+    samples: [
+      {
+        src: '/nuxt.png',
+        height: 200
+      },
+      {
+        src: '/nuxt.png',
+        height: 300,
+        width: 300
+      },
+      {
+        src: '/nuxt.png',
+        quality: 50
+      },
+      {
+        src: '/nuxt.png',
+        format: 'webp',
+        quality: 80,
+        modifiers: {
+          resize: {
+            fw: 900,
+            fh: 200
+          }
+        }
+      }
+    ]
+  },
   // Cloudflare
   {
     name: 'cloudflare',
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 962c216..67051f8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -60,8 +60,8 @@ importers:
         specifier: ^12.1.0
         version: 12.1.0(eslint@8.53.0)(typescript@5.2.2)
       '@types/node':
-        specifier: ^20.8.10
-        version: 20.8.10
+        specifier: ^20.9.0
+        version: 20.9.0
       '@vitest/coverage-v8':
         specifier: 0.34.4
         version: 0.34.4(vitest@0.33.0)
@@ -85,7 +85,7 @@ importers:
         version: 1.21.0
       nuxt:
         specifier: ^3.8.1
-        version: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+        version: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
       nuxt-vitest:
         specifier: ^0.11.3
         version: 0.11.3(@vitejs/plugin-vue-jsx@3.0.2)(@vitejs/plugin-vue@4.4.0)(happy-dom@12.10.3)(rollup@3.29.4)(vite@4.5.0)(vitest@0.33.0)(vue-router@4.2.5)(vue@3.3.8)
@@ -139,7 +139,7 @@ importers:
         version: 10.5.0(nuxt@3.8.1)(rollup@3.29.4)(vue@3.3.8)
       nuxt:
         specifier: ^3.8.1
-        version: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+        version: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
       nuxt-og-image:
         specifier: ^2.2.4
         version: 2.2.4(rollup@3.29.4)(vue@3.3.8)
@@ -154,8 +154,8 @@ importers:
         specifier: ^1.0.0
         version: 1.0.0(nuxt@3.8.1)(rollup@3.29.4)(vite@4.5.0)
       '@types/node':
-        specifier: ^20.8.10
-        version: 20.8.10
+        specifier: ^20.9.0
+        version: 20.9.0
       eslint:
         specifier: ^8.53.0
         version: 8.53.0
@@ -167,7 +167,7 @@ importers:
         version: link:..
       nuxt:
         specifier: latest
-        version: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+        version: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
 
   playground:
     devDependencies:
@@ -176,7 +176,7 @@ importers:
         version: link:..
       nuxt:
         specifier: latest
-        version: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+        version: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
 
 packages:
 
@@ -1364,8 +1364,8 @@ packages:
       '@nuxt/kit': 3.8.1(rollup@3.29.4)
       '@nuxt/schema': 3.8.1(rollup@3.29.4)
       execa: 7.2.0
-      nuxt: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
-      vite: 4.5.0(@types/node@20.8.10)
+      nuxt: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+      vite: 4.5.0(@types/node@20.9.0)
     transitivePeerDependencies:
       - rollup
       - supports-color
@@ -1413,7 +1413,7 @@ packages:
       local-pkg: 0.5.0
       magicast: 0.3.0
       nitropack: 2.7.2
-      nuxt: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+      nuxt: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
       nypm: 0.3.3
       ofetch: 1.3.3
       ohash: 1.1.3
@@ -1427,7 +1427,7 @@ packages:
       simple-git: 3.20.0
       sirv: 2.0.3
       unimport: 3.4.0(rollup@3.29.4)
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
       vite-plugin-inspect: 0.7.40(@nuxt/kit@3.8.1)(rollup@3.29.4)(vite@4.5.0)
       vite-plugin-vue-inspector: 4.0.0(vite@4.5.0)
       which: 3.0.1
@@ -1667,7 +1667,7 @@ packages:
       - webpack
     dev: false
 
-  /@nuxt/vite-builder@3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vue-tsc@1.8.22)(vue@3.3.8):
+  /@nuxt/vite-builder@3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vue-tsc@1.8.22)(vue@3.3.8):
     resolution: {integrity: sha512-Ot/twGONxj22T9U4bxp771ibKVFlZxIiYDHY/e6mZsE4Blc0efKo6MzPPPo0W4/tXQbtKKEq41uINN3dMI3mag==}
     engines: {node: ^14.18.0 || >=16.10.0}
     peerDependencies:
@@ -1702,8 +1702,8 @@ packages:
       strip-literal: 1.3.0
       ufo: 1.3.1
       unplugin: 1.5.0
-      vite: 4.5.0(@types/node@20.8.10)
-      vite-node: 0.33.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
+      vite-node: 0.33.0(@types/node@20.9.0)
       vite-plugin-checker: 0.6.2(eslint@8.53.0)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
       vue: 3.3.8(typescript@5.2.2)
       vue-bundle-renderer: 2.0.0
@@ -1981,6 +1981,7 @@ packages:
     dependencies:
       is-glob: 4.0.3
       micromatch: 4.0.5
+      napi-wasm: 1.1.0
     bundledDependencies:
       - napi-wasm
 
@@ -2527,7 +2528,7 @@ packages:
     resolution: {integrity: sha512-sF59BlXtUdzEAL1u0MSvuzWd7PdZvZEtnaVkzX5mjpdWTJ8brG0jUqve3jPCzSzvAKKMHTG8F8o/WMQLtleZdQ==}
     dependencies:
       '@types/jsonfile': 6.1.2
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
     dev: false
 
   /@types/hast@2.3.6:
@@ -2545,7 +2546,7 @@ packages:
   /@types/http-proxy@1.17.13:
     resolution: {integrity: sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==}
     dependencies:
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
 
   /@types/istanbul-lib-coverage@2.0.4:
     resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==}
@@ -2561,7 +2562,7 @@ packages:
   /@types/jsonfile@6.1.2:
     resolution: {integrity: sha512-8t92P+oeW4d/CRQfJaSqEwXujrhH4OEeHRjGU3v1Q8mUS8GPF3yiX26sw4svv6faL2HfBtGTe2xWIoVgN3dy9w==}
     dependencies:
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
     dev: false
 
   /@types/mdast@3.0.13:
@@ -2579,8 +2580,8 @@ packages:
     resolution: {integrity: sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==}
     dev: false
 
-  /@types/node@20.8.10:
-    resolution: {integrity: sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==}
+  /@types/node@20.9.0:
+    resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==}
     dependencies:
       undici-types: 5.26.5
 
@@ -2812,7 +2813,7 @@ packages:
       '@babel/core': 7.23.0
       '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.0)
       '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.0)
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
       vue: 3.3.8(typescript@5.2.2)
     transitivePeerDependencies:
       - supports-color
@@ -2824,7 +2825,7 @@ packages:
       vite: ^4.0.0
       vue: ^3.2.25
     dependencies:
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
       vue: 3.3.8(typescript@5.2.2)
 
   /@vitest/coverage-v8@0.34.4(vitest@0.33.0):
@@ -3181,7 +3182,7 @@ packages:
       '@vueuse/core': 10.5.0(vue@3.3.8)
       '@vueuse/metadata': 10.5.0
       local-pkg: 0.5.0
-      nuxt: 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
+      nuxt: 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22)
       vue-demi: 0.14.6(vue@3.3.8)
     transitivePeerDependencies:
       - '@vue/composition-api'
@@ -3996,7 +3997,7 @@ packages:
     engines: {node: '>=12.13.0'}
     hasBin: true
     dependencies:
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
       escape-string-regexp: 4.0.0
       is-wsl: 2.2.0
       lighthouse-logger: 2.0.1
@@ -6926,7 +6927,7 @@ packages:
     resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
     engines: {node: '>= 10.13.0'}
     dependencies:
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
       merge-stream: 2.0.0
       supports-color: 8.1.1
     dev: false
@@ -8352,6 +8353,9 @@ packages:
     dev: false
     optional: true
 
+  /napi-wasm@1.1.0:
+    resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==}
+
   /natural-compare-lite@1.4.0:
     resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
     dev: true
@@ -8791,7 +8795,7 @@ packages:
       get-port-please: 3.1.1
       perfect-debounce: 1.0.0
       std-env: 3.4.3
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
       vitest: 0.33.0(happy-dom@12.10.3)(playwright@1.39.0)
       vitest-environment-nuxt: 0.11.3(happy-dom@12.10.3)(rollup@3.29.4)(vitest@0.33.0)(vue-router@4.2.5)(vue@3.3.8)
     transitivePeerDependencies:
@@ -8805,7 +8809,7 @@ packages:
       - vue-router
     dev: true
 
-  /nuxt@3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22):
+  /nuxt@3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vite@4.5.0)(vue-tsc@1.8.22):
     resolution: {integrity: sha512-RSGO56Gv0x2f6AXWw4o4GoBaVdsD0qkPCjrX7Ud/jzH3cRJoyYMPuq/9AOLvf2o1ecZWl39j5elqJ4QHmggyOA==}
     engines: {node: ^14.18.0 || >=16.10.0}
     hasBin: true
@@ -8824,8 +8828,8 @@ packages:
       '@nuxt/schema': 3.8.1(rollup@3.29.4)
       '@nuxt/telemetry': 2.5.2(rollup@3.29.4)
       '@nuxt/ui-templates': 1.3.1
-      '@nuxt/vite-builder': 3.8.1(@types/node@20.8.10)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vue-tsc@1.8.22)(vue@3.3.8)
-      '@types/node': 20.8.10
+      '@nuxt/vite-builder': 3.8.1(@types/node@20.9.0)(eslint@8.53.0)(rollup@3.29.4)(typescript@5.2.2)(vue-tsc@1.8.22)(vue@3.3.8)
+      '@types/node': 20.9.0
       '@unhead/dom': 1.8.3
       '@unhead/ssr': 1.8.3
       '@unhead/vue': 1.8.3(vue@3.3.8)
@@ -11762,7 +11766,7 @@ packages:
       vfile-message: 4.0.2
     dev: false
 
-  /vite-node@0.33.0(@types/node@20.8.10):
+  /vite-node@0.33.0(@types/node@20.9.0):
     resolution: {integrity: sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==}
     engines: {node: '>=v14.18.0'}
     hasBin: true
@@ -11772,7 +11776,7 @@ packages:
       mlly: 1.4.2
       pathe: 1.1.1
       picocolors: 1.0.0
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
     transitivePeerDependencies:
       - '@types/node'
       - less
@@ -11829,7 +11833,7 @@ packages:
       strip-ansi: 6.0.1
       tiny-invariant: 1.3.1
       typescript: 5.2.2
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
       vscode-languageclient: 7.0.0
       vscode-languageserver: 7.0.0
       vscode-languageserver-textdocument: 1.0.11
@@ -11855,7 +11859,7 @@ packages:
       open: 9.1.0
       picocolors: 1.0.0
       sirv: 2.0.3
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
     transitivePeerDependencies:
       - rollup
       - supports-color
@@ -11874,11 +11878,11 @@ packages:
       '@vue/compiler-dom': 3.3.8
       kolorist: 1.8.0
       magic-string: 0.30.5
-      vite: 4.5.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
     transitivePeerDependencies:
       - supports-color
 
-  /vite@4.5.0(@types/node@20.8.10):
+  /vite@4.5.0(@types/node@20.9.0):
     resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
@@ -11906,7 +11910,7 @@ packages:
       terser:
         optional: true
     dependencies:
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
       esbuild: 0.18.20
       postcss: 8.4.31
       rollup: 3.29.4
@@ -11985,7 +11989,7 @@ packages:
     dependencies:
       '@types/chai': 4.3.6
       '@types/chai-subset': 1.3.3
-      '@types/node': 20.8.10
+      '@types/node': 20.9.0
       '@vitest/expect': 0.33.0
       '@vitest/runner': 0.33.0
       '@vitest/snapshot': 0.33.0
@@ -12006,8 +12010,8 @@ packages:
       strip-literal: 1.3.0
       tinybench: 2.5.1
       tinypool: 0.6.0
-      vite: 4.5.0(@types/node@20.8.10)
-      vite-node: 0.33.0(@types/node@20.8.10)
+      vite: 4.5.0(@types/node@20.9.0)
+      vite-node: 0.33.0(@types/node@20.9.0)
       why-is-node-running: 2.2.2
     transitivePeerDependencies:
       - less
diff --git a/src/provider.ts b/src/provider.ts
index 8100400..97b880d 100644
--- a/src/provider.ts
+++ b/src/provider.ts
@@ -11,6 +11,7 @@ import { ipxSetup } from './ipx'
 
 // Please add new providers alphabetically to the list below
 const BuiltInProviders = [
+  'aliyun',
   'cloudflare',
   'cloudimage',
   'cloudinary',
diff --git a/src/runtime/providers/aliyun.ts b/src/runtime/providers/aliyun.ts
new file mode 100644
index 0000000..875af0d
--- /dev/null
+++ b/src/runtime/providers/aliyun.ts
@@ -0,0 +1,48 @@
+import { joinURL } from 'ufo'
+import type { ProviderGetImage } from '@nuxt/image'
+import { createOperationsGenerator } from '#image'
+
+const operationsGenerator = createOperationsGenerator({
+  joinWith: '/',
+  formatter: (key: any, value: any) => {
+    if (typeof value === 'object') {
+      return `${key},${Object.entries(value).map(([k, v]) => `${k}_${v}`).join(',')}`
+    }
+    return `${key},${value}`
+  }
+})
+
+export const getImage: ProviderGetImage = (
+  src,
+  { modifiers = {}, baseURL } = {}
+) => {
+  if (!baseURL) {
+    // also support runtime config
+    baseURL = useRuntimeConfig().public.siteUrl
+  }
+  const _modifiers = { ...modifiers }
+  const { resize, width, height, quality } = _modifiers
+
+  let resizeValue = {}
+  if (width && height) {
+    resizeValue = { fw: width, fh: height }
+  } else if (width) {
+    resizeValue = { w: width }
+  } else if (height) {
+    resizeValue = { h: height }
+  }
+  if (!resize && Object.keys(resizeValue).length) {
+    _modifiers.resize = resizeValue
+  }
+  delete _modifiers.width
+  delete _modifiers.height
+
+  if (quality) {
+    _modifiers.quality = `Q_${quality}`
+  }
+
+  const operations = operationsGenerator(_modifiers)
+  return {
+    url: joinURL(baseURL, src + (operations ? '?image_process=' + operations : ''))
+  }
+}


Test patch:
diff --git a/test/e2e/__snapshots__/no-ssr.test.ts.snap b/test/e2e/__snapshots__/no-ssr.test.ts.snap
index 9e120d8..8656ba7 100644
--- a/test/e2e/__snapshots__/no-ssr.test.ts.snap
+++ b/test/e2e/__snapshots__/no-ssr.test.ts.snap
@@ -1,5 +1,23 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
+exports[`browser (ssr: false) > aliyun should render images 1`] = `
+[
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,h_200",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_300,fh_300",
+  "https://assets.yanbot.tech/nuxt.png?image_process=quality,Q_50",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_900,fh_200/format,webp/quality,Q_80",
+]
+`;
+
+exports[`browser (ssr: false) > aliyun should render images 2`] = `
+[
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,h_200",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_300,fh_300",
+  "https://assets.yanbot.tech/nuxt.png?image_process=quality,Q_50",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_900,fh_200/format,webp/quality,Q_80",
+]
+`;
+
 exports[`browser (ssr: false) > cloudflare should render images 1`] = `
 [
   "https://that-test.site/cdn-cgi/image/h=300,fit=contain/https://s3.that-test.site/burger.jpeg",
@@ -334,6 +352,19 @@ exports[`browser (ssr: false) > sirv should render images 2`] = `
 ]
 `;
 
+exports[`browser (ssr: false) > sirv should render images 3`] = `
+[
+  "https://demo.sirv.com/test.png?w=750&q=75",
+  "https://demo.sirv.com/harris-large.jpg?w=500&format=png",
+  "https://demo.sirv.com/lacoste.jpg?crop.type=trim&w=500&q=95",
+  "https://demo.sirv.com/look-big.jpg?h=500&scale.option=fit",
+  "https://demo.sirv.com/look-big.jpg?crop.type=face&h=500",
+  "https://demo.sirv.com/QW.pdf?page=1&w=500",
+  "https://demo.sirv.com/look-big.jpg?text=Hello&text.align=center&text.position.gravity=south&text.background.color=ffff&text.size=60&text.font.family=Arial&text.color=white&h=500",
+  "https://demo.sirv.com/t-shirt-man.jpg?watermark=/watermark-v1.png&watermark.position=center&watermark.scale.width=30%&h=500",
+]
+`;
+
 exports[`browser (ssr: false) > storyblok should render images 1`] = `
 [
   "https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg",
@@ -381,6 +412,16 @@ exports[`browser (ssr: false) > strapi should render images 2`] = `
 ]
 `;
 
+exports[`browser (ssr: false) > strapi should render images 3`] = `
+[
+  "http://localhost:1337/uploads/4d9z1eiyo2gmf6gd7xhp_823ae510e8.png",
+  "http://localhost:1337/uploads/thumbnail_4d9z1eiyo2gmf6gd7xhp_823ae510e8.png",
+  "http://localhost:1337/uploads/small_4d9z1eiyo2gmf6gd7xhp_823ae510e8.png",
+  "http://localhost:1337/uploads/medium_4d9z1eiyo2gmf6gd7xhp_823ae510e8.png",
+  "http://localhost:1337/uploads/large_4d9z1eiyo2gmf6gd7xhp_823ae510e8.png",
+]
+`;
+
 exports[`browser (ssr: false) > twicpics should render images 1`] = `
 [
   "https://demo.twic.pics/football.jpg",
diff --git a/test/e2e/__snapshots__/ssr.test.ts.snap b/test/e2e/__snapshots__/ssr.test.ts.snap
index 64d85a9..1dd87c0 100644
--- a/test/e2e/__snapshots__/ssr.test.ts.snap
+++ b/test/e2e/__snapshots__/ssr.test.ts.snap
@@ -1,5 +1,23 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
+exports[`browser (ssr: true) > aliyun should render images 1`] = `
+[
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,h_200",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_300,fh_300",
+  "https://assets.yanbot.tech/nuxt.png?image_process=quality,Q_50",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_900,fh_200/format,webp/quality,Q_80",
+]
+`;
+
+exports[`browser (ssr: true) > aliyun should render images 2`] = `
+[
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,h_200",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_300,fh_300",
+  "https://assets.yanbot.tech/nuxt.png?image_process=quality,Q_50",
+  "https://assets.yanbot.tech/nuxt.png?image_process=resize,fw_900,fh_200/format,webp/quality,Q_80",
+]
+`;
+
 exports[`browser (ssr: true) > cloudflare should render images 1`] = `
 [
   "https://that-test.site/cdn-cgi/image/h=300,fit=contain/https://s3.that-test.site/burger.jpeg",
@@ -308,6 +326,24 @@ exports[`browser (ssr: true) > sanity should render images 2`] = `
 ]
 `;
 
+exports[`browser (ssr: true) > should emit load and error events 1`] = `
+[
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=600&h=900",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=200&h=900",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=600&h=200",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=200&h=200&fit=crop",
+]
+`;
+
+exports[`browser (ssr: true) > should emit load and error events 2`] = `
+[
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=600&h=900",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=200&h=900",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=600&h=200",
+  "https://images.prismic.io/200629-sms-hoy/f596a543-d593-4296-9abd-3d3ac15f1e39_ray-hennessy-mpw37yXc_WQ-unsplash.jpg?auto=compress,format&w=200&h=200&fit=crop",
+]
+`;
+
 exports[`browser (ssr: true) > sirv should render images 1`] = `
 [
   "https://demo.sirv.com/test.png?w=750&q=75",
@@ -509,6 +545,12 @@ exports[`browser (ssr: true) > vercel should render images 2`] = `
 ]
 `;
 
+exports[`browser (ssr: true) > vercel should render images 3`] = `
+[
+  "https://image-component.nextjs.gallery/_next/image?url=/colors.jpg&w=750&q=75",
+]
+`;
+
 exports[`browser (ssr: true) > wagtail should render images 1`] = `
 [
   "https://cms.demo.nypr.digital/images/329944/original|format-webp|webpquality-70",
diff --git a/test/providers.ts b/test/providers.ts
index 4bc3735..2be396a 100644
--- a/test/providers.ts
+++ b/test/providers.ts
@@ -3,6 +3,7 @@ export const images = [
     args: ['/test.png', {}],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/_/test.png' },
+    aliyun: { url: '/test.png' },
     cloudflare: { url: '/test.png' },
     cloudinary: { url: '/f_auto,q_auto/test' },
     twicpics: { url: '/test.png' },
@@ -31,6 +32,7 @@ export const images = [
     args: ['/test.png', { width: 200 }],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/w_200/test.png' },
+    aliyun: { url: '/test.png?image_process=resize,w_200' },
     cloudflare: { url: '/cdn-cgi/image/w=200/test.png' },
     cloudinary: { url: '/f_auto,q_auto,w_200/test' },
     twicpics: { url: '/test.png?twic=v1/cover=200x-' },
@@ -59,6 +61,7 @@ export const images = [
     args: ['/test.png', { height: 200 }],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/h_200/test.png' },
+    aliyun: { url: '/test.png?image_process=resize,h_200' },
     cloudflare: { url: '/cdn-cgi/image/h=200/test.png' },
     cloudinary: { url: '/f_auto,q_auto,h_200/test' },
     twicpics: { url: '/test.png?twic=v1/cover=-x200' },
@@ -87,6 +90,7 @@ export const images = [
     args: ['/test.png', { width: 200, height: 200 }],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/s_200x200/test.png' },
+    aliyun: { url: '/test.png?image_process=resize,fw_200,fh_200' },
     cloudflare: { url: '/cdn-cgi/image/w=200,h=200/test.png' },
     cloudinary: { url: '/f_auto,q_auto,w_200,h_200/test' },
     twicpics: { url: '/test.png?twic=v1/cover=200x200' },
@@ -115,6 +119,7 @@ export const images = [
     args: ['/test.png', { width: 200, height: 200, fit: 'contain' }],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/fit_contain&s_200x200/test.png' },
+    aliyun: { url: '/test.png?image_process=fit,contain/resize,fw_200,fh_200' },
     cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain/test.png' },
     cloudinary: { url: '/f_auto,q_auto,w_200,h_200,c_scale/test' },
     twicpics: { url: '/test.png?twic=v1/inside=200x200' },
@@ -143,6 +148,7 @@ export const images = [
     args: ['/test.png', { width: 200, height: 200, fit: 'contain', format: 'jpeg' }],
     none: { url: '/test.png' },
     ipx: { url: '/_ipx/fit_contain&f_jpeg&s_200x200/test.png' },
+    aliyun: { url: '/test.png?image_process=fit,contain/format,jpeg/resize,fw_200,fh_200' },
     cloudflare: { url: '/cdn-cgi/image/w=200,h=200,fit=contain,f=jpeg/test.png' },
     cloudinary: { url: '/f_jpg,q_auto,w_200,h_200,c_scale/test' },
     twicpics: { url: '/test.png?twic=v1/output=jpeg/inside=200x200' },
diff --git a/test/unit/providers.test.ts b/test/unit/providers.test.ts
index f0700ab..4e807ea 100644
--- a/test/unit/providers.test.ts
+++ b/test/unit/providers.test.ts
@@ -7,6 +7,7 @@ import { images } from '../providers'
 import { cleanDoubleSlashes } from '#image/utils'
 import * as ipx from '#image/providers/ipx'
 import * as none from '~/src/runtime/providers/none'
+import * as aliyun from '#image/providers/aliyun'
 import * as cloudflare from '#image/providers/cloudflare'
 import * as cloudinary from '#image/providers/cloudinary'
 import * as twicpics from '#image/providers/twicpics'
@@ -69,7 +70,16 @@ describe('Providers', () => {
       url: '/_ipx/_/images/test.png'
     })
   })
-
+  it('aliyun', () => {
+    const providerOptions = {
+      baseURL: '/'
+    }
+    for (const image of images) {
+      const [src, modifiers] = image.args
+      const generated = aliyun.getImage(src, { modifiers, ...providerOptions }, emptyContext)
+      expect(generated).toMatchObject(image.aliyun)
+    }
+  })
   it('cloudflare', () => {
     const providerOptions = {
       baseURL: '/'