@shopify/hydrogen 1.2.0 → 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.
Files changed (98) hide show
  1. package/README.md +1 -1
  2. package/dist/esnext/components/CartProvider/CartProvider.client.js +6 -0
  3. package/dist/esnext/components/CartProvider/cart-queries.d.ts +1 -1
  4. package/dist/esnext/components/CartProvider/cart-queries.js +1 -0
  5. package/dist/esnext/components/ExternalVideo/ExternalVideo.js +2 -2
  6. package/dist/esnext/components/Image/Image.d.ts +1 -1
  7. package/dist/esnext/components/Image/Image.js +4 -4
  8. package/dist/esnext/components/Image/index.d.ts +1 -1
  9. package/dist/esnext/components/index.d.ts +1 -1
  10. package/dist/esnext/components/index.js +1 -1
  11. package/dist/esnext/constants.d.ts +1 -0
  12. package/dist/esnext/constants.js +1 -0
  13. package/dist/esnext/entry-client.js +1 -1
  14. package/dist/esnext/entry-server.js +30 -28
  15. package/dist/esnext/experimental.d.ts +1 -0
  16. package/dist/esnext/experimental.js +1 -0
  17. package/dist/esnext/foundation/Cache/cache.js +0 -1
  18. package/dist/esnext/foundation/HydrogenRequest/HydrogenRequest.server.d.ts +1 -0
  19. package/dist/esnext/foundation/HydrogenRequest/HydrogenRequest.server.js +1 -0
  20. package/dist/esnext/foundation/HydrogenResponse/HydrogenResponse.server.d.ts +4 -2
  21. package/dist/esnext/foundation/HydrogenResponse/HydrogenResponse.server.js +17 -16
  22. package/dist/esnext/foundation/ServerPropsProvider/ServerPropsProvider.js +1 -3
  23. package/dist/esnext/foundation/fetchSync/ResponseSync.d.ts +2 -1
  24. package/dist/esnext/foundation/fetchSync/ResponseSync.js +14 -2
  25. package/dist/esnext/foundation/session/session-types.d.ts +2 -0
  26. package/dist/esnext/foundation/session/session.d.ts +3 -0
  27. package/dist/esnext/foundation/session/session.js +16 -0
  28. package/dist/esnext/foundation/useQuery/hooks.d.ts +3 -0
  29. package/dist/esnext/foundation/useQuery/hooks.js +1 -1
  30. package/dist/esnext/foundation/useSession/useSession.d.ts +1 -0
  31. package/dist/esnext/foundation/useSession/useSession.js +13 -0
  32. package/dist/esnext/framework/plugin.js +6 -5
  33. package/dist/esnext/framework/plugins/vite-plugin-assets-version.d.ts +2 -0
  34. package/dist/esnext/framework/plugins/vite-plugin-assets-version.js +12 -0
  35. package/dist/esnext/framework/plugins/vite-plugin-client-imports.js +6 -3
  36. package/dist/esnext/framework/plugins/vite-plugin-css-modules-rsc.js +3 -0
  37. package/dist/esnext/framework/plugins/vite-plugin-css-rsc.js +8 -5
  38. package/dist/esnext/framework/plugins/vite-plugin-hydration-auto-import.js +7 -1
  39. package/dist/{node/framework/plugins/vite-plugin-purge-query-cache.d.ts → esnext/framework/plugins/vite-plugin-hydrogen-client-components-cache.d.ts} +1 -1
  40. package/dist/esnext/framework/plugins/{vite-plugin-hydrogen-client-middleware.js → vite-plugin-hydrogen-client-components-cache.js} +2 -2
  41. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.d.ts +2 -1
  42. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-config.js +104 -90
  43. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-middleware.js +6 -6
  44. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +5 -0
  45. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-virtual-files.js +45 -7
  46. package/dist/esnext/framework/plugins/vite-plugin-platform-entry.js +14 -1
  47. package/dist/esnext/framework/plugins/vite-plugin-ssr-interop.js +5 -1
  48. package/dist/esnext/framework/types.d.ts +1 -0
  49. package/dist/esnext/framework/viteception.js +7 -1
  50. package/dist/esnext/storefront-api-types.d.ts +38 -31
  51. package/dist/esnext/storefront-api-types.js +4 -2
  52. package/dist/esnext/types.d.ts +2 -1
  53. package/dist/esnext/utilities/apiRoutes.d.ts +2 -0
  54. package/dist/esnext/utilities/apiRoutes.js +12 -1
  55. package/dist/esnext/utilities/fetch.js +4 -1
  56. package/dist/esnext/utilities/log/log.js +20 -5
  57. package/dist/esnext/utilities/log/utils.js +1 -1
  58. package/dist/esnext/utilities/template.d.ts +7 -6
  59. package/dist/esnext/utilities/template.js +39 -1
  60. package/dist/esnext/utilities/vite.d.ts +1 -0
  61. package/dist/esnext/utilities/vite.js +4 -0
  62. package/dist/esnext/version.d.ts +1 -1
  63. package/dist/esnext/version.js +1 -1
  64. package/dist/node/foundation/session/session-types.d.ts +2 -0
  65. package/dist/node/framework/plugin.js +6 -5
  66. package/dist/node/framework/plugins/vite-plugin-assets-version.d.ts +2 -0
  67. package/dist/node/framework/plugins/vite-plugin-assets-version.js +15 -0
  68. package/dist/node/framework/plugins/vite-plugin-client-imports.js +6 -3
  69. package/dist/node/framework/plugins/vite-plugin-css-modules-rsc.js +3 -0
  70. package/dist/node/framework/plugins/vite-plugin-css-rsc.js +8 -5
  71. package/dist/node/framework/plugins/vite-plugin-hydration-auto-import.js +7 -1
  72. package/dist/{esnext/framework/plugins/vite-plugin-purge-query-cache.d.ts → node/framework/plugins/vite-plugin-hydrogen-client-components-cache.d.ts} +1 -1
  73. package/dist/node/framework/plugins/{vite-plugin-hydrogen-client-middleware.js → vite-plugin-hydrogen-client-components-cache.js} +2 -2
  74. package/dist/node/framework/plugins/vite-plugin-hydrogen-config.d.ts +2 -1
  75. package/dist/node/framework/plugins/vite-plugin-hydrogen-config.js +107 -90
  76. package/dist/node/framework/plugins/vite-plugin-hydrogen-middleware.js +6 -6
  77. package/dist/node/framework/plugins/vite-plugin-hydrogen-suppress-warnings.js +5 -0
  78. package/dist/node/framework/plugins/vite-plugin-hydrogen-virtual-files.js +45 -7
  79. package/dist/node/framework/plugins/vite-plugin-platform-entry.js +14 -1
  80. package/dist/node/framework/plugins/vite-plugin-ssr-interop.js +5 -1
  81. package/dist/node/framework/types.d.ts +1 -0
  82. package/dist/node/framework/viteception.js +7 -1
  83. package/dist/node/utilities/vite.d.ts +1 -0
  84. package/dist/node/utilities/vite.js +30 -0
  85. package/package.json +7 -6
  86. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-plugin.js +36 -25
  87. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.development.server.js +105 -29
  88. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.browser.production.min.server.js +30 -29
  89. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.development.server.js +92 -29
  90. package/vendor/react-server-dom-vite/cjs/react-server-dom-vite-writer.node.production.min.server.js +31 -29
  91. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-plugin.js +29 -18
  92. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js +105 -29
  93. package/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.node.server.js +92 -29
  94. package/vendor/react-server-dom-vite/package.json +2 -2
  95. package/dist/esnext/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +0 -9
  96. package/dist/esnext/framework/plugins/vite-plugin-purge-query-cache.js +0 -11
  97. package/dist/node/framework/plugins/vite-plugin-hydrogen-client-middleware.d.ts +0 -9
  98. package/dist/node/framework/plugins/vite-plugin-purge-query-cache.js +0 -16
