@shopify/hydrogen 0.7.0 → 0.8.2
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/esnext/components/CartEstimatedCost/CartEstimatedCost.client.d.ts +1 -1
- package/dist/esnext/components/CartEstimatedCost/CartEstimatedCost.client.js +1 -1
- package/dist/esnext/components/CartLineProvider/context.d.ts +3 -3
- package/dist/esnext/components/CartLineQuantityAdjustButton/CartLineQuantityAdjustButton.js +4 -0
- package/dist/esnext/components/CartProvider/CartProvider.client.js +0 -1
- package/dist/esnext/components/ExternalVideo/ExternalVideo.d.ts +1 -1
- package/dist/esnext/components/Image/Image.d.ts +1 -1
- package/dist/esnext/components/LocalizationProvider/index.d.ts +1 -0
- package/dist/esnext/components/LocalizationProvider/index.js +1 -0
- package/dist/esnext/components/MediaFile/MediaFile.d.ts +1 -1
- package/dist/esnext/components/Metafield/Metafield.client.d.ts +1 -1
- package/dist/esnext/components/Metafield/components/StarRating/StarRating.d.ts +1 -1
- package/dist/esnext/components/Metafield/index.d.ts +2 -2
- package/dist/esnext/components/Model3D/Model3D.client.d.ts +1 -1
- package/dist/esnext/components/Money/Money.client.d.ts +1 -1
- package/dist/esnext/components/ProductPrice/ProductPrice.client.d.ts +1 -3
- package/dist/esnext/components/ProductPrice/ProductPrice.client.js +1 -3
- package/dist/esnext/components/ProductProvider/ProductProvider.client.d.ts +1 -1
- package/dist/esnext/components/ShopPayButton/ShopPayButton.client.js +1 -1
- package/dist/esnext/components/UnitPrice/UnitPrice.client.d.ts +2 -3
- package/dist/esnext/components/UnitPrice/UnitPrice.client.js +1 -2
- package/dist/esnext/components/Video/Video.d.ts +1 -1
- package/dist/esnext/components/index.d.ts +3 -2
- package/dist/esnext/components/index.js +1 -0
- package/dist/esnext/entry-client.js +4 -6
- package/dist/esnext/entry-server.js +77 -47
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheContext.d.ts +2 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheContext.js +4 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheProvider.d.ts +2 -0
- package/dist/esnext/foundation/RenderCacheProvider/RenderCacheProvider.js +5 -0
- package/dist/esnext/foundation/RenderCacheProvider/hook.d.ts +11 -0
- package/dist/esnext/foundation/RenderCacheProvider/hook.js +34 -0
- package/dist/esnext/foundation/RenderCacheProvider/index.d.ts +1 -0
- package/dist/esnext/foundation/RenderCacheProvider/index.js +1 -0
- package/dist/esnext/foundation/RenderCacheProvider/types.d.ts +18 -0
- package/dist/esnext/foundation/RenderCacheProvider/types.js +1 -0
- package/dist/esnext/foundation/Router/DefaultRoutes.d.ts +3 -1
- package/dist/esnext/foundation/Router/DefaultRoutes.js +2 -2
- package/dist/esnext/foundation/ServerStateProvider/ServerStateProvider.client.js +4 -2
- package/dist/esnext/foundation/ServerStateProvider/index.d.ts +2 -1
- package/dist/esnext/foundation/ShopifyProvider/ShopifyServerProvider.server.d.ts +1 -3
- package/dist/esnext/foundation/ShopifyProvider/ShopifyServerProvider.server.js +2 -4
- package/dist/esnext/foundation/ShopifyProvider/types.d.ts +0 -5
- package/dist/esnext/foundation/useQuery/hooks.d.ts +8 -6
- package/dist/esnext/foundation/useQuery/hooks.js +13 -14
- package/dist/esnext/foundation/useQuery/index.d.ts +0 -1
- package/dist/esnext/foundation/useQuery/index.js +0 -1
- package/dist/esnext/foundation/useServerState/use-server-state.d.ts +1 -1
- package/dist/esnext/foundation/useServerState/use-server-state.js +1 -1
- package/dist/esnext/foundation/useShop/use-shop.d.ts +1 -1
- package/dist/esnext/foundation/useShop/use-shop.js +1 -1
- package/dist/esnext/framework/ClientMarker/ClientMarker.js +0 -1
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/esnext/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/esnext/framework/Hydration/writer.server.js +1 -0
- package/dist/esnext/framework/cache.d.ts +2 -2
- package/dist/esnext/framework/cache.js +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.d.ts +1 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +13 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.d.ts +7 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +15 -1
- package/dist/esnext/framework/plugins/vite-plugin-react-server-components-shim.js +1 -23
- package/dist/esnext/framework/server-components.js +25 -47
- package/dist/esnext/graphql/graphql-constants.d.ts +23 -23
- package/dist/esnext/handle-event.d.ts +1 -1
- package/dist/esnext/handle-event.js +68 -10
- package/dist/esnext/hooks/index.d.ts +1 -1
- package/dist/esnext/hooks/index.js +1 -1
- package/dist/esnext/hooks/useCartLine/useCartLine.d.ts +3 -3
- package/dist/esnext/hooks/useShopQuery/hooks.d.ts +5 -5
- package/dist/esnext/hooks/useShopQuery/hooks.js +45 -17
- package/dist/esnext/index.d.ts +2 -1
- package/dist/esnext/index.js +2 -1
- package/dist/esnext/types.d.ts +2 -1
- package/dist/esnext/utilities/fetch.js +3 -6
- package/dist/esnext/utilities/index.d.ts +1 -0
- package/dist/esnext/utilities/index.js +1 -0
- package/dist/esnext/utilities/log/index.d.ts +1 -0
- package/dist/esnext/utilities/log/index.js +1 -0
- package/dist/esnext/utilities/log/log.d.ts +17 -0
- package/dist/esnext/utilities/log/log.js +70 -0
- package/dist/esnext/utilities/suspense.d.ts +2 -2
- package/dist/esnext/utilities/suspense.js +0 -6
- package/dist/esnext/utilities/timing.d.ts +7 -0
- package/dist/esnext/utilities/timing.js +14 -0
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/framework/ClientMarker/ClientMarker.js +2 -3
- package/dist/node/framework/Hydration/Cache.client.js +4 -4
- package/dist/node/framework/Hydration/HydrationContext.server.js +1 -1
- package/dist/node/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/node/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/node/framework/Hydration/ServerComponentResponse.server.js +2 -2
- package/dist/node/framework/Hydration/react-utils.js +3 -3
- package/dist/node/framework/Hydration/wire.server.js +1 -1
- package/dist/node/framework/Hydration/writer.server.js +1 -0
- package/dist/node/framework/cache.d.ts +2 -2
- package/dist/node/framework/cache.js +5 -4
- package/dist/node/framework/middleware.js +2 -2
- package/dist/node/framework/plugin.js +5 -5
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.d.ts +1 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +13 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.d.ts +7 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +17 -3
- package/dist/node/framework/plugins/vite-plugin-react-server-components-shim.js +8 -30
- package/dist/node/framework/server-components.js +27 -49
- package/dist/node/handle-event.d.ts +1 -1
- package/dist/node/handle-event.js +72 -14
- package/dist/node/types.d.ts +2 -1
- package/dist/node/utilities/fetch.js +4 -7
- package/dist/node/utilities/index.d.ts +1 -0
- package/dist/node/utilities/index.js +3 -1
- package/dist/node/utilities/isServer/isServer.js +1 -1
- package/dist/node/utilities/suspense.d.ts +2 -2
- package/dist/node/utilities/suspense.js +0 -6
- package/dist/node/utilities/timing.d.ts +7 -0
- package/dist/node/utilities/timing.js +18 -0
- package/dist/node/utilities/video_parameters.js +1 -1
- package/dist/node/version.d.ts +1 -1
- package/dist/node/version.js +1 -1
- package/dist/worker/framework/Hydration/ServerComponentRequest.server.d.ts +1 -0
- package/dist/worker/framework/Hydration/ServerComponentRequest.server.js +2 -0
- package/dist/worker/framework/cache.d.ts +2 -2
- package/dist/worker/framework/cache.js +1 -1
- package/dist/worker/handle-event.d.ts +1 -1
- package/dist/worker/handle-event.js +68 -10
- package/dist/worker/types.d.ts +2 -1
- package/dist/worker/utilities/timing.d.ts +7 -0
- package/dist/worker/utilities/timing.js +14 -0
- package/package.json +10 -10
- package/dist/esnext/foundation/useQuery/QueryProvider.d.ts +0 -6
- package/dist/esnext/foundation/useQuery/QueryProvider.js +0 -13
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import
|
|
2
|
+
import { ServerResponse } from 'http';
|
|
3
3
|
import type { ServerComponentRequest } from './framework/Hydration/ServerComponentRequest.server';
|
|
4
4
|
import { RuntimeContext } from './framework/runtime';
|
|
5
5
|
interface HydrogenFetchEvent {
|
|
@@ -9,9 +9,9 @@ async function handleEvent(event, { request, entrypoint, indexTemplate, assetHan
|
|
|
9
9
|
/**
|
|
10
10
|
* Inject the cache & context into the module loader so we can pull it out for subrequests.
|
|
11
11
|
*/
|
|
12
|
-
runtime_1.setCache(cache);
|
|
13
|
-
runtime_1.setContext(context);
|
|
14
|
-
config_1.setConfig({ dev });
|
|
12
|
+
(0, runtime_1.setCache)(cache);
|
|
13
|
+
(0, runtime_1.setContext)(context);
|
|
14
|
+
(0, config_1.setConfig)({ dev });
|
|
15
15
|
const isReactHydrationRequest = url.pathname === '/react';
|
|
16
16
|
const template = typeof indexTemplate === 'function'
|
|
17
17
|
? await indexTemplate(url.toString())
|
|
@@ -29,7 +29,8 @@ async function handleEvent(event, { request, entrypoint, indexTemplate, assetHan
|
|
|
29
29
|
throw new Error(`entry-server.jsx could not be loaded. This likely occurred because of a Vite compilation error.\n` +
|
|
30
30
|
`Please check your server logs for more information.`);
|
|
31
31
|
}
|
|
32
|
-
const
|
|
32
|
+
const userAgent = request.headers.get('user-agent');
|
|
33
|
+
const isStreamable = streamableResponse && !isBotUA(url, userAgent);
|
|
33
34
|
/**
|
|
34
35
|
* Stream back real-user responses, but for bots/etc,
|
|
35
36
|
* use `render` instead. This is because we need to inject <head>
|
|
@@ -37,7 +38,12 @@ async function handleEvent(event, { request, entrypoint, indexTemplate, assetHan
|
|
|
37
38
|
*/
|
|
38
39
|
if (isStreamable) {
|
|
39
40
|
if (isReactHydrationRequest) {
|
|
40
|
-
hydrate(url, {
|
|
41
|
+
hydrate(url, {
|
|
42
|
+
context: {},
|
|
43
|
+
request,
|
|
44
|
+
response: streamableResponse,
|
|
45
|
+
dev,
|
|
46
|
+
});
|
|
41
47
|
}
|
|
42
48
|
else {
|
|
43
49
|
stream(url, {
|
|
@@ -50,13 +56,18 @@ async function handleEvent(event, { request, entrypoint, indexTemplate, assetHan
|
|
|
50
56
|
}
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
|
-
const { body, bodyAttributes, htmlAttributes, componentResponse, ...head } = await render(url, {
|
|
59
|
+
const { body, bodyAttributes, htmlAttributes, componentResponse, ...head } = await render(url, {
|
|
60
|
+
request,
|
|
61
|
+
context: {},
|
|
62
|
+
isReactHydrationRequest,
|
|
63
|
+
dev,
|
|
64
|
+
});
|
|
54
65
|
const headers = componentResponse.headers;
|
|
55
66
|
/**
|
|
56
67
|
* TODO: Also add `Vary` headers for `accept-language` and any other keys
|
|
57
68
|
* we want to shard our full-page cache for all Hydrogen storefronts.
|
|
58
69
|
*/
|
|
59
|
-
headers.set(cache_1.getCacheControlHeader({ dev }), componentResponse.cacheControlHeader);
|
|
70
|
+
headers.set((0, cache_1.getCacheControlHeader)({ dev }), componentResponse.cacheControlHeader);
|
|
60
71
|
if (componentResponse.customBody) {
|
|
61
72
|
const { status, customStatus } = componentResponse;
|
|
62
73
|
return new Response(await componentResponse.customBody, {
|
|
@@ -89,13 +100,6 @@ async function handleEvent(event, { request, entrypoint, indexTemplate, assetHan
|
|
|
89
100
|
return response;
|
|
90
101
|
}
|
|
91
102
|
exports.default = handleEvent;
|
|
92
|
-
function isStreamableRequest(url) {
|
|
93
|
-
/**
|
|
94
|
-
* TODO: Add UA detection.
|
|
95
|
-
*/
|
|
96
|
-
const isBot = url.searchParams.has('_bot');
|
|
97
|
-
return !isBot;
|
|
98
|
-
}
|
|
99
103
|
/**
|
|
100
104
|
* Generate the contents of the `head` tag, and update the existing `<title>` tag
|
|
101
105
|
* if one exists, and if a title is passed.
|
|
@@ -120,3 +124,57 @@ function generateHeadTag(head) {
|
|
|
120
124
|
return `<head>${headHtml}</head>`;
|
|
121
125
|
};
|
|
122
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Determines if the request is from a bot, using the URL and User Agent
|
|
129
|
+
*/
|
|
130
|
+
function isBotUA(url, userAgent) {
|
|
131
|
+
return (url.searchParams.has('_bot') || (!!userAgent && botUARegex.test(userAgent)));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* An alphabetized list of User Agents of known bots, combined from lists found at:
|
|
135
|
+
* https://github.com/vercel/next.js/blob/d87dc2b5a0b3fdbc0f6806a47be72bad59564bd0/packages/next/server/utils.ts#L18-L22
|
|
136
|
+
* https://github.com/GoogleChrome/rendertron/blob/6f681688737846b28754fbfdf5db173846a826df/middleware/src/middleware.ts#L24-L41
|
|
137
|
+
*/
|
|
138
|
+
const botUserAgents = [
|
|
139
|
+
'AdsBot-Google',
|
|
140
|
+
'applebot',
|
|
141
|
+
'Baiduspider',
|
|
142
|
+
'baiduspider',
|
|
143
|
+
'bingbot',
|
|
144
|
+
'Bingbot',
|
|
145
|
+
'BingPreview',
|
|
146
|
+
'bitlybot',
|
|
147
|
+
'Discordbot',
|
|
148
|
+
'DuckDuckBot',
|
|
149
|
+
'Embedly',
|
|
150
|
+
'facebookcatalog',
|
|
151
|
+
'facebookexternalhit',
|
|
152
|
+
'Google-PageRenderer',
|
|
153
|
+
'Googlebot',
|
|
154
|
+
'googleweblight',
|
|
155
|
+
'ia_archive',
|
|
156
|
+
'LinkedInBot',
|
|
157
|
+
'Mediapartners-Google',
|
|
158
|
+
'outbrain',
|
|
159
|
+
'pinterest',
|
|
160
|
+
'quora link preview',
|
|
161
|
+
'redditbot',
|
|
162
|
+
'rogerbot',
|
|
163
|
+
'showyoubot',
|
|
164
|
+
'SkypeUriPreview',
|
|
165
|
+
'Slackbot',
|
|
166
|
+
'Slurp',
|
|
167
|
+
'sogou',
|
|
168
|
+
'Storebot-Google',
|
|
169
|
+
'TelegramBot',
|
|
170
|
+
'tumblr',
|
|
171
|
+
'Twitterbot',
|
|
172
|
+
'vkShare',
|
|
173
|
+
'W3C_Validator',
|
|
174
|
+
'WhatsApp',
|
|
175
|
+
'yandex',
|
|
176
|
+
];
|
|
177
|
+
/**
|
|
178
|
+
* Creates a regex based on the botUserAgents array
|
|
179
|
+
*/
|
|
180
|
+
const botUARegex = new RegExp(botUserAgents.join('|'), 'i');
|
package/dist/node/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import
|
|
2
|
+
import { ServerResponse } from 'http';
|
|
3
3
|
import type { ServerComponentResponse } from './framework/Hydration/ServerComponentResponse.server';
|
|
4
4
|
import type { ServerComponentRequest } from './framework/Hydration/ServerComponentRequest.server';
|
|
5
5
|
import type { Metafield, Image, MediaContentType } from './graphql/types/types';
|
|
@@ -78,6 +78,7 @@ export interface Measurement {
|
|
|
78
78
|
unit: string;
|
|
79
79
|
value: number;
|
|
80
80
|
}
|
|
81
|
+
export declare type QueryKey = string | readonly unknown[];
|
|
81
82
|
export interface CacheOptions {
|
|
82
83
|
private?: boolean;
|
|
83
84
|
maxAge?: number;
|
|
@@ -41,13 +41,16 @@ function fetchBuilder(request) {
|
|
|
41
41
|
headers,
|
|
42
42
|
method: clonedRequest.method,
|
|
43
43
|
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw response;
|
|
46
|
+
}
|
|
44
47
|
const data = await response.json();
|
|
45
48
|
return data;
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
exports.fetchBuilder = fetchBuilder;
|
|
49
52
|
function graphqlRequestBody(query, variables) {
|
|
50
|
-
const queryString = typeof query === 'string' ? query : graphql_1.print(query);
|
|
53
|
+
const queryString = typeof query === 'string' ? query : (0, graphql_1.print)(query);
|
|
51
54
|
return JSON.stringify({
|
|
52
55
|
query: queryString,
|
|
53
56
|
variables,
|
|
@@ -55,12 +58,6 @@ function graphqlRequestBody(query, variables) {
|
|
|
55
58
|
}
|
|
56
59
|
exports.graphqlRequestBody = graphqlRequestBody;
|
|
57
60
|
function decodeShopifyId(id) {
|
|
58
|
-
if (!id.startsWith('gid://')) {
|
|
59
|
-
id =
|
|
60
|
-
typeof btoa !== 'undefined'
|
|
61
|
-
? btoa(id)
|
|
62
|
-
: Buffer.from(id, 'base64').toString('ascii');
|
|
63
|
-
}
|
|
64
61
|
if (!id.startsWith('gid://')) {
|
|
65
62
|
throw new Error('invalid Shopify ID');
|
|
66
63
|
}
|
|
@@ -8,3 +8,4 @@ export { isServer } from './isServer';
|
|
|
8
8
|
export { getMeasurementAsParts, getMeasurementAsString } from './measurement';
|
|
9
9
|
export { parseMetafieldValue } from './parseMetafieldValue';
|
|
10
10
|
export { fetchBuilder, graphqlRequestBody, decodeShopifyId } from './fetch';
|
|
11
|
+
export { getTime } from './timing';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.decodeShopifyId = exports.graphqlRequestBody = exports.fetchBuilder = exports.parseMetafieldValue = exports.getMeasurementAsString = exports.getMeasurementAsParts = exports.isServer = exports.isClient = exports.flattenConnection = exports.wrapPromise = exports.loadScript = exports.useEmbeddedVideoUrl = exports.addParametersToEmbeddedVideoUrl = exports.shopifyImageLoader = exports.getShopifyImageDimensions = exports.useImageUrl = exports.addImageSizeParametersToUrl = void 0;
|
|
3
|
+
exports.getTime = exports.decodeShopifyId = exports.graphqlRequestBody = exports.fetchBuilder = exports.parseMetafieldValue = exports.getMeasurementAsString = exports.getMeasurementAsParts = exports.isServer = exports.isClient = exports.flattenConnection = exports.wrapPromise = exports.loadScript = exports.useEmbeddedVideoUrl = exports.addParametersToEmbeddedVideoUrl = exports.shopifyImageLoader = exports.getShopifyImageDimensions = exports.useImageUrl = exports.addImageSizeParametersToUrl = void 0;
|
|
4
4
|
var image_size_1 = require("./image_size");
|
|
5
5
|
Object.defineProperty(exports, "addImageSizeParametersToUrl", { enumerable: true, get: function () { return image_size_1.addImageSizeParametersToUrl; } });
|
|
6
6
|
Object.defineProperty(exports, "useImageUrl", { enumerable: true, get: function () { return image_size_1.useImageUrl; } });
|
|
@@ -28,3 +28,5 @@ var fetch_1 = require("./fetch");
|
|
|
28
28
|
Object.defineProperty(exports, "fetchBuilder", { enumerable: true, get: function () { return fetch_1.fetchBuilder; } });
|
|
29
29
|
Object.defineProperty(exports, "graphqlRequestBody", { enumerable: true, get: function () { return fetch_1.graphqlRequestBody; } });
|
|
30
30
|
Object.defineProperty(exports, "decodeShopifyId", { enumerable: true, get: function () { return fetch_1.decodeShopifyId; } });
|
|
31
|
+
var timing_1 = require("./timing");
|
|
32
|
+
Object.defineProperty(exports, "getTime", { enumerable: true, get: function () { return timing_1.getTime; } });
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Wrap the fetch promise in a way that React Suspense understands.
|
|
3
3
|
* Essentially, keep throwing something until you have legit data.
|
|
4
4
|
*/
|
|
5
|
-
export declare function wrapPromise(promise: Promise<
|
|
6
|
-
read: () =>
|
|
5
|
+
export declare function wrapPromise<T>(promise: Promise<T>): {
|
|
6
|
+
read: () => T;
|
|
7
7
|
};
|
|
@@ -14,14 +14,8 @@ function wrapPromise(promise) {
|
|
|
14
14
|
}, (err) => {
|
|
15
15
|
status = 'error';
|
|
16
16
|
response = err;
|
|
17
|
-
throw err;
|
|
18
17
|
});
|
|
19
18
|
const read = () => {
|
|
20
|
-
/**
|
|
21
|
-
* TODO: This logic doesn't hold up when an error is thrown. For some reason.
|
|
22
|
-
* We instead throw the exception above in the suspender. We should revisit
|
|
23
|
-
* this and add a better server fetch implementation.
|
|
24
|
-
*/
|
|
25
19
|
switch (status) {
|
|
26
20
|
case 'pending':
|
|
27
21
|
throw suspender;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Not all environments have access to Performance.now(). This is to prevent
|
|
3
|
+
* timing side channel attacks.
|
|
4
|
+
*
|
|
5
|
+
* See: https://community.cloudflare.com/t/cloudflare-workers-how-do-i-measure-execution-time-of-my-method/69672
|
|
6
|
+
*/
|
|
7
|
+
export declare function getTime(): number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTime = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Not all environments have access to Performance.now(). This is to prevent
|
|
6
|
+
* timing side channel attacks.
|
|
7
|
+
*
|
|
8
|
+
* See: https://community.cloudflare.com/t/cloudflare-workers-how-do-i-measure-execution-time-of-my-method/69672
|
|
9
|
+
*/
|
|
10
|
+
function getTime() {
|
|
11
|
+
if (typeof performance !== 'undefined' && performance.now) {
|
|
12
|
+
return performance.now();
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return Date.now();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.getTime = getTime;
|
|
@@ -17,7 +17,7 @@ function addParametersToEmbeddedVideoUrl(url, parameters) {
|
|
|
17
17
|
}
|
|
18
18
|
exports.addParametersToEmbeddedVideoUrl = addParametersToEmbeddedVideoUrl;
|
|
19
19
|
function useEmbeddedVideoUrl(url, parameters) {
|
|
20
|
-
return react_1.useMemo(() => {
|
|
20
|
+
return (0, react_1.useMemo)(() => {
|
|
21
21
|
if (!parameters) {
|
|
22
22
|
return url;
|
|
23
23
|
}
|
package/dist/node/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "0.
|
|
1
|
+
export declare const LIB_VERSION = "0.8.2";
|
package/dist/node/version.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getTime } from '../../utilities/timing';
|
|
1
2
|
/**
|
|
2
3
|
* This augments the `Request` object from the Fetch API:
|
|
3
4
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request
|
|
@@ -16,6 +17,7 @@ export class ServerComponentRequest extends Request {
|
|
|
16
17
|
method: input.method,
|
|
17
18
|
});
|
|
18
19
|
}
|
|
20
|
+
this.time = getTime();
|
|
19
21
|
this.cookies = this.parseCookies();
|
|
20
22
|
}
|
|
21
23
|
parseCookies() {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { QueryKey } from '
|
|
2
|
-
import type { CacheOptions } from '../types';
|
|
1
|
+
import type { CacheOptions, QueryKey } from '../types';
|
|
3
2
|
export declare function generateCacheControlHeader(options: CacheOptions): string;
|
|
4
3
|
/**
|
|
5
4
|
* Use a preview header during development.
|
|
@@ -9,6 +8,7 @@ export declare function generateCacheControlHeader(options: CacheOptions): strin
|
|
|
9
8
|
export declare function getCacheControlHeader({ dev }: {
|
|
10
9
|
dev?: boolean;
|
|
11
10
|
}): "cache-control-preview" | "cache-control";
|
|
11
|
+
export declare function hashKey(key: QueryKey): string;
|
|
12
12
|
/**
|
|
13
13
|
* Get an item from the cache. If a match is found, returns a tuple
|
|
14
14
|
* containing the `JSON.parse` version of the response as well
|
|
@@ -21,7 +21,7 @@ export function generateCacheControlHeader(options) {
|
|
|
21
21
|
export function getCacheControlHeader({ dev }) {
|
|
22
22
|
return dev ? 'cache-control-preview' : 'cache-control';
|
|
23
23
|
}
|
|
24
|
-
function hashKey(key) {
|
|
24
|
+
export function hashKey(key) {
|
|
25
25
|
const rawKey = key instanceof Array ? key : [key];
|
|
26
26
|
/**
|
|
27
27
|
* TODO: Smarter hash
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="@types/node" />
|
|
2
|
-
import
|
|
2
|
+
import { ServerResponse } from 'http';
|
|
3
3
|
import type { ServerComponentRequest } from './framework/Hydration/ServerComponentRequest.server';
|
|
4
4
|
import { RuntimeContext } from './framework/runtime';
|
|
5
5
|
interface HydrogenFetchEvent {
|
|
@@ -27,7 +27,8 @@ export default async function handleEvent(event, { request, entrypoint, indexTem
|
|
|
27
27
|
throw new Error(`entry-server.jsx could not be loaded. This likely occurred because of a Vite compilation error.\n` +
|
|
28
28
|
`Please check your server logs for more information.`);
|
|
29
29
|
}
|
|
30
|
-
const
|
|
30
|
+
const userAgent = request.headers.get('user-agent');
|
|
31
|
+
const isStreamable = streamableResponse && !isBotUA(url, userAgent);
|
|
31
32
|
/**
|
|
32
33
|
* Stream back real-user responses, but for bots/etc,
|
|
33
34
|
* use `render` instead. This is because we need to inject <head>
|
|
@@ -35,7 +36,12 @@ export default async function handleEvent(event, { request, entrypoint, indexTem
|
|
|
35
36
|
*/
|
|
36
37
|
if (isStreamable) {
|
|
37
38
|
if (isReactHydrationRequest) {
|
|
38
|
-
hydrate(url, {
|
|
39
|
+
hydrate(url, {
|
|
40
|
+
context: {},
|
|
41
|
+
request,
|
|
42
|
+
response: streamableResponse,
|
|
43
|
+
dev,
|
|
44
|
+
});
|
|
39
45
|
}
|
|
40
46
|
else {
|
|
41
47
|
stream(url, {
|
|
@@ -48,7 +54,12 @@ export default async function handleEvent(event, { request, entrypoint, indexTem
|
|
|
48
54
|
}
|
|
49
55
|
return;
|
|
50
56
|
}
|
|
51
|
-
const { body, bodyAttributes, htmlAttributes, componentResponse, ...head } = await render(url, {
|
|
57
|
+
const { body, bodyAttributes, htmlAttributes, componentResponse, ...head } = await render(url, {
|
|
58
|
+
request,
|
|
59
|
+
context: {},
|
|
60
|
+
isReactHydrationRequest,
|
|
61
|
+
dev,
|
|
62
|
+
});
|
|
52
63
|
const headers = componentResponse.headers;
|
|
53
64
|
/**
|
|
54
65
|
* TODO: Also add `Vary` headers for `accept-language` and any other keys
|
|
@@ -86,13 +97,6 @@ export default async function handleEvent(event, { request, entrypoint, indexTem
|
|
|
86
97
|
}
|
|
87
98
|
return response;
|
|
88
99
|
}
|
|
89
|
-
function isStreamableRequest(url) {
|
|
90
|
-
/**
|
|
91
|
-
* TODO: Add UA detection.
|
|
92
|
-
*/
|
|
93
|
-
const isBot = url.searchParams.has('_bot');
|
|
94
|
-
return !isBot;
|
|
95
|
-
}
|
|
96
100
|
/**
|
|
97
101
|
* Generate the contents of the `head` tag, and update the existing `<title>` tag
|
|
98
102
|
* if one exists, and if a title is passed.
|
|
@@ -117,3 +121,57 @@ function generateHeadTag(head) {
|
|
|
117
121
|
return `<head>${headHtml}</head>`;
|
|
118
122
|
};
|
|
119
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Determines if the request is from a bot, using the URL and User Agent
|
|
126
|
+
*/
|
|
127
|
+
function isBotUA(url, userAgent) {
|
|
128
|
+
return (url.searchParams.has('_bot') || (!!userAgent && botUARegex.test(userAgent)));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* An alphabetized list of User Agents of known bots, combined from lists found at:
|
|
132
|
+
* https://github.com/vercel/next.js/blob/d87dc2b5a0b3fdbc0f6806a47be72bad59564bd0/packages/next/server/utils.ts#L18-L22
|
|
133
|
+
* https://github.com/GoogleChrome/rendertron/blob/6f681688737846b28754fbfdf5db173846a826df/middleware/src/middleware.ts#L24-L41
|
|
134
|
+
*/
|
|
135
|
+
const botUserAgents = [
|
|
136
|
+
'AdsBot-Google',
|
|
137
|
+
'applebot',
|
|
138
|
+
'Baiduspider',
|
|
139
|
+
'baiduspider',
|
|
140
|
+
'bingbot',
|
|
141
|
+
'Bingbot',
|
|
142
|
+
'BingPreview',
|
|
143
|
+
'bitlybot',
|
|
144
|
+
'Discordbot',
|
|
145
|
+
'DuckDuckBot',
|
|
146
|
+
'Embedly',
|
|
147
|
+
'facebookcatalog',
|
|
148
|
+
'facebookexternalhit',
|
|
149
|
+
'Google-PageRenderer',
|
|
150
|
+
'Googlebot',
|
|
151
|
+
'googleweblight',
|
|
152
|
+
'ia_archive',
|
|
153
|
+
'LinkedInBot',
|
|
154
|
+
'Mediapartners-Google',
|
|
155
|
+
'outbrain',
|
|
156
|
+
'pinterest',
|
|
157
|
+
'quora link preview',
|
|
158
|
+
'redditbot',
|
|
159
|
+
'rogerbot',
|
|
160
|
+
'showyoubot',
|
|
161
|
+
'SkypeUriPreview',
|
|
162
|
+
'Slackbot',
|
|
163
|
+
'Slurp',
|
|
164
|
+
'sogou',
|
|
165
|
+
'Storebot-Google',
|
|
166
|
+
'TelegramBot',
|
|
167
|
+
'tumblr',
|
|
168
|
+
'Twitterbot',
|
|
169
|
+
'vkShare',
|
|
170
|
+
'W3C_Validator',
|
|
171
|
+
'WhatsApp',
|
|
172
|
+
'yandex',
|
|
173
|
+
];
|
|
174
|
+
/**
|
|
175
|
+
* Creates a regex based on the botUserAgents array
|
|
176
|
+
*/
|
|
177
|
+
const botUARegex = new RegExp(botUserAgents.join('|'), 'i');
|
package/dist/worker/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="@types/node" />
|
|
2
|
-
import
|
|
2
|
+
import { ServerResponse } from 'http';
|
|
3
3
|
import type { ServerComponentResponse } from './framework/Hydration/ServerComponentResponse.server';
|
|
4
4
|
import type { ServerComponentRequest } from './framework/Hydration/ServerComponentRequest.server';
|
|
5
5
|
import type { Metafield, Image, MediaContentType } from './graphql/types/types';
|
|
@@ -78,6 +78,7 @@ export interface Measurement {
|
|
|
78
78
|
unit: string;
|
|
79
79
|
value: number;
|
|
80
80
|
}
|
|
81
|
+
export declare type QueryKey = string | readonly unknown[];
|
|
81
82
|
export interface CacheOptions {
|
|
82
83
|
private?: boolean;
|
|
83
84
|
maxAge?: number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Not all environments have access to Performance.now(). This is to prevent
|
|
3
|
+
* timing side channel attacks.
|
|
4
|
+
*
|
|
5
|
+
* See: https://community.cloudflare.com/t/cloudflare-workers-how-do-i-measure-execution-time-of-my-method/69672
|
|
6
|
+
*/
|
|
7
|
+
export declare function getTime(): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Not all environments have access to Performance.now(). This is to prevent
|
|
3
|
+
* timing side channel attacks.
|
|
4
|
+
*
|
|
5
|
+
* See: https://community.cloudflare.com/t/cloudflare-workers-how-do-i-measure-execution-time-of-my-method/69672
|
|
6
|
+
*/
|
|
7
|
+
export function getTime() {
|
|
8
|
+
if (typeof performance !== 'undefined' && performance.now) {
|
|
9
|
+
return performance.now();
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return Date.now();
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public",
|
|
5
5
|
"@shopify:registry": "https://registry.npmjs.org"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.8.2",
|
|
8
8
|
"description": "Modern custom Shopify storefronts",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"main": "dist/esnext/index.js",
|
|
@@ -68,36 +68,36 @@
|
|
|
68
68
|
"@types/react": "^17.0.3",
|
|
69
69
|
"@types/react-dom": "^17.0.3",
|
|
70
70
|
"@types/react-router-dom": "^5.1.7",
|
|
71
|
+
"@types/ws": "^8.2.0",
|
|
71
72
|
"babel-loader": "^8.2.2",
|
|
72
73
|
"cpy-cli": "3.1.1",
|
|
73
74
|
"mkdirp": "^1.0.4",
|
|
74
75
|
"postcss": "^8",
|
|
75
76
|
"raw-loader": "^4.0.2",
|
|
76
|
-
"rimraf": "^3.0.2"
|
|
77
|
-
"tailwindcss": "^2.1.1"
|
|
77
|
+
"rimraf": "^3.0.2"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
-
"react": "
|
|
81
|
-
"react-dom": "
|
|
80
|
+
"react": "0.0.0-experimental-0cc724c77-20211125",
|
|
81
|
+
"react-dom": "0.0.0-experimental-0cc724c77-20211125",
|
|
82
82
|
"react-router-dom": "^5.2.0",
|
|
83
|
-
"vite": "^2.
|
|
83
|
+
"vite": "^2.7.0"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@vitejs/plugin-react": "^1.
|
|
86
|
+
"@vitejs/plugin-react": "^1.1.1",
|
|
87
87
|
"connect": "^3.7.0",
|
|
88
88
|
"es-module-lexer": "^0.9.0",
|
|
89
89
|
"fast-glob": "^3.2.5",
|
|
90
|
-
"graphql": "^
|
|
90
|
+
"graphql": "^16.0.1",
|
|
91
91
|
"html-dom-parser": "^1.0.1",
|
|
92
92
|
"html-react-parser": "^1.2.6",
|
|
93
93
|
"isomorphic-dompurify": "^0.13.0",
|
|
94
|
+
"kolorist": "^1.5.1",
|
|
94
95
|
"magic-string": "^0.25.7",
|
|
95
96
|
"node-fetch": "^2.6.1",
|
|
96
97
|
"react-error-boundary": "^3.1.3",
|
|
97
98
|
"react-helmet-async": "^1.0.9",
|
|
98
|
-
"react-query": "^3.18.1",
|
|
99
99
|
"react-ssr-prepass": "^1.4.0",
|
|
100
100
|
"vite-plugin-inspect": "^0.3.6"
|
|
101
101
|
},
|
|
102
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "587f117221ab94a06165e69602658c4e561f5723"
|
|
103
103
|
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import type { ReactQueryHydrationContext } from '../../foundation/ShopifyProvider/types';
|
|
3
|
-
export declare function QueryProvider({ children, hydrationContext, }: {
|
|
4
|
-
children: ReactNode;
|
|
5
|
-
hydrationContext?: ReactQueryHydrationContext;
|
|
6
|
-
}): JSX.Element;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { QueryClientProvider, QueryClient } from 'react-query';
|
|
3
|
-
import { Hydrate } from 'react-query/hydration';
|
|
4
|
-
export function QueryProvider({ children, hydrationContext, }) {
|
|
5
|
-
const queryClient = new QueryClient({
|
|
6
|
-
defaultOptions: { queries: { suspense: true } },
|
|
7
|
-
});
|
|
8
|
-
if (hydrationContext) {
|
|
9
|
-
hydrationContext.queryClient = queryClient;
|
|
10
|
-
}
|
|
11
|
-
return (React.createElement(QueryClientProvider, { client: queryClient },
|
|
12
|
-
React.createElement(Hydrate, { state: hydrationContext === null || hydrationContext === void 0 ? void 0 : hydrationContext.dehydratedState }, children)));
|
|
13
|
-
}
|