diff --git a/fixtures/react-router-cloudflare/app/routes/[another-page]._index.tsx b/fixtures/react-router-cloudflare/app/routes/[another-page]._index.tsx index 17d3491d0b80..13f5ce08b0b5 100644 --- a/fixtures/react-router-cloudflare/app/routes/[another-page]._index.tsx +++ b/fixtures/react-router-cloudflare/app/routes/[another-page]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-cloudflare/app/routes/_index.tsx b/fixtures/react-router-cloudflare/app/routes/_index.tsx index dec09db55604..23ce05241be0 100644 --- a/fixtures/react-router-cloudflare/app/routes/_index.tsx +++ b/fixtures/react-router-cloudflare/app/routes/_index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-docker/app/routes/[another-page]._index.tsx b/fixtures/react-router-docker/app/routes/[another-page]._index.tsx index 17d3491d0b80..13f5ce08b0b5 100644 --- a/fixtures/react-router-docker/app/routes/[another-page]._index.tsx +++ b/fixtures/react-router-docker/app/routes/[another-page]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-docker/app/routes/_index.tsx b/fixtures/react-router-docker/app/routes/_index.tsx index dec09db55604..23ce05241be0 100644 --- a/fixtures/react-router-docker/app/routes/_index.tsx +++ b/fixtures/react-router-docker/app/routes/_index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-netlify/app/routes/[another-page]._index.tsx b/fixtures/react-router-netlify/app/routes/[another-page]._index.tsx index 17d3491d0b80..13f5ce08b0b5 100644 --- a/fixtures/react-router-netlify/app/routes/[another-page]._index.tsx +++ b/fixtures/react-router-netlify/app/routes/[another-page]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-netlify/app/routes/_index.tsx b/fixtures/react-router-netlify/app/routes/_index.tsx index dec09db55604..23ce05241be0 100644 --- a/fixtures/react-router-netlify/app/routes/_index.tsx +++ b/fixtures/react-router-netlify/app/routes/_index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-vercel/app/routes/[another-page]._index.tsx b/fixtures/react-router-vercel/app/routes/[another-page]._index.tsx index 17d3491d0b80..13f5ce08b0b5 100644 --- a/fixtures/react-router-vercel/app/routes/[another-page]._index.tsx +++ b/fixtures/react-router-vercel/app/routes/[another-page]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/react-router-vercel/app/routes/_index.tsx b/fixtures/react-router-vercel/app/routes/_index.tsx index dec09db55604..23ce05241be0 100644 --- a/fixtures/react-router-vercel/app/routes/_index.tsx +++ b/fixtures/react-router-vercel/app/routes/_index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx b/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx index 8b285af2d9a7..6c357a9e8d7c 100644 --- a/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx +++ b/fixtures/webstudio-cloudflare-template/app/routes/[another-page]._index.tsx @@ -13,6 +13,7 @@ import { isLocalResource, loadResource, loadResources, + cachedFetch, formIdFieldName, formBotFieldName, } from "@webstudio-is/sdk/runtime"; @@ -43,7 +44,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -53,7 +54,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx b/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx index 98dfabad5346..1baf468dce4d 100644 --- a/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx +++ b/fixtures/webstudio-cloudflare-template/app/routes/_index.tsx @@ -13,6 +13,7 @@ import { isLocalResource, loadResource, loadResources, + cachedFetch, formIdFieldName, formBotFieldName, } from "@webstudio-is/sdk/runtime"; @@ -43,7 +44,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -53,7 +54,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[_route_with_symbols_]._index.tsx b/fixtures/webstudio-features/app/routes/[_route_with_symbols_]._index.tsx index edc9ce20a752..77fb67185afe 100644 --- a/fixtures/webstudio-features/app/routes/[_route_with_symbols_]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[_route_with_symbols_]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[animations]._index.tsx b/fixtures/webstudio-features/app/routes/[animations]._index.tsx index e765d6ae7169..f240fdfef0dd 100644 --- a/fixtures/webstudio-features/app/routes/[animations]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[animations]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[class-names]._index.tsx b/fixtures/webstudio-features/app/routes/[class-names]._index.tsx index b1f500d54174..d8791547f417 100644 --- a/fixtures/webstudio-features/app/routes/[class-names]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[class-names]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[content-block]._index.tsx b/fixtures/webstudio-features/app/routes/[content-block]._index.tsx index 4707da8caa18..939509cbedf3 100644 --- a/fixtures/webstudio-features/app/routes/[content-block]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[content-block]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[duration]._index.tsx b/fixtures/webstudio-features/app/routes/[duration]._index.tsx index 41ce6045d803..31ee6454458d 100644 --- a/fixtures/webstudio-features/app/routes/[duration]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[duration]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[expressions]._index.tsx b/fixtures/webstudio-features/app/routes/[expressions]._index.tsx index ea8fc413a6a1..b2a0f977efab 100644 --- a/fixtures/webstudio-features/app/routes/[expressions]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[expressions]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[form]._index.tsx b/fixtures/webstudio-features/app/routes/[form]._index.tsx index 1b5da5bec09b..c331a2370572 100644 --- a/fixtures/webstudio-features/app/routes/[form]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[form]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[head-tag]._index.tsx b/fixtures/webstudio-features/app/routes/[head-tag]._index.tsx index 18a752310741..85071d61b2b6 100644 --- a/fixtures/webstudio-features/app/routes/[head-tag]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[head-tag]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[heading-with-id]._index.tsx b/fixtures/webstudio-features/app/routes/[heading-with-id]._index.tsx index 88e4ae7fb778..d5566ad117b6 100644 --- a/fixtures/webstudio-features/app/routes/[heading-with-id]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[heading-with-id]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[nested].[nested-page]._index.tsx b/fixtures/webstudio-features/app/routes/[nested].[nested-page]._index.tsx index ef970f1cdc90..dfca5b924784 100644 --- a/fixtures/webstudio-features/app/routes/[nested].[nested-page]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[nested].[nested-page]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[radix]._index.tsx b/fixtures/webstudio-features/app/routes/[radix]._index.tsx index 035aa84f2dc4..dc0c7ceef60a 100644 --- a/fixtures/webstudio-features/app/routes/[radix]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[radix]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[resources]._index.tsx b/fixtures/webstudio-features/app/routes/[resources]._index.tsx index 91664fecce12..f2d19bd03968 100644 --- a/fixtures/webstudio-features/app/routes/[resources]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[resources]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/[text-duration]._index.tsx b/fixtures/webstudio-features/app/routes/[text-duration]._index.tsx index eaf748752264..4cda7f1b4cd2 100644 --- a/fixtures/webstudio-features/app/routes/[text-duration]._index.tsx +++ b/fixtures/webstudio-features/app/routes/[text-duration]._index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/fixtures/webstudio-features/app/routes/_index.tsx b/fixtures/webstudio-features/app/routes/_index.tsx index dec09db55604..23ce05241be0 100644 --- a/fixtures/webstudio-features/app/routes/_index.tsx +++ b/fixtures/webstudio-features/app/routes/_index.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "../__generated__/$resources.sitemap.xml"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/packages/cli/templates/defaults/app/route-templates/html.tsx b/packages/cli/templates/defaults/app/route-templates/html.tsx index 12581dcc3689..fb3c6295e406 100644 --- a/packages/cli/templates/defaults/app/route-templates/html.tsx +++ b/packages/cli/templates/defaults/app/route-templates/html.tsx @@ -13,6 +13,7 @@ import { isLocalResource, loadResource, loadResources, + cachedFetch, formIdFieldName, formBotFieldName, } from "@webstudio-is/sdk/runtime"; @@ -43,7 +44,7 @@ import { sitemap } from "__SITEMAP__"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -53,7 +54,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/packages/cli/templates/react-router/app/route-templates/html.tsx b/packages/cli/templates/react-router/app/route-templates/html.tsx index b9dbbbb84259..894af05a9cbd 100644 --- a/packages/cli/templates/react-router/app/route-templates/html.tsx +++ b/packages/cli/templates/react-router/app/route-templates/html.tsx @@ -15,6 +15,7 @@ import { loadResources, formIdFieldName, formBotFieldName, + cachedFetch, } from "@webstudio-is/sdk/runtime"; import { ReactSdkContext, @@ -42,7 +43,7 @@ import { sitemap } from "__SITEMAP__"; const customFetch: typeof fetch = (input, init) => { if (typeof input !== "string") { - return fetch(input, init); + return cachedFetch(projectId, input, init); } if (isLocalResource(input, "sitemap.xml")) { @@ -52,7 +53,7 @@ const customFetch: typeof fetch = (input, init) => { return Promise.resolve(response); } - return fetch(input, init); + return cachedFetch(projectId, input, init); }; export const loader = async (arg: LoaderFunctionArgs) => { diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 24f057e15c9d..0cef9f8c0adb 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -41,6 +41,7 @@ "dts": "tsc --project tsconfig.dts.json" }, "dependencies": { + "@emotion/hash": "^0.9.2", "@webstudio-is/css-engine": "workspace:*", "@webstudio-is/fonts": "workspace:*", "@webstudio-is/icons": "workspace:*", diff --git a/packages/sdk/src/resource-loader.ts b/packages/sdk/src/resource-loader.ts index dd2f3504b121..53422de21bb1 100644 --- a/packages/sdk/src/resource-loader.ts +++ b/packages/sdk/src/resource-loader.ts @@ -1,3 +1,4 @@ +import hash from "@emotion/hash"; import type { ResourceRequest } from "./schema/resources"; const LOCAL_RESOURCE_PREFIX = "$resources"; @@ -89,3 +90,56 @@ export const loadResources = async ( ) ); }; + +/** + * cache api supports only get method + * put hash of method and body into url + * to support for example graphql queries + */ +const getCacheKey = async (request: Request) => { + const url = new URL(request.url); + const method = request.method; + const body = await request.clone().text(); + // invalidate cache when cache-control is changed + const cacheControl = request.headers.get("Cache-Control"); + const resourceHash = hash(`${method}:${body}:${cacheControl}`); + url.searchParams.set("ws-resource-hash", resourceHash); + return url; +}; + +export const cachedFetch = async ( + namespace: string, + input: RequestInfo | URL, + init?: RequestInit +) => { + if (globalThis.caches) { + const request = new Request(input, init); + const requestCacheControl = request.headers.get("Cache-Control"); + // make cache opt in with cache-control header + if (!requestCacheControl) { + return fetch(input, init); + } + const cache = await caches.open(namespace); + const cacheKey = await getCacheKey(request); + let response = await cache.match(cacheKey); + if (response) { + // avoid mutating cached response + return new Response(response.body, response); + } + // load response when missing in cache + response = await fetch(request); + // avoid caching failed responses + if (!response.ok) { + return response; + } + // put Cache-Control from request into response + // https://developers.cloudflare.com/workers/reference/how-the-cache-works/#cache-api + // response.clone() does not remove read-only constraint from headers + response = new Response(response.body, response); + response.headers.set("Cache-Control", requestCacheControl); + // avoid mutating cached response + await cache.put(cacheKey, response.clone()); + return response; + } + return fetch(input, init); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7ed11a7f6e5..ab034739821b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1805,6 +1805,9 @@ importers: packages/sdk: dependencies: + '@emotion/hash': + specifier: ^0.9.2 + version: 0.9.2 '@webstudio-is/css-engine': specifier: workspace:* version: link:../css-engine