@@ -1,11 +1,10 @@
1
1
  import hydrogenConfig from './plugins/vite-plugin-hydrogen-config.js';
2
2
  import hydrogenMiddleware from './plugins/vite-plugin-hydrogen-middleware.js';
3
- import hydrogenClientMiddleware from './plugins/vite-plugin-hydrogen-client-middleware.js';
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';
7
7
  import ssrInterop from './plugins/vite-plugin-ssr-interop.js';
8
- import purgeQueryCache from './plugins/vite-plugin-purge-query-cache.js';
9
8
  import hydrationAutoImport from './plugins/vite-plugin-hydration-auto-import.js';
10
9
  import inspect from 'vite-plugin-inspect';
11
10
  import react from '@vitejs/plugin-react';
@@ -13,11 +12,12 @@ import cssRsc from './plugins/vite-plugin-css-rsc.js';
13
12
  import cssModulesRsc from './plugins/vite-plugin-css-modules-rsc.js';
14
13
  import clientImports from './plugins/vite-plugin-client-imports.js';
15
14
  import suppressWarnings from './plugins/vite-plugin-hydrogen-suppress-warnings.js';
15
+ import assetsVersion from './plugins/vite-plugin-assets-version.js';
16
16
  const hydrogenPlugin = (pluginOptions = {}) => {
17
17
  return [
18
18
  process.env.VITE_INSPECT && inspect(),
19
- hydrogenConfig(),
20
- hydrogenClientMiddleware(),
19
+ hydrogenConfig(pluginOptions),
20
+ hydrogenClientComponentsCache(),
21
21
  clientImports(),
22
22
  hydrogenMiddleware(pluginOptions),
23
23
  hydrogenVirtualFiles(pluginOptions),
@@ -28,7 +28,8 @@ const hydrogenPlugin = (pluginOptions = {}) => {
28
28
  rsc(pluginOptions),
29
29
  platformEntry(),
30
30
  suppressWarnings(),
31
- pluginOptions.purgeQueryCacheOnBuild && purgeQueryCache(),
31
+ pluginOptions.assetHashVersion &&
32
+ assetsVersion(pluginOptions.assetHashVersion),
32
33
  ];
33
34
  };
34
35
  export default hydrogenPlugin; // For ESM
@@ -0,0 +1,2 @@
1
+ import { Plugin } from 'vite';
2
+ export default function assetsVersion(version?: string): Plugin;
@@ -0,0 +1,12 @@
1
+ /* -- Plugin notes:
2
+ * Used to manually change the hash of output chunks (`index.k12dw5q.js`)
3
+ * when their content have not been updated.
4
+ */
5
+ export default function assetsVersion(version) {
6
+ return {
7
+ name: 'hydrogen:augment-with-version',
8
+ augmentChunkHash() {
9
+ return version ?? '';
10
+ },
11
+ };
12
+ }
@@ -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 {
@@ -35,7 +43,6 @@ export default function cssRsc() {
35
43
  if (server) {
36
44
  const tags = [];
37
45
  const foundCssFiles = new Set();
38
- const { browserHash = '' } = server._optimizedDeps?.metadata || {};
39
46
  for (const [key, value] of server.moduleGraph.idToModuleMap.entries()) {
40
47
  if (
41
48
  // Note: Some CSS-in-JS libraries use `.css.js`
@@ -55,10 +62,6 @@ export default function cssRsc() {
55
62
  ? url.replace('?', timestampQuery + '&')
56
63
  : url + timestampQuery;
57
64
  }
58
- if (browserHash && !url.includes('v=')) {
59
- // Append the hash at the end
60
- url += (url.includes('?') ? '&' : '?') + `v=${browserHash}`;
61
- }
62
65
  tags.push(value.type === 'css'
63
66
  ? { tag: 'link', attrs: { rel: 'stylesheet', href: url } }
64
67
  : { tag: 'script', attrs: { type: 'module', src: url } });
@@ -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: 'vite-plugin-hydration-auto-import',
14
+ name: 'hydrogen:client-hydration-auto-import',
9
15
  enforce: 'pre',
10
16
  configResolved(_config) {
11
17
  config = _config;
@@ -1,3 +1,3 @@
1
- import type { Plugin } from 'vite';
1
+ import { type Plugin } from 'vite';
2
2
  declare const _default: () => Plugin;
3
3
  export default _default;
@@ -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: 'vite-plugin-hydrogen-client-middleware',
10
+ name: 'hydrogen:client-components-cache',
11
11
  enforce: 'pre',
12
12
  configureServer(server) {
13
13
  server.middlewares.use(async (req, res, next) => {
@@ -1,3 +1,4 @@
1
1
  import { Plugin } from 'vite';
2
- declare const _default: () => Plugin;
2
+ import type { HydrogenVitePluginOptions } from '../types.js';
3
+ declare const _default: (pluginOptions: HydrogenVitePluginOptions) => Plugin;
3
4
  export default _default;
@@ -1,102 +1,116 @@
1
- export default () => {
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
+ */
6
+ export default (pluginOptions) => {
2
7
  const rollupOptions = {
3
8
  output: {},
4
9
  };
5
10
  const isWorker = Boolean(process.env.WORKER) && process.env.WORKER !== 'undefined';
6
- if (isWorker) {
7
- /**
8
- * By default, SSR dedupe logic gets bundled which runs `require('module')`.
9
- * We don't want this in our workers runtime, because `require` is not supported.
10
- */
11
- rollupOptions.output = {
12
- format: 'es',
13
- };
14
- }
15
- if (process.env.NODE_ENV !== 'development' && !process.env.LOCAL_DEV) {
16
- /**
17
- * Ofuscate production asset name - To prevent ad blocker logics that blocks
18
- * certain files due to how it is named.
19
- */
20
- rollupOptions.output = {
21
- ...rollupOptions.output,
22
- chunkFileNames: 'assets/[hash].js',
23
- };
24
- }
25
11
  return {
26
- name: 'vite-plugin-hydrogen-config',
27
- config: async (config, env) => ({
28
- resolve: {
29
- alias: {
30
- // This library is currently included as a compiled vendor lib, not published yet to NPM
31
- 'react-server-dom-vite/client-proxy': require.resolve('@shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-client-proxy.js'),
32
- },
33
- },
34
- build: {
35
- minify: config.build?.minify ?? (process.env.LOCAL_DEV ? false : 'esbuild'),
36
- sourcemap: true,
37
- rollupOptions: config.build?.rollupOptions
38
- ? Object.assign(rollupOptions, config.build.rollupOptions)
39
- : rollupOptions,
40
- target: config.build?.ssr
41
- ? isWorker
42
- ? 'es2022' // CFW (Updates weekly to latest V8)
43
- : 'es2020' // Node (Support for v14.19 used in SB)
44
- : 'modules', // Browsers (Vite default value)
45
- },
46
- ssr: {
12
+ name: 'hydrogen:config',
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) {
47
25
  /**
48
- * Tell Vite to bundle everything when we're building for Workers.
49
- * Otherwise, bundle RSC plugin as a workaround to apply the vendor alias above.
26
+ * Ofuscate production asset name - To prevent ad blocker logics that blocks
27
+ * certain files due to how it is named.
50
28
  */
51
- noExternal: isWorker || [/react-server-dom-vite/],
52
- target: isWorker ? 'webworker' : 'node',
53
- },
54
- // Reload when updating local Hydrogen lib
55
- server: process.env.LOCAL_DEV && {
56
- watch: {
57
- ignored: [
58
- '!**/node_modules/@shopify/hydrogen/**',
59
- '!**/node_modules/@shopify/hydrogen-ui/**',
60
- ],
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
+ },
61
40
  },
62
- },
63
- optimizeDeps: {
64
- exclude: [
65
- '@shopify/hydrogen',
66
- '@shopify/hydrogen/client',
67
- '@shopify/hydrogen/entry-client',
68
- '@shopify/hydrogen-ui',
69
- ],
70
- include: [
71
- /**
72
- * Additionally, the following dependencies have trouble loading the
73
- * correct version of the dependency (server vs client). This tells Vite to take the
74
- * server versions and optimize them for ESM.
75
- */
76
- 'react-helmet-async',
77
- '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: {
78
54
  /**
79
- * Vite cannot find the following dependencies since they might be
80
- * required in RSC asynchronously. This tells Vite to optimize them
81
- * 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.
82
57
  */
83
- 'react',
84
- 'react-dom/client',
85
- 'react-server-dom-vite/client-proxy',
86
- // https://github.com/vitejs/vite/issues/6215
87
- 'react/jsx-runtime',
88
- // https://github.com/nfriedly/set-cookie-parser/issues/50
89
- 'set-cookie-parser',
90
- 'undici',
91
- ],
92
- },
93
- define: {
94
- __HYDROGEN_DEV__: env.mode !== 'production',
95
- __HYDROGEN_WORKER__: isWorker,
96
- __HYDROGEN_TEST__: false, // Used in unit tests
97
- },
98
- envPrefix: ['VITE_', 'PUBLIC_'],
99
- base: process.env.HYDROGEN_ASSET_BASE_URL,
100
- }),
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
+ },
101
115
  };
102
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',
@@ -2,6 +2,15 @@ import { normalizePath } from 'vite';
2
2
  import path from 'path';
3
3
  import { promises as fs } from 'fs';
4
4
  import { viteception } from '../viteception.js';
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
+ */
5
14
  export const HYDROGEN_DEFAULT_SERVER_ENTRY = process.env.HYDROGEN_SERVER_ENTRY || '/src/App.server';
6
15
  // The character ":" breaks Vite with Node >= 16.15. Use "_" instead
7
16
  const VIRTUAL_PREFIX = 'virtual__';
@@ -14,9 +23,11 @@ export const VIRTUAL_PROXY_HYDROGEN_CONFIG_ID = VIRTUAL_PREFIX + PROXY_PREFIX +
14
23
  const HYDROGEN_ROUTES_ID = 'hydrogen-routes.server.jsx';
15
24
  const VIRTUAL_HYDROGEN_ROUTES_ID = VIRTUAL_PREFIX + HYDROGEN_ROUTES_ID;
16
25
  export const VIRTUAL_PROXY_HYDROGEN_ROUTES_ID = VIRTUAL_PREFIX + PROXY_PREFIX + HYDROGEN_ROUTES_ID;
26
+ const VIRTUAL_STREAM_ID = 'virtual__stream';
17
27
  export default (pluginOptions) => {
18
28
  let config;
19
29
  let server;
30
+ let resolvedConfigPath;
20
31
  return {
21
32
  name: 'hydrogen:virtual-files',
22
33
  configResolved(_config) {
@@ -27,16 +38,19 @@ export default (pluginOptions) => {
27
38
  },
28
39
  resolveId(source, importer) {
29
40
  if (source === VIRTUAL_HYDROGEN_CONFIG_ID) {
30
- return findHydrogenConfigPath(config.root, pluginOptions.configPath).then((hcPath) =>
31
- // This direct dependency on a real file
32
- // makes HMR work for the virtual module.
33
- this.resolve(hcPath, importer, { skipSelf: true }));
41
+ return findHydrogenConfigPath(config.root, pluginOptions.configPath).then((hcPath) => {
42
+ resolvedConfigPath = normalizePath(hcPath);
43
+ // This direct dependency on a real file
44
+ // makes HMR work for the virtual module.
45
+ return this.resolve(hcPath, importer, { skipSelf: true });
46
+ });
34
47
  }
35
48
  if ([
36
49
  VIRTUAL_PROXY_HYDROGEN_CONFIG_ID,
37
50
  VIRTUAL_PROXY_HYDROGEN_ROUTES_ID,
38
51
  VIRTUAL_HYDROGEN_ROUTES_ID,
39
52
  VIRTUAL_ERROR_FILE,
53
+ VIRTUAL_STREAM_ID,
40
54
  ].includes(source)) {
41
55
  // Virtual modules convention
42
56
  // https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention
@@ -44,10 +58,17 @@ export default (pluginOptions) => {
44
58
  }
45
59
  },
46
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
+ }
47
68
  // Likely due to a bug in Vite, but virtual modules cannot be loaded
48
69
  // directly using ssrLoadModule from a Vite plugin. It needs to be proxied as follows:
49
70
  if (id === '\0' + VIRTUAL_PROXY_HYDROGEN_CONFIG_ID) {
50
- return `import hc from '${VIRTUAL_HYDROGEN_CONFIG_ID}'; export default hc;`;
71
+ return `import hc from '${VIRTUAL_HYDROGEN_CONFIG_ID}'; export default typeof hc === 'function' ? hc() : hc;`;
51
72
  }
52
73
  if (id === '\0' + VIRTUAL_PROXY_HYDROGEN_ROUTES_ID) {
53
74
  return `import hr from '${VIRTUAL_HYDROGEN_ROUTES_ID}'; export default hr;`;
@@ -66,7 +87,10 @@ export default (pluginOptions) => {
66
87
  routesPath += '**/*.server.[jt](s|sx)';
67
88
  }
68
89
  const [dirPrefix] = routesPath.split('/*');
69
- let code = `export default {\n dirPrefix: '${dirPrefix}',\n basePath: '${hc.routes?.basePath ?? ''}',\n files: import.meta.globEager('${routesPath}')\n};`;
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};`;
70
94
  if (config.command === 'serve') {
71
95
  // Add dependency on Hydrogen config for HMR
72
96
  code += `\nimport '${VIRTUAL_HYDROGEN_CONFIG_ID}';`;
@@ -82,13 +106,27 @@ export default (pluginOptions) => {
82
106
  });
83
107
  }
84
108
  },
109
+ transform(code, id) {
110
+ if (id === resolvedConfigPath) {
111
+ const s = new MagicString(code);
112
+ // Wrap in function to avoid evaluating `Oxygen.env`
113
+ // in the config until we have polyfilled it properly.
114
+ s.replace(/export\s+default\s+(\w+)\s*\(/g, (all, m1) => all.replace(m1, `() => ${m1}`));
115
+ return {
116
+ code: s.toString(),
117
+ map: s.generateMap({ file: id, source: id }),
118
+ };
119
+ }
120
+ },
85
121
  };
86
122
  async function importHydrogenConfig() {
87
123
  if (server) {
88
124
  const loaded = await server.ssrLoadModule(VIRTUAL_PROXY_HYDROGEN_CONFIG_ID);
89
125
  return loaded.default;
90
126
  }
91
- const { loaded } = await viteception([VIRTUAL_PROXY_HYDROGEN_CONFIG_ID]);
127
+ const { loaded } = await viteception([VIRTUAL_PROXY_HYDROGEN_CONFIG_ID], {
128
+ root: config.root,
129
+ });
92
130
  return loaded[0].default;
93
131
  }
94
132
  };
@@ -4,10 +4,23 @@ import MagicString from 'magic-string';
4
4
  import path from 'path';
5
5
  import fs from 'fs';
6
6
  import fastGlob from 'fast-glob';
7
+ import { isVite3 } from '../../utilities/vite.js';
7
8
  const SSR_BUNDLE_NAME = 'index.js';
8
9
  // Keep this in the outer scope to share it
9
10
  // across client <> server builds.
10
11
  let clientBuildPath;
12
+ /* -- Plugin notes:
13
+ * This plugin simplifies the way a platform entry file imports user files. This is
14
+ * needed to write generic integrations with different platform providers.
15
+ *
16
+ * Instead of using relative paths:
17
+ * `import handleRequest from '../../<arbitrary_path>/src/App.server';`
18
+ * `import indexTemplate from '../../<arbitrary_path>/dist/client/index.html?raw';`
19
+ *
20
+ * It allows importing from a known static path which dynamically resolves the user files:
21
+ * `import {handleRequest, indexTemplate} from '@shopify/hydrogen/platforms';`
22
+ *
23
+ */
11
24
  export default () => {
12
25
  let config;
13
26
  let isESM;
@@ -18,7 +31,7 @@ export default () => {
18
31
  config = _config;
19
32
  if (config.build.ssr) {
20
33
  const { output = {} } = config.build.rollupOptions || {};
21
- const { format = '' } = (Array.isArray(output) ? output[0] : output) || {};
34
+ const { format = isVite3 ? 'es' : '' } = (Array.isArray(output) ? output[0] : output) || {};
22
35
  isESM = Boolean(process.env.WORKER) || ['es', 'esm'].includes(format);
23
36
  }
24
37
  },
@@ -1,6 +1,10 @@
1
+ /* -- Plugin notes:
2
+ * This plugin makes sure we don't leak server logic to the browser when importing
3
+ * the `useEnvContext` utility.
4
+ */
1
5
  export default () => {
2
6
  return {
3
- name: 'vite-plugin-ssr-interop',
7
+ name: 'hydrogen:ssr-interop',
4
8
  enforce: 'pre',
5
9
  transform(code, id, options = {}) {
6
10
  if (options.ssr && id.includes('foundation/ssr-interop')) {
@@ -3,6 +3,7 @@ export interface HydrogenVitePluginOptions {
3
3
  purgeQueryCacheOnBuild?: boolean;
4
4
  configPath?: string;
5
5
  optimizeBoundaries?: boolean | 'build';
6
+ assetHashVersion?: string;
6
7
  /**
7
8
  * Experimental features
8
9
  */
@@ -1,10 +1,16 @@
1
1
  import { createServer } from 'vite';
2
+ import { isVite3 } from '../utilities/vite.js';
2
3
  export async function viteception(paths, options) {
3
4
  const isWorker = process.env.WORKER;
4
5
  delete process.env.WORKER;
5
6
  const server = await createServer({
6
7
  clearScreen: false,
7
- server: { middlewareMode: 'ssr' },
8
+ server: {
9
+ middlewareMode: isVite3 ? true : 'ssr',
10
+ hmr: false,
11
+ },
12
+ // @ts-ignore
13
+ appType: 'custom',
8
14
  ...options,
9
15
  });
10
16
  if (isWorker) {