@shopify/hydrogen 1.3.1 → 1.3.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/entry-client.js +1 -1
- package/dist/esnext/entry-server.js +20 -25
- package/dist/esnext/foundation/HydrogenResponse/HydrogenResponse.server.d.ts +4 -0
- package/dist/esnext/foundation/HydrogenResponse/HydrogenResponse.server.js +16 -1
- package/dist/esnext/foundation/fetchSync/ResponseSync.d.ts +2 -1
- package/dist/esnext/foundation/fetchSync/ResponseSync.js +14 -2
- package/dist/esnext/framework/plugin.js +2 -2
- package/dist/esnext/framework/plugins/vite-plugin-assets-version.js +4 -0
- package/dist/esnext/framework/plugins/vite-plugin-client-imports.js +6 -3
- package/dist/esnext/framework/plugins/vite-plugin-css-modules-rsc.js +3 -0
- package/dist/esnext/framework/plugins/vite-plugin-css-rsc.js +8 -0
- package/dist/esnext/framework/plugins/vite-plugin-hydration-auto-import.js +7 -1
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-client-components-cache.d.ts +3 -0
- package/dist/esnext/framework/plugins/{vite-plugin-hydrogen-client-middleware.js → vite-plugin-hydrogen-client-components-cache.js} +2 -2
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +101 -91
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +6 -6
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +5 -0
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-virtual-files.js +21 -1
- package/dist/esnext/framework/plugins/vite-plugin-platform-entry.js +14 -1
- package/dist/esnext/framework/plugins/vite-plugin-ssr-interop.js +5 -1
- package/dist/esnext/framework/viteception.js +7 -1
- package/dist/esnext/types.d.ts +2 -1
- package/dist/esnext/utilities/apiRoutes.d.ts +2 -0
- package/dist/esnext/utilities/apiRoutes.js +1 -0
- package/dist/esnext/utilities/log/log.js +12 -3
- package/dist/esnext/utilities/template.d.ts +7 -6
- package/dist/esnext/utilities/template.js +39 -1
- package/dist/esnext/utilities/vite.d.ts +1 -0
- package/dist/esnext/utilities/vite.js +4 -0
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/node/framework/plugin.js +2 -2
- package/dist/node/framework/plugins/vite-plugin-assets-version.js +4 -0
- package/dist/node/framework/plugins/vite-plugin-client-imports.js +6 -3
- package/dist/node/framework/plugins/vite-plugin-css-modules-rsc.js +3 -0
- package/dist/node/framework/plugins/vite-plugin-css-rsc.js +8 -0
- package/dist/node/framework/plugins/vite-plugin-hydration-auto-import.js +7 -1
- package/dist/node/framework/plugins/vite-plugin-hydrogen-client-components-cache.d.ts +3 -0
- package/dist/node/framework/plugins/{vite-plugin-hydrogen-client-middleware.js → vite-plugin-hydrogen-client-components-cache.js} +2 -2
- package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +101 -91
- package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +6 -6
- package/dist/node/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +5 -0
- package/dist/node/framework/plugins/vite-plugin-hydrogen-virtual-files.js +21 -1
- package/dist/node/framework/plugins/vite-plugin-platform-entry.js +14 -1
- package/dist/node/framework/plugins/vite-plugin-ssr-interop.js +5 -1
- package/dist/node/framework/viteception.js +7 -1
- package/dist/node/utilities/vite.d.ts +1 -0
- package/dist/node/utilities/vite.js +30 -0
- package/package.json +3 -3
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +31 -21
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +105 -29
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +30 -29
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +92 -29
- package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +31 -29
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +24 -14
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +105 -29
- package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +92 -29
- package/vendor/react-server-dom-vite/package.json +2 -2
- package/dist/esnext/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +0 -9
- package/dist/node/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +0 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { Suspense, useState, StrictMode, Fragment, useEffect, } from 'react';
|
|
2
2
|
import { hydrateRoot } from 'react-dom/client';
|
|
3
|
-
import { ErrorBoundary } from 'react-error-boundary';
|
|
3
|
+
import { ErrorBoundary } from 'react-error-boundary/dist/react-error-boundary.esm';
|
|
4
4
|
import { createFromFetch, createFromReadableStream,
|
|
5
5
|
// @ts-ignore
|
|
6
6
|
} from '@shopify/hydrogen/vendor/react-server-dom-vite';
|
|
@@ -10,7 +10,7 @@ import { ServerPropsProvider } from './foundation/ServerPropsProvider/index.js';
|
|
|
10
10
|
import { isBotUA } from './utilities/bot-ua.js';
|
|
11
11
|
import { getCache, setCache } from './foundation/runtime.js';
|
|
12
12
|
import { ssrRenderToPipeableStream, ssrRenderToReadableStream, rscRenderToReadableStream, createFromReadableStream, bufferReadableStream, } from './streaming.server.js';
|
|
13
|
-
import {
|
|
13
|
+
import { getTemplate } from './utilities/template.js';
|
|
14
14
|
import { Analytics } from './foundation/Analytics/Analytics.server.js';
|
|
15
15
|
import { DevTools } from './foundation/DevTools/DevTools.server.js';
|
|
16
16
|
import { getSyncSessionApi } from './foundation/session/session.js';
|
|
@@ -21,6 +21,13 @@ import { deleteItemFromCache, getItemFromCache, isStale, setItemInCache, } from
|
|
|
21
21
|
import { CacheShort, NO_STORE } from './foundation/Cache/strategies/index.js';
|
|
22
22
|
import { getBuiltInRoute } from './foundation/BuiltInRoutes/BuiltInRoutes.js';
|
|
23
23
|
import { FORM_REDIRECT_COOKIE } from './constants.js';
|
|
24
|
+
// Importing 'stream' directly breaks Vite resolve
|
|
25
|
+
// when building for workers, even though this code
|
|
26
|
+
// does not run in a worker. Looks like tree-shaking
|
|
27
|
+
// kicks in after the import analysis/bundle.
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
import stream from 'virtual__stream';
|
|
30
|
+
const PassThrough = stream.PassThrough;
|
|
24
31
|
const DOCTYPE = '<!DOCTYPE html>';
|
|
25
32
|
const CONTENT_TYPE = 'Content-Type';
|
|
26
33
|
const HTML_CONTENT_TYPE = 'text/html; charset=UTF-8';
|
|
@@ -45,7 +52,7 @@ export const renderHydrogen = (App) => {
|
|
|
45
52
|
request.ctx.buyerIpHeader = buyerIpHeader;
|
|
46
53
|
setLogger(hydrogenConfig.logger);
|
|
47
54
|
const log = getLoggerWithContext(request);
|
|
48
|
-
const response = new HydrogenResponse(null, {
|
|
55
|
+
const response = new HydrogenResponse(request.url, null, {
|
|
49
56
|
headers: headers || {},
|
|
50
57
|
});
|
|
51
58
|
if (request.cookies.get(FORM_REDIRECT_COOKIE)) {
|
|
@@ -97,6 +104,7 @@ export const renderHydrogen = (App) => {
|
|
|
97
104
|
maxAge: 10,
|
|
98
105
|
}));
|
|
99
106
|
await processRequest(handleRequest, App, url, request, sessionApi, options, response, hydrogenConfig, true);
|
|
107
|
+
response.markAsSent();
|
|
100
108
|
}
|
|
101
109
|
catch (e) {
|
|
102
110
|
log.error('Cache revalidate error', e);
|
|
@@ -108,7 +116,9 @@ export const renderHydrogen = (App) => {
|
|
|
108
116
|
return cachedResponse;
|
|
109
117
|
}
|
|
110
118
|
}
|
|
111
|
-
|
|
119
|
+
const result = await processRequest(handleRequest, App, url, request, sessionApi, options, response, hydrogenConfig);
|
|
120
|
+
response.markAsSent();
|
|
121
|
+
return result;
|
|
112
122
|
};
|
|
113
123
|
if (__HYDROGEN_WORKER__)
|
|
114
124
|
return handleRequest;
|
|
@@ -161,19 +171,10 @@ async function processRequest(handleRequest, App, url, request, sessionApi, opti
|
|
|
161
171
|
request,
|
|
162
172
|
response,
|
|
163
173
|
nodeResponse,
|
|
164
|
-
template: await getTemplate(indexTemplate, url),
|
|
165
174
|
revalidate,
|
|
175
|
+
template: await getTemplate(indexTemplate, url),
|
|
166
176
|
});
|
|
167
177
|
}
|
|
168
|
-
async function getTemplate(indexTemplate, url) {
|
|
169
|
-
let template = typeof indexTemplate === 'function'
|
|
170
|
-
? await indexTemplate(url.toString())
|
|
171
|
-
: indexTemplate;
|
|
172
|
-
if (template && typeof template !== 'string') {
|
|
173
|
-
template = template.default;
|
|
174
|
-
}
|
|
175
|
-
return template;
|
|
176
|
-
}
|
|
177
178
|
function getApiRoute(url, routes) {
|
|
178
179
|
const apiRoutes = getApiRoutes(routes);
|
|
179
180
|
return getApiRouteFromURL(url, apiRoutes);
|
|
@@ -192,18 +193,21 @@ function assembleHtml({ ssrHtml, rscPayload, request, template, }) {
|
|
|
192
193
|
* Run the SSR/Fizz part of the App. If streaming is disabled,
|
|
193
194
|
* this buffers the output and applies SEO enhancements.
|
|
194
195
|
*/
|
|
195
|
-
async function runSSR({ rsc, state, request, response, nodeResponse,
|
|
196
|
+
async function runSSR({ rsc, state, request, response, nodeResponse, nonce, dev, log, revalidate, template: { raw: template, noScriptTemplate, bootstrapModules, bootstrapScripts, linkHeader, }, }) {
|
|
196
197
|
let ssrDidError;
|
|
197
198
|
const didError = () => rsc.didError() ?? ssrDidError;
|
|
198
199
|
const [rscReadableForFizz, rscReadableForFlight] = rsc.readable.tee();
|
|
199
200
|
const rscResponse = createFromReadableStream(rscReadableForFizz);
|
|
200
201
|
const RscConsumer = () => rscResponse.readRoot();
|
|
201
|
-
const { noScriptTemplate, bootstrapScripts, bootstrapModules } = stripScriptsFromTemplate(template);
|
|
202
202
|
const AppSSR = (React.createElement(Html, { template: response.canStream() ? noScriptTemplate : template, hydrogenConfig: request.ctx.hydrogenConfig },
|
|
203
203
|
React.createElement(ServerRequestProvider, { request: request },
|
|
204
204
|
React.createElement(ServerPropsProvider, { initialServerProps: state, setServerPropsForRsc: () => { }, setRscResponseFromApiRoute: () => { } },
|
|
205
205
|
React.createElement(Suspense, { fallback: null },
|
|
206
206
|
React.createElement(RscConsumer, null))))));
|
|
207
|
+
if (linkHeader) {
|
|
208
|
+
const existingLinkHeader = response.headers.get('Link');
|
|
209
|
+
response.headers.set('Link', existingLinkHeader ? existingLinkHeader + ', ' + linkHeader : linkHeader);
|
|
210
|
+
}
|
|
207
211
|
log.trace('start ssr');
|
|
208
212
|
const rscReadable = response.canStream()
|
|
209
213
|
? new ReadableStream({
|
|
@@ -380,7 +384,7 @@ async function runSSR({ rsc, state, request, response, nodeResponse, template, n
|
|
|
380
384
|
// Redirects found after any async code
|
|
381
385
|
return nodeResponse.end();
|
|
382
386
|
}
|
|
383
|
-
const bufferedResponse =
|
|
387
|
+
const bufferedResponse = new PassThrough();
|
|
384
388
|
const bufferedRscPromise = bufferReadableStream(rscReadable.getReader());
|
|
385
389
|
let ssrHtml = '';
|
|
386
390
|
bufferedResponse.on('data', (chunk) => (ssrHtml += chunk.toString()));
|
|
@@ -499,15 +503,6 @@ function isRedirect(response) {
|
|
|
499
503
|
const status = response.status ?? response.statusCode ?? 0;
|
|
500
504
|
return status >= 300 && status < 400;
|
|
501
505
|
}
|
|
502
|
-
async function createNodeWriter() {
|
|
503
|
-
// Importing 'stream' directly breaks Vite resolve
|
|
504
|
-
// when building for workers, even though this code
|
|
505
|
-
// does not run in a worker. Looks like tree-shaking
|
|
506
|
-
// kicks in after the import analysis/bundle.
|
|
507
|
-
const streamImport = __HYDROGEN_WORKER__ ? '' : 'stream';
|
|
508
|
-
const { PassThrough } = await import(streamImport);
|
|
509
|
-
return new PassThrough();
|
|
510
|
-
}
|
|
511
506
|
function flightContainer(chunk) {
|
|
512
507
|
return `<meta data-flight="${htmlEncode(chunk)}" />`;
|
|
513
508
|
}
|
|
@@ -2,9 +2,13 @@ import type { CachingStrategy } from '../../types.js';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export declare class HydrogenResponse extends Response {
|
|
4
4
|
private wait;
|
|
5
|
+
private sent;
|
|
5
6
|
private cacheOptions;
|
|
6
7
|
status: number;
|
|
7
8
|
statusText: string;
|
|
9
|
+
url: string;
|
|
10
|
+
constructor(url: string, body: any, init: any);
|
|
11
|
+
markAsSent(): void;
|
|
8
12
|
/**
|
|
9
13
|
* Buffer the current response until all queries have resolved,
|
|
10
14
|
* and prevent it from streaming back early.
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { CacheShort, generateCacheControlHeader, } from '../Cache/strategies/index.js';
|
|
2
2
|
import Redirect from '../Redirect/Redirect.client.js';
|
|
3
3
|
import React from 'react';
|
|
4
|
+
import { log } from '../../utilities/log/log.js';
|
|
4
5
|
export class HydrogenResponse extends Response {
|
|
5
6
|
wait = false;
|
|
7
|
+
sent = false;
|
|
6
8
|
cacheOptions = CacheShort();
|
|
7
9
|
status = 200;
|
|
8
10
|
statusText = '';
|
|
11
|
+
url;
|
|
12
|
+
constructor(url, body, init) {
|
|
13
|
+
super(body, init);
|
|
14
|
+
this.url = url;
|
|
15
|
+
}
|
|
16
|
+
markAsSent() {
|
|
17
|
+
this.sent = true;
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
20
|
* Buffer the current response until all queries have resolved,
|
|
11
21
|
* and prevent it from streaming back early.
|
|
12
22
|
*/
|
|
13
23
|
doNotStream() {
|
|
14
|
-
this.
|
|
24
|
+
if (!this.sent) {
|
|
25
|
+
this.wait = true;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
log.warn(`response.doNotStream() failed, the stream has already started on: ${this.url}\nDisabling streaming should always be the first thing in your route server component.`);
|
|
29
|
+
}
|
|
15
30
|
}
|
|
16
31
|
canStream() {
|
|
17
32
|
return !this.wait;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
declare type ResponseSyncInit = [string, ResponseInit];
|
|
1
|
+
declare type ResponseSyncInit = [string, ResponseInit, string];
|
|
2
2
|
export declare class ResponseSync extends Response {
|
|
3
3
|
#private;
|
|
4
4
|
bodyUsed: boolean;
|
|
5
|
+
url: string;
|
|
5
6
|
constructor(init: ResponseSyncInit);
|
|
6
7
|
text(): string;
|
|
7
8
|
json(): any;
|
|
@@ -4,16 +4,27 @@ export class ResponseSync extends Response {
|
|
|
4
4
|
bodyUsed = true;
|
|
5
5
|
#text;
|
|
6
6
|
#json;
|
|
7
|
+
url;
|
|
7
8
|
constructor(init) {
|
|
8
|
-
super(
|
|
9
|
+
super(init[0], init[1]);
|
|
9
10
|
this.#text = init[0];
|
|
11
|
+
this.url = init[2];
|
|
10
12
|
}
|
|
11
13
|
// @ts-expect-error Changing inherited types
|
|
12
14
|
text() {
|
|
13
15
|
return this.#text;
|
|
14
16
|
}
|
|
15
17
|
json() {
|
|
16
|
-
|
|
18
|
+
try {
|
|
19
|
+
return (this.#json ??= parseJSON(this.#text));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
if (!this.ok) {
|
|
23
|
+
throw new Error(`Request to ${this.url} failed with ${this.status} and the response body is not parseable.\nMake sure to handle the error state when using fetchSync.`);
|
|
24
|
+
}
|
|
25
|
+
else
|
|
26
|
+
throw e;
|
|
27
|
+
}
|
|
17
28
|
}
|
|
18
29
|
/**
|
|
19
30
|
* @deprecated Access response properties at the top level instead.
|
|
@@ -33,6 +44,7 @@ export class ResponseSync extends Response {
|
|
|
33
44
|
statusText: response.statusText,
|
|
34
45
|
headers: Array.from(response.headers.entries()),
|
|
35
46
|
},
|
|
47
|
+
response.url,
|
|
36
48
|
];
|
|
37
49
|
}
|
|
38
50
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import hydrogenConfig from './plugins/vite-plugin-hydrogen-config.js';
|
|
2
2
|
import hydrogenMiddleware from './plugins/vite-plugin-hydrogen-middleware.js';
|
|
3
|
-
import
|
|
3
|
+
import hydrogenClientComponentsCache from './plugins/vite-plugin-hydrogen-client-components-cache.js';
|
|
4
4
|
import hydrogenVirtualFiles from './plugins/vite-plugin-hydrogen-virtual-files.js';
|
|
5
5
|
import platformEntry from './plugins/vite-plugin-platform-entry.js';
|
|
6
6
|
import rsc from './plugins/vite-plugin-hydrogen-rsc.js';
|
|
@@ -17,7 +17,7 @@ const hydrogenPlugin = (pluginOptions = {}) => {
|
|
|
17
17
|
return [
|
|
18
18
|
process.env.VITE_INSPECT && inspect(),
|
|
19
19
|
hydrogenConfig(pluginOptions),
|
|
20
|
-
|
|
20
|
+
hydrogenClientComponentsCache(),
|
|
21
21
|
clientImports(),
|
|
22
22
|
hydrogenMiddleware(pluginOptions),
|
|
23
23
|
hydrogenVirtualFiles(pluginOptions),
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/* -- Plugin notes:
|
|
2
|
+
* This plugin allows to import always from '@shopify/hydrogen' path, instead of
|
|
3
|
+
* using '@shopify/hydrogen/client' in browser files. It does this by redirecting
|
|
4
|
+
* the server path to the browser path if the importer file is a client component.
|
|
5
|
+
*/
|
|
1
6
|
export default function clientImports() {
|
|
2
7
|
return {
|
|
3
8
|
name: 'hydrogen:client-imports',
|
|
@@ -14,9 +19,7 @@ export default function clientImports() {
|
|
|
14
19
|
return;
|
|
15
20
|
if ('@shopify/hydrogen' !== source)
|
|
16
21
|
return;
|
|
17
|
-
const resolution = await this.resolve('@shopify/hydrogen/client', importer, {
|
|
18
|
-
skipSelf: true,
|
|
19
|
-
});
|
|
22
|
+
const resolution = await this.resolve('@shopify/hydrogen/client', importer, { skipSelf: true });
|
|
20
23
|
if (resolution) {
|
|
21
24
|
return resolution.id;
|
|
22
25
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { HYDROGEN_DEFAULT_SERVER_ENTRY } from './vite-plugin-hydrogen-middleware.js';
|
|
2
2
|
import MagicString from 'magic-string';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
/* -- Plugin notes:
|
|
5
|
+
* Old approach to inlining CSS inside server components. This is deprecated.
|
|
6
|
+
*/
|
|
4
7
|
const cssModuleRE = /\.module\.(s?css|sass|less|stylus)/;
|
|
5
8
|
export default function cssModulesRsc() {
|
|
6
9
|
// 1. Original CSS module: `.myStyle { color: red; }`
|
|
@@ -6,6 +6,14 @@ const INJECT_STYLES_COMMENT = '<!--__INJECT_STYLES__-->';
|
|
|
6
6
|
// Keep this in the outer scope to share it
|
|
7
7
|
// across client <> server builds.
|
|
8
8
|
let clientBuildPath;
|
|
9
|
+
/* -- Plugin notes:
|
|
10
|
+
* This plugin collects all the CSS imported in both client and server components and
|
|
11
|
+
* extracts it in a single stylesheet that is added to the <head>. It does this by:
|
|
12
|
+
* 1. Removing all the CSS generated during the client build. The client build CSS is a sub-set of the
|
|
13
|
+
* server build CSS because it can only find CSS imported in client components. This avoids duplicates.
|
|
14
|
+
* 2. Force Vite to collect CSS in every file during the server build, and emit it as a chunk.
|
|
15
|
+
* 3. Move the generated CSS chunk in the server build to the client build output as an asset, and link to it in `index.html`.
|
|
16
|
+
*/
|
|
9
17
|
export default function cssRsc() {
|
|
10
18
|
let config;
|
|
11
19
|
return {
|
|
@@ -2,10 +2,16 @@ import { normalizePath } from 'vite';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import MagicString from 'magic-string';
|
|
4
4
|
const HYDROGEN_ENTRY_FILE = 'hydrogen-entry-client.jsx';
|
|
5
|
+
/* -- Plugin notes:
|
|
6
|
+
* Originally, every Hydrogen app required a `src/entry-client.jsx` file. However, this file
|
|
7
|
+
* was rarely modified by the user. This plugin provides a virtual file with the same content of
|
|
8
|
+
* that file, which allows to remove it by default from the file system.
|
|
9
|
+
* The virtual file created here is imported in `index.html` in a script tag.
|
|
10
|
+
*/
|
|
5
11
|
export default () => {
|
|
6
12
|
let config;
|
|
7
13
|
return {
|
|
8
|
-
name: '
|
|
14
|
+
name: 'hydrogen:client-hydration-auto-import',
|
|
9
15
|
enforce: 'pre',
|
|
10
16
|
configResolved(_config) {
|
|
11
17
|
config = _config;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { send } from 'vite';
|
|
2
|
-
|
|
2
|
+
/* -- Plugin notes:
|
|
3
3
|
* This dev server middleware prevents Vite from applying immutable cache control headers to client
|
|
4
4
|
* components. These client components are part of the user's local source, but since they are
|
|
5
5
|
* referenced via import globs in the `react-dom-server-vite` NPM package, Vite assumes they
|
|
@@ -7,7 +7,7 @@ import { send } from 'vite';
|
|
|
7
7
|
*/
|
|
8
8
|
export default () => {
|
|
9
9
|
return {
|
|
10
|
-
name: '
|
|
10
|
+
name: 'hydrogen:client-components-cache',
|
|
11
11
|
enforce: 'pre',
|
|
12
12
|
configureServer(server) {
|
|
13
13
|
server.middlewares.use(async (req, res, next) => {
|
|
@@ -1,106 +1,116 @@
|
|
|
1
1
|
import Crypto from 'crypto';
|
|
2
|
+
/* -- Plugin notes:
|
|
3
|
+
* Provide configuration options to Vite to ensure Hydrogen is built correctly
|
|
4
|
+
* for worker environments, using latest ES syntax, and some other requirements.
|
|
5
|
+
*/
|
|
2
6
|
export default (pluginOptions) => {
|
|
3
7
|
const rollupOptions = {
|
|
4
8
|
output: {},
|
|
5
9
|
};
|
|
6
10
|
const isWorker = Boolean(process.env.WORKER) && process.env.WORKER !== 'undefined';
|
|
7
|
-
if (isWorker) {
|
|
8
|
-
/**
|
|
9
|
-
* By default, SSR dedupe logic gets bundled which runs `require('module')`.
|
|
10
|
-
* We don't want this in our workers runtime, because `require` is not supported.
|
|
11
|
-
*/
|
|
12
|
-
rollupOptions.output = {
|
|
13
|
-
format: 'es',
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
if (process.env.NODE_ENV !== 'development' && !process.env.LOCAL_DEV) {
|
|
17
|
-
/**
|
|
18
|
-
* Ofuscate production asset name - To prevent ad blocker logics that blocks
|
|
19
|
-
* certain files due to how it is named.
|
|
20
|
-
*/
|
|
21
|
-
rollupOptions.output = {
|
|
22
|
-
...rollupOptions.output,
|
|
23
|
-
chunkFileNames: 'assets/[hash].js',
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
11
|
return {
|
|
27
12
|
name: 'hydrogen:config',
|
|
28
|
-
config: async (config, env) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
: rollupOptions,
|
|
41
|
-
target: config.build?.ssr
|
|
42
|
-
? isWorker
|
|
43
|
-
? 'es2022' // CFW (Updates weekly to latest V8)
|
|
44
|
-
: 'es2020' // Node (Support for v14.19 used in SB)
|
|
45
|
-
: 'modules', // Browsers (Vite default value)
|
|
46
|
-
},
|
|
47
|
-
ssr: {
|
|
13
|
+
config: async (config, env) => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const isSsrBuild = env.ssrBuild ?? !!config.build?.ssr;
|
|
16
|
+
/**
|
|
17
|
+
* By default, SSR dedupe logic gets bundled which runs `require('module')`.
|
|
18
|
+
* We don't want this in our workers runtime, because `require` is not supported.
|
|
19
|
+
*/
|
|
20
|
+
rollupOptions.output = {
|
|
21
|
+
format: isWorker || !isSsrBuild ? 'es' : 'cjs',
|
|
22
|
+
inlineDynamicImports: isSsrBuild ? true : undefined,
|
|
23
|
+
};
|
|
24
|
+
if (process.env.NODE_ENV !== 'development' && !process.env.LOCAL_DEV) {
|
|
48
25
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
26
|
+
* Ofuscate production asset name - To prevent ad blocker logics that blocks
|
|
27
|
+
* certain files due to how it is named.
|
|
51
28
|
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
29
|
+
rollupOptions.output = {
|
|
30
|
+
...rollupOptions.output,
|
|
31
|
+
chunkFileNames: 'assets/[hash].js',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
resolve: {
|
|
36
|
+
alias: {
|
|
37
|
+
// This library is currently included as a compiled vendor lib, not published yet to NPM
|
|
38
|
+
'react-server-dom-vite/client-proxy': require.resolve('@shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js'),
|
|
39
|
+
},
|
|
62
40
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*/
|
|
77
|
-
'react-helmet-async',
|
|
78
|
-
'react-error-boundary',
|
|
41
|
+
build: {
|
|
42
|
+
minify: config.build?.minify ?? (process.env.LOCAL_DEV ? false : 'esbuild'),
|
|
43
|
+
sourcemap: true,
|
|
44
|
+
rollupOptions: config.build?.rollupOptions
|
|
45
|
+
? Object.assign(rollupOptions, config.build.rollupOptions)
|
|
46
|
+
: rollupOptions,
|
|
47
|
+
target: config.build?.ssr
|
|
48
|
+
? isWorker
|
|
49
|
+
? 'es2022' // CFW (Updates weekly to latest V8)
|
|
50
|
+
: 'es2020' // Node (Support for v14.19 used in SB)
|
|
51
|
+
: 'modules', // Browsers (Vite default value)
|
|
52
|
+
},
|
|
53
|
+
ssr: {
|
|
79
54
|
/**
|
|
80
|
-
* Vite
|
|
81
|
-
*
|
|
82
|
-
* at server start to avoid posterior page reloads and issues (#429 #430).
|
|
55
|
+
* Tell Vite to bundle everything when we're building for Workers.
|
|
56
|
+
* Otherwise, bundle RSC plugin as a workaround to apply the vendor alias above.
|
|
83
57
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
'
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
58
|
+
noExternal: isWorker || [
|
|
59
|
+
/react-server-dom-vite/,
|
|
60
|
+
/@shopify\/hydrogen/,
|
|
61
|
+
],
|
|
62
|
+
target: isWorker ? 'webworker' : 'node',
|
|
63
|
+
},
|
|
64
|
+
// Reload when updating local Hydrogen lib
|
|
65
|
+
server: process.env.LOCAL_DEV && {
|
|
66
|
+
watch: {
|
|
67
|
+
ignored: [
|
|
68
|
+
'!**/node_modules/@shopify/hydrogen/**',
|
|
69
|
+
'!**/node_modules/@shopify/hydrogen-ui/**',
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
optimizeDeps: {
|
|
74
|
+
exclude: [
|
|
75
|
+
'@shopify/hydrogen',
|
|
76
|
+
'@shopify/hydrogen/client',
|
|
77
|
+
'@shopify/hydrogen/entry-client',
|
|
78
|
+
'@shopify/hydrogen-ui',
|
|
79
|
+
],
|
|
80
|
+
include: [
|
|
81
|
+
/**
|
|
82
|
+
* Additionally, the following dependencies have trouble loading the
|
|
83
|
+
* correct version of the dependency (server vs client). This tells Vite to take the
|
|
84
|
+
* server versions and optimize them for ESM.
|
|
85
|
+
*/
|
|
86
|
+
'react-helmet-async',
|
|
87
|
+
'react-error-boundary',
|
|
88
|
+
/**
|
|
89
|
+
* Vite cannot find the following dependencies since they might be
|
|
90
|
+
* required in RSC asynchronously. This tells Vite to optimize them
|
|
91
|
+
* at server start to avoid posterior page reloads and issues (#429 #430).
|
|
92
|
+
*/
|
|
93
|
+
'react',
|
|
94
|
+
'react-dom/client',
|
|
95
|
+
'react-server-dom-vite/client-proxy',
|
|
96
|
+
// https://github.com/vitejs/vite/issues/6215
|
|
97
|
+
'react/jsx-runtime',
|
|
98
|
+
// https://github.com/nfriedly/set-cookie-parser/issues/50
|
|
99
|
+
'set-cookie-parser',
|
|
100
|
+
'undici',
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
define: {
|
|
104
|
+
__HYDROGEN_DEV__: env.mode !== 'production',
|
|
105
|
+
__HYDROGEN_WORKER__: isWorker,
|
|
106
|
+
__HYDROGEN_TEST__: false,
|
|
107
|
+
__HYDROGEN_CACHE_ID__: pluginOptions.purgeQueryCacheOnBuild
|
|
108
|
+
? `"${Crypto.randomBytes(8).toString('hex').slice(0, 8)}"`
|
|
109
|
+
: '"__QUERY_CACHE_ID__"',
|
|
110
|
+
},
|
|
111
|
+
envPrefix: ['VITE_', 'PUBLIC_'],
|
|
112
|
+
base: process.env.HYDROGEN_ASSET_BASE_URL,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
105
115
|
};
|
|
106
116
|
};
|
|
@@ -6,15 +6,15 @@ import { hydrogenMiddleware, graphiqlMiddleware } from '../middleware.js';
|
|
|
6
6
|
import { InMemoryCache } from '../cache/in-memory.js';
|
|
7
7
|
import { VIRTUAL_PROXY_HYDROGEN_CONFIG_ID } from './vite-plugin-hydrogen-virtual-files.js';
|
|
8
8
|
export const HYDROGEN_DEFAULT_SERVER_ENTRY = process.env.HYDROGEN_SERVER_ENTRY || '/src/App.server';
|
|
9
|
+
/* -- Plugin notes:
|
|
10
|
+
* By adding a middleware to the Vite dev server, we can handle SSR without needing
|
|
11
|
+
* a custom node script. It works by handling any requests for `text/html` documents,
|
|
12
|
+
* loading them in an SSR context, rendering them using the `entry-server` endpoint in the
|
|
13
|
+
* user's project, and injecting the static HTML into the template.
|
|
14
|
+
*/
|
|
9
15
|
export default (pluginOptions) => {
|
|
10
16
|
return {
|
|
11
17
|
name: 'hydrogen:middleware',
|
|
12
|
-
/**
|
|
13
|
-
* By adding a middleware to the Vite dev server, we can handle SSR without needing
|
|
14
|
-
* a custom node script. It works by handling any requests for `text/html` documents,
|
|
15
|
-
* loading them in an SSR context, rendering them using the `entry-server` endpoint in the
|
|
16
|
-
* user's project, and injecting the static HTML into the template.
|
|
17
|
-
*/
|
|
18
18
|
async configureServer(server) {
|
|
19
19
|
const resolve = (p) => path.resolve(server.config.root, p);
|
|
20
20
|
async function getIndexTemplate(url) {
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/* -- Plugin notes:
|
|
2
|
+
* Vite prints some warnings automatically are not important and
|
|
3
|
+
* not actionable. We hide them here to prevent confusing devs when
|
|
4
|
+
* real warnings or errors appear.
|
|
5
|
+
*/
|
|
1
6
|
export default () => {
|
|
2
7
|
return {
|
|
3
8
|
name: 'hydrogen:suppress-warnings',
|
|
@@ -3,6 +3,14 @@ import path from 'path';
|
|
|
3
3
|
import { promises as fs } from 'fs';
|
|
4
4
|
import { viteception } from '../viteception.js';
|
|
5
5
|
import MagicString from 'magic-string';
|
|
6
|
+
import { isVite3 } from '../../utilities/vite.js';
|
|
7
|
+
/* -- Plugin notes:
|
|
8
|
+
* The Hydrogen framework needs to import certain files from the user app, such as
|
|
9
|
+
* routes and config. A priori, we can't import these files from the framework
|
|
10
|
+
* because we don't know the user path to write it in an `import * from '...'` statement.
|
|
11
|
+
* Instead, we import "virtual files" that are resolved by Vite in this plugin.
|
|
12
|
+
* These virtual files can include the user path and re-export the in-app files.
|
|
13
|
+
*/
|
|
6
14
|
export const HYDROGEN_DEFAULT_SERVER_ENTRY = process.env.HYDROGEN_SERVER_ENTRY || '/src/App.server';
|
|
7
15
|
// The character ":" breaks Vite with Node >= 16.15. Use "_" instead
|
|
8
16
|
const VIRTUAL_PREFIX = 'virtual__';
|
|
@@ -15,6 +23,7 @@ export const VIRTUAL_PROXY_HYDROGEN_CONFIG_ID = VIRTUAL_PREFIX + PROXY_PREFIX +
|
|
|
15
23
|
const HYDROGEN_ROUTES_ID = 'hydrogen-routes.server.jsx';
|
|
16
24
|
const VIRTUAL_HYDROGEN_ROUTES_ID = VIRTUAL_PREFIX + HYDROGEN_ROUTES_ID;
|
|
17
25
|
export const VIRTUAL_PROXY_HYDROGEN_ROUTES_ID = VIRTUAL_PREFIX + PROXY_PREFIX + HYDROGEN_ROUTES_ID;
|
|
26
|
+
const VIRTUAL_STREAM_ID = 'virtual__stream';
|
|
18
27
|
export default (pluginOptions) => {
|
|
19
28
|
let config;
|
|
20
29
|
let server;
|
|
@@ -41,6 +50,7 @@ export default (pluginOptions) => {
|
|
|
41
50
|
VIRTUAL_PROXY_HYDROGEN_ROUTES_ID,
|
|
42
51
|
VIRTUAL_HYDROGEN_ROUTES_ID,
|
|
43
52
|
VIRTUAL_ERROR_FILE,
|
|
53
|
+
VIRTUAL_STREAM_ID,
|
|
44
54
|
].includes(source)) {
|
|
45
55
|
// Virtual modules convention
|
|
46
56
|
// https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention
|
|
@@ -48,6 +58,13 @@ export default (pluginOptions) => {
|
|
|
48
58
|
}
|
|
49
59
|
},
|
|
50
60
|
load(id) {
|
|
61
|
+
if (id === '\0' + VIRTUAL_STREAM_ID) {
|
|
62
|
+
return {
|
|
63
|
+
code: process.env.WORKER
|
|
64
|
+
? `export default {};`
|
|
65
|
+
: `export {default} from 'stream';`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
51
68
|
// Likely due to a bug in Vite, but virtual modules cannot be loaded
|
|
52
69
|
// directly using ssrLoadModule from a Vite plugin. It needs to be proxied as follows:
|
|
53
70
|
if (id === '\0' + VIRTUAL_PROXY_HYDROGEN_CONFIG_ID) {
|
|
@@ -70,7 +87,10 @@ export default (pluginOptions) => {
|
|
|
70
87
|
routesPath += '**/*.server.[jt](s|sx)';
|
|
71
88
|
}
|
|
72
89
|
const [dirPrefix] = routesPath.split('/*');
|
|
73
|
-
|
|
90
|
+
const importGlob = isVite3
|
|
91
|
+
? `import.meta.glob('${routesPath}', {eager: true})`
|
|
92
|
+
: `import.meta.globEager('${routesPath}')`;
|
|
93
|
+
let code = `export default {\n dirPrefix: '${dirPrefix}',\n basePath: '${hc.routes?.basePath ?? ''}',\n files: ${importGlob}\n};`;
|
|
74
94
|
if (config.command === 'serve') {
|
|
75
95
|
// Add dependency on Hydrogen config for HMR
|
|
76
96
|
code += `\nimport '${VIRTUAL_HYDROGEN_CONFIG_ID}';`;
|