Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1f808d079 | ||
|
|
a8a632e1b0 |
Vendored
+1
@@ -7,3 +7,4 @@
|
|||||||
*/
|
*/
|
||||||
export { RenderBlocks } from '../modules/blocks/index.js';
|
export { RenderBlocks } from '../modules/blocks/index.js';
|
||||||
export type { BlockComponentMap, BlockData, EnhanceProps, RenderBlocksProps, } from '../modules/blocks/index.js';
|
export type { BlockComponentMap, BlockData, EnhanceProps, RenderBlocksProps, } from '../modules/blocks/index.js';
|
||||||
|
export { MediaPreconnect } from '../modules/storage/MediaPreconnect.js';
|
||||||
|
|||||||
Vendored
+1
@@ -5,5 +5,6 @@
|
|||||||
* lives here rather than in the main package entry to keep React out of the
|
* lives here rather than in the main package entry to keep React out of the
|
||||||
* server-config bundle.
|
* server-config bundle.
|
||||||
*/ export { RenderBlocks } from '../modules/blocks/index.js';
|
*/ export { RenderBlocks } from '../modules/blocks/index.js';
|
||||||
|
export { MediaPreconnect } from '../modules/storage/MediaPreconnect.js';
|
||||||
|
|
||||||
//# sourceMappingURL=rsc.js.map
|
//# sourceMappingURL=rsc.js.map
|
||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["/**\n * Entry point: ipal-kit/rsc\n *\n * Server-component exports. RenderBlocks is a React Server Component, so it\n * lives here rather than in the main package entry to keep React out of the\n * server-config bundle.\n */\nexport { RenderBlocks } from '../modules/blocks/index.js'\nexport type {\n BlockComponentMap,\n BlockData,\n EnhanceProps,\n RenderBlocksProps,\n} from '../modules/blocks/index.js'\n"],"names":["RenderBlocks"],"mappings":"AAAA;;;;;;CAMC,GACD,SAASA,YAAY,QAAQ,6BAA4B"}
|
{"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["/**\n * Entry point: ipal-kit/rsc\n *\n * Server-component exports. RenderBlocks is a React Server Component, so it\n * lives here rather than in the main package entry to keep React out of the\n * server-config bundle.\n */\nexport { RenderBlocks } from '../modules/blocks/index.js'\nexport type {\n BlockComponentMap,\n BlockData,\n EnhanceProps,\n RenderBlocksProps,\n} from '../modules/blocks/index.js'\nexport { MediaPreconnect } from '../modules/storage/MediaPreconnect.js'\n"],"names":["RenderBlocks","MediaPreconnect"],"mappings":"AAAA;;;;;;CAMC,GACD,SAASA,YAAY,QAAQ,6BAA4B;AAOzD,SAASC,eAAe,QAAQ,wCAAuC"}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Emits <link rel="preconnect"> + <link rel="dns-prefetch"> for the media CDN
|
||||||
|
* domain (R2_PUBLIC_URL), so the browser opens the TLS/DNS connection to the
|
||||||
|
* media host early — before it hits the first <img>. Saves ~150–300ms on the
|
||||||
|
* first image load.
|
||||||
|
*
|
||||||
|
* Reads the domain from R2_PUBLIC_URL (the same env var buildR2Storage uses),
|
||||||
|
* so there's ONE source of truth — no per-project hardcoded domain. Renders
|
||||||
|
* nothing when R2_PUBLIC_URL isn't set (local disk / no CDN → nothing to
|
||||||
|
* preconnect).
|
||||||
|
*
|
||||||
|
* Server Component — drop it in the <head> of your locale layout:
|
||||||
|
*
|
||||||
|
* import { MediaPreconnect } from '@intecion/ipal-kit/rsc'
|
||||||
|
* // in <head> (or top of <body> — Next hoists link tags):
|
||||||
|
* <MediaPreconnect />
|
||||||
|
*/
|
||||||
|
export declare function MediaPreconnect(): import("react/jsx-runtime").JSX.Element | null;
|
||||||
|
export default MediaPreconnect;
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
||||||
|
/**
|
||||||
|
* Emits <link rel="preconnect"> + <link rel="dns-prefetch"> for the media CDN
|
||||||
|
* domain (R2_PUBLIC_URL), so the browser opens the TLS/DNS connection to the
|
||||||
|
* media host early — before it hits the first <img>. Saves ~150–300ms on the
|
||||||
|
* first image load.
|
||||||
|
*
|
||||||
|
* Reads the domain from R2_PUBLIC_URL (the same env var buildR2Storage uses),
|
||||||
|
* so there's ONE source of truth — no per-project hardcoded domain. Renders
|
||||||
|
* nothing when R2_PUBLIC_URL isn't set (local disk / no CDN → nothing to
|
||||||
|
* preconnect).
|
||||||
|
*
|
||||||
|
* Server Component — drop it in the <head> of your locale layout:
|
||||||
|
*
|
||||||
|
* import { MediaPreconnect } from '@intecion/ipal-kit/rsc'
|
||||||
|
* // in <head> (or top of <body> — Next hoists link tags):
|
||||||
|
* <MediaPreconnect />
|
||||||
|
*/ export function MediaPreconnect() {
|
||||||
|
const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\/$/, '');
|
||||||
|
if (!publicUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Origin only (scheme + host) — preconnect targets an origin, not a path.
|
||||||
|
let origin;
|
||||||
|
try {
|
||||||
|
origin = new URL(publicUrl).origin;
|
||||||
|
} catch {
|
||||||
|
return null // malformed URL → skip rather than emit a broken tag
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
||||||
|
children: [
|
||||||
|
/*#__PURE__*/ _jsx("link", {
|
||||||
|
crossOrigin: "anonymous",
|
||||||
|
href: origin,
|
||||||
|
rel: "preconnect"
|
||||||
|
}),
|
||||||
|
/*#__PURE__*/ _jsx("link", {
|
||||||
|
href: origin,
|
||||||
|
rel: "dns-prefetch"
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export default MediaPreconnect;
|
||||||
|
|
||||||
|
//# sourceMappingURL=MediaPreconnect.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/modules/storage/MediaPreconnect.tsx"],"sourcesContent":["/**\n * Emits <link rel=\"preconnect\"> + <link rel=\"dns-prefetch\"> for the media CDN\n * domain (R2_PUBLIC_URL), so the browser opens the TLS/DNS connection to the\n * media host early — before it hits the first <img>. Saves ~150–300ms on the\n * first image load.\n *\n * Reads the domain from R2_PUBLIC_URL (the same env var buildR2Storage uses),\n * so there's ONE source of truth — no per-project hardcoded domain. Renders\n * nothing when R2_PUBLIC_URL isn't set (local disk / no CDN → nothing to\n * preconnect).\n *\n * Server Component — drop it in the <head> of your locale layout:\n *\n * import { MediaPreconnect } from '@intecion/ipal-kit/rsc'\n * // in <head> (or top of <body> — Next hoists link tags):\n * <MediaPreconnect />\n */\nexport function MediaPreconnect() {\n const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\\/$/, '')\n if (!publicUrl) {return null}\n\n // Origin only (scheme + host) — preconnect targets an origin, not a path.\n let origin: string\n try {\n origin = new URL(publicUrl).origin\n } catch {\n return null // malformed URL → skip rather than emit a broken tag\n }\n\n return (\n <>\n <link crossOrigin=\"anonymous\" href={origin} rel=\"preconnect\" />\n <link href={origin} rel=\"dns-prefetch\" />\n </>\n )\n}\n\nexport default MediaPreconnect\n"],"names":["MediaPreconnect","publicUrl","process","env","R2_PUBLIC_URL","replace","origin","URL","link","crossOrigin","href","rel"],"mappings":";AAAA;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASA;IACd,MAAMC,YAAYC,QAAQC,GAAG,CAACC,aAAa,EAAEC,QAAQ,OAAO;IAC5D,IAAI,CAACJ,WAAW;QAAC,OAAO;IAAI;IAE5B,0EAA0E;IAC1E,IAAIK;IACJ,IAAI;QACFA,SAAS,IAAIC,IAAIN,WAAWK,MAAM;IACpC,EAAE,OAAM;QACN,OAAO,KAAK,qDAAqD;;IACnE;IAEA,qBACE;;0BACE,KAACE;gBAAKC,aAAY;gBAAYC,MAAMJ;gBAAQK,KAAI;;0BAChD,KAACH;gBAAKE,MAAMJ;gBAAQK,KAAI;;;;AAG9B;AAEA,eAAeX,gBAAe"}
|
||||||
@@ -184,3 +184,28 @@ czysta nazwa trafia i do bazy, i do bucketa). Dlaczego to ważne:
|
|||||||
|
|
||||||
Sama funkcja `normalizeFilename(name)` też jest wyeksportowana, gdybyś potrzebował
|
Sama funkcja `normalizeFilename(name)` też jest wyeksportowana, gdybyś potrzebował
|
||||||
jej poza hookiem.
|
jej poza hookiem.
|
||||||
|
|
||||||
|
## Preconnect do domeny mediów (wydajność)
|
||||||
|
|
||||||
|
Komponent `MediaPreconnect` generuje `<link rel="preconnect">` + `dns-prefetch`
|
||||||
|
dla domeny mediów (R2_PUBLIC_URL) — przeglądarka nawiązuje połączenie TLS/DNS
|
||||||
|
z CDN zawczasu, zanim napotka pierwszy `<img>`. Zysk ~150–300 ms na pierwszym
|
||||||
|
obrazie.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// layout.tsx — w <head> (albo górze <body>, Next hoistuje link tagi)
|
||||||
|
import { MediaPreconnect } from '@intecion/ipal-kit/rsc'
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<MediaPreconnect />
|
||||||
|
</head>
|
||||||
|
```
|
||||||
|
|
||||||
|
Czyta domenę z **R2_PUBLIC_URL** (to samo źródło co buildR2Storage) — zero
|
||||||
|
hardkodu, jedno źródło prawdy. Gdy R2_PUBLIC_URL nie ustawione (lokalny dysk,
|
||||||
|
brak CDN) → nie renderuje nic. Zmiana domeny mediów = zmiana jednej zmiennej
|
||||||
|
env, komponent podąża automatycznie.
|
||||||
|
|
||||||
|
> NIE hardkoduj `<link rel="preconnect" href="https://media.klient.pl">` ręcznie
|
||||||
|
> w layoutcie — to zaszywa domenę klienta w kodzie. Użyj MediaPreconnect, który
|
||||||
|
> bierze ją z env.
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@intecion/ipal-kit",
|
"name": "@intecion/ipal-kit",
|
||||||
"version": "1.0.22",
|
"version": "1.1.0",
|
||||||
"description": "Intecion Payload Advanced Library — a Payload CMS 3 plugin: i18n, SEO, forms, consent, analytics, blog/archives.",
|
"description": "Intecion Payload Advanced Library — a Payload CMS 3 plugin: i18n, SEO, forms, consent, analytics, blog/archives.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -12,3 +12,4 @@ export type {
|
|||||||
EnhanceProps,
|
EnhanceProps,
|
||||||
RenderBlocksProps,
|
RenderBlocksProps,
|
||||||
} from '../modules/blocks/index.js'
|
} from '../modules/blocks/index.js'
|
||||||
|
export { MediaPreconnect } from '../modules/storage/MediaPreconnect.js'
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Emits <link rel="preconnect"> + <link rel="dns-prefetch"> for the media CDN
|
||||||
|
* domain (R2_PUBLIC_URL), so the browser opens the TLS/DNS connection to the
|
||||||
|
* media host early — before it hits the first <img>. Saves ~150–300ms on the
|
||||||
|
* first image load.
|
||||||
|
*
|
||||||
|
* Reads the domain from R2_PUBLIC_URL (the same env var buildR2Storage uses),
|
||||||
|
* so there's ONE source of truth — no per-project hardcoded domain. Renders
|
||||||
|
* nothing when R2_PUBLIC_URL isn't set (local disk / no CDN → nothing to
|
||||||
|
* preconnect).
|
||||||
|
*
|
||||||
|
* Server Component — drop it in the <head> of your locale layout:
|
||||||
|
*
|
||||||
|
* import { MediaPreconnect } from '@intecion/ipal-kit/rsc'
|
||||||
|
* // in <head> (or top of <body> — Next hoists link tags):
|
||||||
|
* <MediaPreconnect />
|
||||||
|
*/
|
||||||
|
export function MediaPreconnect() {
|
||||||
|
const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\/$/, '')
|
||||||
|
if (!publicUrl) {return null}
|
||||||
|
|
||||||
|
// Origin only (scheme + host) — preconnect targets an origin, not a path.
|
||||||
|
let origin: string
|
||||||
|
try {
|
||||||
|
origin = new URL(publicUrl).origin
|
||||||
|
} catch {
|
||||||
|
return null // malformed URL → skip rather than emit a broken tag
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<link crossOrigin="anonymous" href={origin} rel="preconnect" />
|
||||||
|
<link href={origin} rel="dns-prefetch" />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MediaPreconnect
|
||||||
Reference in New Issue
Block a user