@netlify/vite-plugin-react-router 3.1.0-next.1 → 3.1.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.1.0](https://github.com/netlify/remix-compute/compare/vite-plugin-react-router-v3.0.0...vite-plugin-react-router-v3.1.0) (2026-03-13)
4
+
5
+
6
+ ### Features
7
+
8
+ * **vite-plugin-react-router:** support Hydrogen sites ([#641](https://github.com/netlify/remix-compute/issues/641)) ([923d9dc](https://github.com/netlify/remix-compute/commit/923d9dcba02ff6027d85bba697bd6cf1f1d09329))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * actually use Hydrogen entry in dev ([#651](https://github.com/netlify/remix-compute/issues/651)) ([c8f93a2](https://github.com/netlify/remix-compute/commit/c8f93a2d2aeeb95f68d9cc5e2c9b876f8d875aff))
14
+
3
15
  ## [3.0.0](https://github.com/netlify/remix-compute/compare/vite-plugin-react-router-v2.1.3...vite-plugin-react-router-v3.0.0) (2026-02-25)
4
16
 
5
17
 
package/dist/index.js CHANGED
@@ -109,11 +109,12 @@ function createRequestHandler({
109
109
  var import_promises = require("fs/promises");
110
110
  var import_node_path2 = require("path");
111
111
  var import_posix = require("path/posix");
112
+ var import_node_fetch_server = require("@remix-run/node-fetch-server");
112
113
  var import_tinyglobby = require("tinyglobby");
113
114
 
114
115
  // package.json
115
116
  var name = "@netlify/vite-plugin-react-router";
116
- var version = "3.1.0-next.1";
117
+ var version = "3.1.0";
117
118
 
118
119
  // src/lib/rollup.ts
119
120
  var import_node_path = require("path");
@@ -228,6 +229,7 @@ function netlifyPlugin(options = {}) {
228
229
  let isProductionSsrBuild = false;
229
230
  let currentCommand;
230
231
  let isHydrogenSite = false;
232
+ let userServerFile;
231
233
  return {
232
234
  name: "vite-plugin-netlify-react-router",
233
235
  config(_config, { command, isSsrBuild }) {
@@ -296,14 +298,52 @@ function netlifyPlugin(options = {}) {
296
298
  async handler(config) {
297
299
  resolvedConfig = config;
298
300
  isHydrogenSite = config.plugins.some((plugin) => plugin.name === "hydrogen:main");
299
- if (isHydrogenSite && edge && isProductionSsrBuild) {
300
- const userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
301
- if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
302
- config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
301
+ if (isHydrogenSite && edge) {
302
+ userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
303
+ if (isProductionSsrBuild) {
304
+ if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
305
+ config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
306
+ }
303
307
  }
304
308
  }
305
309
  }
306
310
  },
311
+ // In dev, Hydrogen sites need their server.ts to be loaded and called for each request so that
312
+ // it can provide `getLoadContext` (storefront, cart, session, etc.) to React Router's request
313
+ // handler. Without this, React Router's dev middleware would handle SSR with no load context.
314
+ configureServer: {
315
+ order: "pre",
316
+ handler(viteDevServer) {
317
+ if (!isHydrogenSite || !edge) return;
318
+ if (!userServerFile) {
319
+ viteDevServer.config.logger.warn(
320
+ "Hydrogen site detected but no server.ts found. Dev SSR will fall through to React Router defaults."
321
+ );
322
+ return;
323
+ }
324
+ const serverEntryFile = userServerFile;
325
+ return () => {
326
+ viteDevServer.middlewares.use(async (req, res, next) => {
327
+ try {
328
+ const serverModule = await viteDevServer.ssrLoadModule((0, import_node_path2.join)(viteDevServer.config.root, serverEntryFile));
329
+ const handler = serverModule.default;
330
+ req.url = req.originalUrl ?? req.url;
331
+ const request = (0, import_node_fetch_server.createRequest)(req, res);
332
+ const netlifyContext = { waitUntil: () => {
333
+ }, ...globalThis.Netlify?.context };
334
+ const response = await handler(request, netlifyContext);
335
+ if (response) {
336
+ await (0, import_node_fetch_server.sendResponse)(res, response);
337
+ } else {
338
+ next();
339
+ }
340
+ } catch (error) {
341
+ next(error);
342
+ }
343
+ });
344
+ };
345
+ }
346
+ },
307
347
  // See https://rollupjs.org/plugin-development/#writebundle.
308
348
  async writeBundle() {
309
349
  if (isProductionSsrBuild) {
package/dist/index.mjs CHANGED
@@ -8,11 +8,12 @@ import "./chunk-J5PMA2AP.mjs";
8
8
  import { access, mkdir, writeFile } from "node:fs/promises";
9
9
  import { dirname, join, relative, resolve, sep } from "node:path";
10
10
  import { sep as posixSep } from "node:path/posix";
11
+ import { createRequest, sendResponse } from "@remix-run/node-fetch-server";
11
12
  import { glob } from "tinyglobby";
12
13
 
13
14
  // package.json
14
15
  var name = "@netlify/vite-plugin-react-router";
15
- var version = "3.1.0-next.1";
16
+ var version = "3.1.0";
16
17
 
17
18
  // src/lib/rollup.ts
18
19
  import { basename, extname } from "node:path";
@@ -127,6 +128,7 @@ function netlifyPlugin(options = {}) {
127
128
  let isProductionSsrBuild = false;
128
129
  let currentCommand;
129
130
  let isHydrogenSite = false;
131
+ let userServerFile;
130
132
  return {
131
133
  name: "vite-plugin-netlify-react-router",
132
134
  config(_config, { command, isSsrBuild }) {
@@ -195,14 +197,52 @@ function netlifyPlugin(options = {}) {
195
197
  async handler(config) {
196
198
  resolvedConfig = config;
197
199
  isHydrogenSite = config.plugins.some((plugin) => plugin.name === "hydrogen:main");
198
- if (isHydrogenSite && edge && isProductionSsrBuild) {
199
- const userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
200
- if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
201
- config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
200
+ if (isHydrogenSite && edge) {
201
+ userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
202
+ if (isProductionSsrBuild) {
203
+ if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
204
+ config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
205
+ }
202
206
  }
203
207
  }
204
208
  }
205
209
  },
210
+ // In dev, Hydrogen sites need their server.ts to be loaded and called for each request so that
211
+ // it can provide `getLoadContext` (storefront, cart, session, etc.) to React Router's request
212
+ // handler. Without this, React Router's dev middleware would handle SSR with no load context.
213
+ configureServer: {
214
+ order: "pre",
215
+ handler(viteDevServer) {
216
+ if (!isHydrogenSite || !edge) return;
217
+ if (!userServerFile) {
218
+ viteDevServer.config.logger.warn(
219
+ "Hydrogen site detected but no server.ts found. Dev SSR will fall through to React Router defaults."
220
+ );
221
+ return;
222
+ }
223
+ const serverEntryFile = userServerFile;
224
+ return () => {
225
+ viteDevServer.middlewares.use(async (req, res, next) => {
226
+ try {
227
+ const serverModule = await viteDevServer.ssrLoadModule(join(viteDevServer.config.root, serverEntryFile));
228
+ const handler = serverModule.default;
229
+ req.url = req.originalUrl ?? req.url;
230
+ const request = createRequest(req, res);
231
+ const netlifyContext = { waitUntil: () => {
232
+ }, ...globalThis.Netlify?.context };
233
+ const response = await handler(request, netlifyContext);
234
+ if (response) {
235
+ await sendResponse(res, response);
236
+ } else {
237
+ next();
238
+ }
239
+ } catch (error) {
240
+ next(error);
241
+ }
242
+ });
243
+ };
244
+ }
245
+ },
206
246
  // See https://rollupjs.org/plugin-development/#writebundle.
207
247
  async writeBundle() {
208
248
  if (isProductionSsrBuild) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/vite-plugin-react-router",
3
- "version": "3.1.0-next.1",
3
+ "version": "3.1.0",
4
4
  "description": "React Router 7+ Vite plugin for Netlify",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -54,6 +54,7 @@
54
54
  "dependencies": {
55
55
  "@netlify/edge-functions": "^3.0.4",
56
56
  "@netlify/functions": "^5.1.3",
57
+ "@remix-run/node-fetch-server": "^0.9.0",
57
58
  "isbot": "^5.1.25",
58
59
  "tinyglobby": "^0.2.10"
59
60
  },
@@ -64,7 +65,7 @@
64
65
  "react-dom": "^18.2.0",
65
66
  "react-router": "^7.9.4",
66
67
  "tsup": "^8.0.2",
67
- "vite": "^6.2.5"
68
+ "vite": "^8.0.0"
68
69
  },
69
70
  "peerDependencies": {
70
71
  "react-router": ">=7.9.0",