@smoothcdn/loader 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astro.d.ts +5 -0
- package/dist/astro.d.ts.map +1 -0
- package/dist/astro.js +3 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +78 -0
- package/dist/core/createLoader.d.ts +3 -0
- package/dist/core/createLoader.d.ts.map +1 -0
- package/dist/core/createLoader.js +24 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/loaders/fetch.d.ts +2 -0
- package/dist/core/loaders/fetch.d.ts.map +1 -0
- package/dist/core/loaders/fetch.js +10 -0
- package/dist/core/loaders/image.d.ts +2 -0
- package/dist/core/loaders/image.d.ts.map +1 -0
- package/dist/core/loaders/image.js +12 -0
- package/dist/core/loaders/script.d.ts +2 -0
- package/dist/core/loaders/script.d.ts.map +1 -0
- package/dist/core/loaders/script.js +14 -0
- package/dist/core/loaders/style.d.ts +2 -0
- package/dist/core/loaders/style.d.ts.map +1 -0
- package/dist/core/loaders/style.js +14 -0
- package/dist/core/runtime.d.ts +2 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +7 -0
- package/dist/core/types.d.ts +72 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +50 -0
- package/dist/framework/shared.d.ts +7 -0
- package/dist/framework/shared.d.ts.map +1 -0
- package/dist/framework/shared.js +8 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/next/CDNImage.d.ts +8 -0
- package/dist/next/CDNImage.d.ts.map +1 -0
- package/dist/next/CDNImage.js +6 -0
- package/dist/next/Script.d.ts +7 -0
- package/dist/next/Script.d.ts.map +1 -0
- package/dist/next/Script.js +7 -0
- package/dist/next/Style.d.ts +6 -0
- package/dist/next/Style.d.ts.map +1 -0
- package/dist/next/Style.js +7 -0
- package/dist/next/index.d.ts +7 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +6 -0
- package/dist/nuxt.d.ts +6 -0
- package/dist/nuxt.d.ts.map +1 -0
- package/dist/nuxt.js +4 -0
- package/dist/react/CDNAudio.d.ts +14 -0
- package/dist/react/CDNAudio.d.ts.map +1 -0
- package/dist/react/CDNAudio.js +5 -0
- package/dist/react/CDNImage.d.ts +11 -0
- package/dist/react/CDNImage.d.ts.map +1 -0
- package/dist/react/CDNImage.js +28 -0
- package/dist/react/CDNVideo.d.ts +12 -0
- package/dist/react/CDNVideo.d.ts.map +1 -0
- package/dist/react/CDNVideo.js +5 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +7 -0
- package/dist/react/useFetch.d.ts +6 -0
- package/dist/react/useFetch.d.ts.map +1 -0
- package/dist/react/useFetch.js +14 -0
- package/dist/react/useImage.d.ts +6 -0
- package/dist/react/useImage.d.ts.map +1 -0
- package/dist/react/useImage.js +13 -0
- package/dist/react/useScript.d.ts +6 -0
- package/dist/react/useScript.d.ts.map +1 -0
- package/dist/react/useScript.js +13 -0
- package/dist/react/useStyle.d.ts +3 -0
- package/dist/react/useStyle.d.ts.map +1 -0
- package/dist/react/useStyle.js +7 -0
- package/dist/remix.d.ts +11 -0
- package/dist/remix.d.ts.map +1 -0
- package/dist/remix.js +8 -0
- package/dist/sveltekit.d.ts +19 -0
- package/dist/sveltekit.d.ts.map +1 -0
- package/dist/sveltekit.js +15 -0
- package/dist/types-generator.d.ts +20 -0
- package/dist/types-generator.d.ts.map +1 -0
- package/dist/types-generator.js +209 -0
- package/dist/vue/CDNImage.d.ts +39 -0
- package/dist/vue/CDNImage.d.ts.map +1 -0
- package/dist/vue/CDNImage.js +26 -0
- package/dist/vue/index.d.ts +7 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +5 -0
- package/dist/vue/useCdnFetch.d.ts +6 -0
- package/dist/vue/useCdnFetch.d.ts.map +1 -0
- package/dist/vue/useCdnFetch.js +14 -0
- package/dist/vue/useCdnScript.d.ts +3 -0
- package/dist/vue/useCdnScript.d.ts.map +1 -0
- package/dist/vue/useCdnScript.js +7 -0
- package/dist/vue/useCdnStyle.d.ts +3 -0
- package/dist/vue/useCdnStyle.d.ts.map +1 -0
- package/dist/vue/useCdnStyle.js +7 -0
- package/dist/vue/useFetch.d.ts +6 -0
- package/dist/vue/useFetch.d.ts.map +1 -0
- package/dist/vue/useFetch.js +19 -0
- package/dist/vue/useImage.d.ts +6 -0
- package/dist/vue/useImage.d.ts.map +1 -0
- package/dist/vue/useImage.js +18 -0
- package/package.json +93 -0
- package/readme.md +356 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LoaderAssetMap, LoaderDefaultAssetMap, LoaderEndpointPath, LoaderVariantSlug } from "../core/types.js";
|
|
2
|
+
export declare function useFetch<T = unknown, TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>(assetPath: LoaderEndpointPath<TAssets>, variantSlug?: LoaderVariantSlug<TAssets>, init?: RequestInit): {
|
|
3
|
+
data: [T | null] extends [import("vue").Ref<any, any>] ? import("@vue/shared").IfAny<import("vue").Ref<any, any> & T, import("vue").Ref<import("vue").Ref<any, any> & T, import("vue").Ref<any, any> & T>, import("vue").Ref<any, any> & T> : import("vue").Ref<import("vue").UnwrapRef<T> | null, T | import("vue").UnwrapRef<T> | null>;
|
|
4
|
+
error: import("vue").Ref<Error | null, Error | null>;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=useFetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFetch.d.ts","sourceRoot":"","sources":["../../src/vue/useFetch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEnH,wBAAgB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAC7G,SAAS,EAAE,kBAAkB,CAAC,OAAO,CAAC,EACtC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,EACxC,IAAI,CAAC,EAAE,WAAW;;;EAmBrB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ref, watchEffect } from "vue";
|
|
2
|
+
import { createLoader } from "../core/createLoader.js";
|
|
3
|
+
export function useFetch(assetPath, variantSlug, init) {
|
|
4
|
+
const data = ref(null);
|
|
5
|
+
const error = ref(null);
|
|
6
|
+
watchEffect(() => {
|
|
7
|
+
createLoader()
|
|
8
|
+
.fetch(assetPath, variantSlug, init)
|
|
9
|
+
.then((response) => response.json())
|
|
10
|
+
.then((payload) => {
|
|
11
|
+
data.value = payload;
|
|
12
|
+
error.value = null;
|
|
13
|
+
})
|
|
14
|
+
.catch((currentError) => {
|
|
15
|
+
error.value = currentError;
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
return { data, error };
|
|
19
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LoaderAssetMap, LoaderDefaultAssetMap, LoaderImagePath, LoaderVariantSlug } from "../core/types.js";
|
|
2
|
+
export declare function useImage<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>(assetPath: LoaderImagePath<TAssets>, variantSlug?: LoaderVariantSlug<TAssets>): {
|
|
3
|
+
image: import("vue").Ref<HTMLImageElement | null, HTMLImageElement | null>;
|
|
4
|
+
error: import("vue").Ref<Error | null, Error | null>;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=useImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useImage.d.ts","sourceRoot":"","sources":["../../src/vue/useImage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,EACnC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC;;;EAkB3C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ref, watchEffect } from "vue";
|
|
2
|
+
import { createLoader } from "../core/createLoader.js";
|
|
3
|
+
export function useImage(assetPath, variantSlug) {
|
|
4
|
+
const image = ref(null);
|
|
5
|
+
const error = ref(null);
|
|
6
|
+
watchEffect(() => {
|
|
7
|
+
createLoader()
|
|
8
|
+
.image(assetPath, variantSlug)
|
|
9
|
+
.then((loadedImage) => {
|
|
10
|
+
image.value = loadedImage;
|
|
11
|
+
error.value = null;
|
|
12
|
+
})
|
|
13
|
+
.catch((currentError) => {
|
|
14
|
+
error.value = currentError;
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
return { image, error };
|
|
18
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smoothcdn/loader",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Smooth CDN framework-aware asset loader",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./core": {
|
|
17
|
+
"types": "./dist/core/index.d.ts",
|
|
18
|
+
"import": "./dist/core/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./react": {
|
|
21
|
+
"types": "./dist/react/index.d.ts",
|
|
22
|
+
"import": "./dist/react/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./vue": {
|
|
25
|
+
"types": "./dist/vue/index.d.ts",
|
|
26
|
+
"import": "./dist/vue/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./next": {
|
|
29
|
+
"types": "./dist/next/index.d.ts",
|
|
30
|
+
"import": "./dist/next/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./nuxt": {
|
|
33
|
+
"types": "./dist/nuxt.d.ts",
|
|
34
|
+
"import": "./dist/nuxt.js"
|
|
35
|
+
},
|
|
36
|
+
"./astro": {
|
|
37
|
+
"types": "./dist/astro.d.ts",
|
|
38
|
+
"import": "./dist/astro.js"
|
|
39
|
+
},
|
|
40
|
+
"./sveltekit": {
|
|
41
|
+
"types": "./dist/sveltekit.d.ts",
|
|
42
|
+
"import": "./dist/sveltekit.js"
|
|
43
|
+
},
|
|
44
|
+
"./remix": {
|
|
45
|
+
"types": "./dist/remix.d.ts",
|
|
46
|
+
"import": "./dist/remix.js"
|
|
47
|
+
},
|
|
48
|
+
"./types-generator": {
|
|
49
|
+
"types": "./dist/types-generator.d.ts",
|
|
50
|
+
"import": "./dist/types-generator.js"
|
|
51
|
+
},
|
|
52
|
+
"./package.json": {
|
|
53
|
+
"default": "./package.json"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
"files": ["dist"],
|
|
58
|
+
"sideEffects": false,
|
|
59
|
+
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsc",
|
|
62
|
+
"dev": "tsc --watch"
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
67
|
+
"vue": "^3.0.0",
|
|
68
|
+
"next": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"react": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"vue": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"next": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
"devDependencies": {
|
|
83
|
+
"@types/node": "^25.6.0",
|
|
84
|
+
"typescript": "^5.3.0",
|
|
85
|
+
|
|
86
|
+
"react": "^18.2.0",
|
|
87
|
+
"@types/react": "^18.2.0",
|
|
88
|
+
|
|
89
|
+
"vue": "^3.4.0",
|
|
90
|
+
|
|
91
|
+
"next": "^13.5.0"
|
|
92
|
+
}
|
|
93
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# @smoothcdn/loader
|
|
2
|
+
|
|
3
|
+
Framework-aware loader for Smooth CDN assets.
|
|
4
|
+
|
|
5
|
+
`@smoothcdn/loader` reads the same `.scdn.json` project configuration used by the Smooth CDN CLI and gives your app typed helpers and ready-to-use components for loading images, scripts, styles and fetchable assets from Smooth CDN.
|
|
6
|
+
|
|
7
|
+
It includes:
|
|
8
|
+
|
|
9
|
+
- a framework-neutral core loader,
|
|
10
|
+
- React and Next.js components/hooks for images, audio, video, scripts and styles,
|
|
11
|
+
- Vue and Nuxt helpers,
|
|
12
|
+
- Astro, SvelteKit and Remix entrypoints,
|
|
13
|
+
- TypeScript asset typing generated from `.scdn.json`.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @smoothcdn/loader
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Place `.scdn.json` in the root of your project, generate the loader module, then call its bootstrap once from your app entrypoint.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
scdn types
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { configureSmoothCDN } from "./smoothcdn-loader";
|
|
31
|
+
|
|
32
|
+
configureSmoothCDN();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
After that, import components and helpers directly from `@smoothcdn/loader`. The generated file adds project asset types globally, so `assetPath` suggestions work without importing a project-specific wrapper in every component.
|
|
36
|
+
|
|
37
|
+
The loader expects the standard Smooth CDN config shape:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"userSlug": "smoothcdn",
|
|
42
|
+
"projectSlug": "web",
|
|
43
|
+
"customSubdomain": "web",
|
|
44
|
+
"sources": ["./public/*", "./.next/static/**/*"],
|
|
45
|
+
"excludes": ["./public/*.txt", "./.next/static/**/*.map"],
|
|
46
|
+
"replacePath": {
|
|
47
|
+
"/.next/": "/_next/"
|
|
48
|
+
},
|
|
49
|
+
"imageVariants": {
|
|
50
|
+
"320": 320,
|
|
51
|
+
"480": 480,
|
|
52
|
+
"640": 640,
|
|
53
|
+
"768": 768,
|
|
54
|
+
"960": 960,
|
|
55
|
+
"1200": 1200
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use `replacePath` when files are collected from one location but should be referenced from another public path. `replacePaths` is also accepted as an alias.
|
|
61
|
+
|
|
62
|
+
For projects with `customSubdomain`, URLs are built from the subdomain root:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
buildUrl("/public/logo.svg");
|
|
66
|
+
// https://web.smoothcdn.com/public/logo.svg
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Without `customSubdomain`, URLs use the standard Smooth CDN path:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
buildUrl("/public/logo.svg");
|
|
73
|
+
// https://cdn.smoothcdn.com/<userSlug>/<projectSlug>/<version>/<variant>/public/logo.svg
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## TypeScript Asset Typing
|
|
77
|
+
|
|
78
|
+
The package exposes a generator that reads root `.scdn.json`, scans configured sources, applies `excludes` and `replacePath`, and writes a TypeScript module with project asset types.
|
|
79
|
+
|
|
80
|
+
Generate the types with the Smooth CDN CLI:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
scdn types
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The command should generate:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
smoothcdn-loader.ts
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
To write the file somewhere else:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
scdn types --output src/smoothcdn-loader.ts
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Once the generated module is included in your app bootstrap, helpers and components imported from `@smoothcdn/loader` use those generated asset types automatically:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { createLoader } from "@smoothcdn/loader";
|
|
102
|
+
|
|
103
|
+
const loader = createLoader();
|
|
104
|
+
|
|
105
|
+
loader.url("/public/logo.svg");
|
|
106
|
+
loader.image("/public/logo.svg");
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Commit `smoothcdn-loader.ts` with your app if you want asset-path autocomplete to work without regenerating it on every install. The `.scdn` directory can stay ignored.
|
|
110
|
+
|
|
111
|
+
```gitignore
|
|
112
|
+
.scdn/*
|
|
113
|
+
!.scdn/
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Core
|
|
117
|
+
|
|
118
|
+
Use the core loader in any JavaScript or TypeScript runtime that has the required browser APIs.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { createLoader } from "@smoothcdn/loader";
|
|
122
|
+
|
|
123
|
+
const loader = createLoader();
|
|
124
|
+
|
|
125
|
+
const logoUrl = loader.url("/public/logo.svg");
|
|
126
|
+
|
|
127
|
+
await loader.script("/public/app.js");
|
|
128
|
+
await loader.style("/public/app.css");
|
|
129
|
+
await loader.image("/public/logo.svg");
|
|
130
|
+
|
|
131
|
+
const response = await loader.fetch("/public/data.json");
|
|
132
|
+
const data = await response.json();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## React
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { CDNImage, useFetch, useImage } from "@smoothcdn/loader/react";
|
|
139
|
+
|
|
140
|
+
export function Logo() {
|
|
141
|
+
return (
|
|
142
|
+
<CDNImage
|
|
143
|
+
assetPath="/public/logo.svg"
|
|
144
|
+
alt="Smooth CDN"
|
|
145
|
+
width={40}
|
|
146
|
+
height={40}
|
|
147
|
+
/>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function Preview() {
|
|
152
|
+
const { image, error } = useImage("/public/logo.svg");
|
|
153
|
+
|
|
154
|
+
if (error) return null;
|
|
155
|
+
return <span>{image ? "Loaded" : "Loading"}</span>;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function DataBlock() {
|
|
159
|
+
const { data } = useFetch("/public/data.json");
|
|
160
|
+
|
|
161
|
+
return <pre>{JSON.stringify(data, null, 2)}</pre>;
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Next.js
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { Script, Style } from "@smoothcdn/loader/next";
|
|
169
|
+
import { CDNAudio, CDNImage, CDNVideo } from "@smoothcdn/loader/react";
|
|
170
|
+
|
|
171
|
+
export default function Page() {
|
|
172
|
+
return (
|
|
173
|
+
<>
|
|
174
|
+
<Style assetPath="/public/app.css" />
|
|
175
|
+
<Script assetPath="/public/app.js" />
|
|
176
|
+
|
|
177
|
+
<CDNImage
|
|
178
|
+
assetPath="/public/logo.svg"
|
|
179
|
+
alt="Smooth CDN"
|
|
180
|
+
width={80}
|
|
181
|
+
height={80}
|
|
182
|
+
/>
|
|
183
|
+
|
|
184
|
+
<CDNAudio
|
|
185
|
+
assetPath="/public/intro.mp3"
|
|
186
|
+
controls
|
|
187
|
+
/>
|
|
188
|
+
|
|
189
|
+
<CDNVideo
|
|
190
|
+
assetPath="/public/demo.mp4"
|
|
191
|
+
posterAssetPath="/public/demo-poster.jpg"
|
|
192
|
+
controls
|
|
193
|
+
width={1280}
|
|
194
|
+
height={720}
|
|
195
|
+
/>
|
|
196
|
+
</>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Vue
|
|
202
|
+
|
|
203
|
+
```vue
|
|
204
|
+
<script setup lang="ts">
|
|
205
|
+
import { CDNImage, useImage } from "@smoothcdn/loader/vue";
|
|
206
|
+
|
|
207
|
+
const { image, error } = useImage("/public/logo.svg");
|
|
208
|
+
</script>
|
|
209
|
+
|
|
210
|
+
<template>
|
|
211
|
+
<CDNImage
|
|
212
|
+
asset-path="/public/logo.svg"
|
|
213
|
+
alt="Smooth CDN"
|
|
214
|
+
width="80"
|
|
215
|
+
height="80"
|
|
216
|
+
/>
|
|
217
|
+
|
|
218
|
+
<span v-if="image">Loaded</span>
|
|
219
|
+
<span v-if="error">Failed</span>
|
|
220
|
+
</template>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Nuxt
|
|
224
|
+
|
|
225
|
+
Create a plugin that configures the loader once.
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
// plugins/smoothcdn.ts
|
|
229
|
+
import { configureSmoothCDN } from "../smoothcdn-loader";
|
|
230
|
+
|
|
231
|
+
export default defineNuxtPlugin(() => {
|
|
232
|
+
configureSmoothCDN();
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Use the Nuxt entrypoint in components or composables:
|
|
237
|
+
|
|
238
|
+
```vue
|
|
239
|
+
<script setup lang="ts">
|
|
240
|
+
import { createSmoothLoader, CDNImage } from "@smoothcdn/loader/nuxt";
|
|
241
|
+
|
|
242
|
+
const { url } = createSmoothLoader();
|
|
243
|
+
const logoUrl = url("/public/logo.svg");
|
|
244
|
+
</script>
|
|
245
|
+
|
|
246
|
+
<template>
|
|
247
|
+
<CDNImage
|
|
248
|
+
asset-path="/public/logo.svg"
|
|
249
|
+
alt="Smooth CDN"
|
|
250
|
+
width="80"
|
|
251
|
+
height="80"
|
|
252
|
+
/>
|
|
253
|
+
|
|
254
|
+
<a :href="logoUrl">Open logo</a>
|
|
255
|
+
</template>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Astro
|
|
259
|
+
|
|
260
|
+
```astro
|
|
261
|
+
---
|
|
262
|
+
import { createSmoothLoader } from "@smoothcdn/loader/astro";
|
|
263
|
+
|
|
264
|
+
const { url } = createSmoothLoader();
|
|
265
|
+
const logoUrl = url("/public/logo.svg");
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
<img src={logoUrl} alt="Smooth CDN" width="80" height="80" />
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## SvelteKit
|
|
272
|
+
|
|
273
|
+
Initialize the loader in a shared module:
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
// src/lib/smoothcdn.ts
|
|
277
|
+
import { createSmoothLoader } from "@smoothcdn/loader/sveltekit";
|
|
278
|
+
|
|
279
|
+
export const smoothcdn = createSmoothLoader();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Use it in a Svelte component:
|
|
283
|
+
|
|
284
|
+
```svelte
|
|
285
|
+
<script lang="ts">
|
|
286
|
+
import { smoothcdn } from "$lib/smoothcdn";
|
|
287
|
+
|
|
288
|
+
const logoUrl = smoothcdn.url("/public/logo.svg");
|
|
289
|
+
</script>
|
|
290
|
+
|
|
291
|
+
<img src={logoUrl} alt="Smooth CDN" width="80" height="80" />
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Or create a typed `load` helper:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import { createAssetLoad } from "@smoothcdn/loader/sveltekit";
|
|
298
|
+
|
|
299
|
+
export const load = createAssetLoad({
|
|
300
|
+
assetPath: "/public/logo.svg",
|
|
301
|
+
depends: ["smoothcdn:logo"],
|
|
302
|
+
cacheControl: "public, max-age=3600"
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Remix
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
import { createSmoothLoader, createStyleLink } from "@smoothcdn/loader/remix";
|
|
310
|
+
|
|
311
|
+
const { url } = createSmoothLoader();
|
|
312
|
+
|
|
313
|
+
export const links = () => [
|
|
314
|
+
createStyleLink("/public/app.css")
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
export default function Route() {
|
|
318
|
+
return (
|
|
319
|
+
<img
|
|
320
|
+
src={url("/public/logo.svg")}
|
|
321
|
+
alt="Smooth CDN"
|
|
322
|
+
width={80}
|
|
323
|
+
height={80}
|
|
324
|
+
/>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Generated Image Variants
|
|
330
|
+
|
|
331
|
+
If your `.scdn.json` contains `imageVariants`, generated type output also includes those labels as valid variants.
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
const loader = createLoader();
|
|
335
|
+
|
|
336
|
+
loader.image("/public/logo.png", "640");
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
For responsive images, use the package component with `responsive`. It builds `srcSet` from `imageVariants` in `.scdn.json` unless you pass `variants` explicitly.
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
import { CDNImage } from "@smoothcdn/loader/react";
|
|
343
|
+
|
|
344
|
+
export function HeroImage() {
|
|
345
|
+
return (
|
|
346
|
+
<CDNImage
|
|
347
|
+
responsive
|
|
348
|
+
assetPath="/public/hero.png"
|
|
349
|
+
alt="Hero"
|
|
350
|
+
width={1536}
|
|
351
|
+
height={1024}
|
|
352
|
+
sizes="(min-width: 1024px) 50vw, 100vw"
|
|
353
|
+
/>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
```
|