@netlify/vite-plugin-react-router 3.1.0-next.1 → 3.1.0-next.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/README.md CHANGED
@@ -10,33 +10,28 @@ To deploy a React Router 7+ site to Netlify, install this package:
10
10
  npm install @netlify/vite-plugin-react-router
11
11
  ```
12
12
 
13
- It's also recommended (but not required) to use the
14
- [Netlify Vite plugin](https://www.npmjs.com/package/@netlify/vite-plugin), which provides full Netlify platform
15
- emulation directly in your local dev server:
16
-
17
- ```sh
18
- npm install --save-dev @netlify/vite-plugin
19
- ```
20
-
21
- and include the Netlify plugin in your `vite.config.ts`:
13
+ Then include the Netlify plugin in your `vite.config.ts`:
22
14
 
23
15
  ```typescript
24
16
  import { reactRouter } from '@react-router/dev/vite'
25
17
  import { defineConfig } from 'vite'
26
18
  import tsconfigPaths from 'vite-tsconfig-paths'
27
19
  import netlifyReactRouter from '@netlify/vite-plugin-react-router' // <- add this
28
- import netlify from '@netlify/vite-plugin' // <- add this (optional)
29
20
 
30
21
  export default defineConfig({
31
22
  plugins: [
32
23
  reactRouter(),
33
24
  tsconfigPaths(),
34
25
  netlifyReactRouter(), // <- add this
35
- netlify(), // <- add this (optional)
36
26
  ],
37
27
  })
38
28
  ```
39
29
 
30
+ > [!NOTE]
31
+ >
32
+ > This plugin automatically includes [`@netlify/vite-plugin`](https://npmx.dev/@netlify/vite-plugin), which provides
33
+ > full Netlify platform emulation directly in your local dev server.
34
+
40
35
  Your app is ready to [deploy to Netlify](https://docs.netlify.com/deploy/create-deploys/).
41
36
 
42
37
  ### Deploying to Edge Functions
@@ -53,7 +48,6 @@ export default defineConfig({
53
48
  reactRouter(),
54
49
  tsconfigPaths(),
55
50
  netlifyReactRouter({ edge: true }), // <- deploy to Edge Functions
56
- netlify(),
57
51
  ],
58
52
  })
59
53
  ```
@@ -88,7 +82,6 @@ export default defineConfig({
88
82
  edge: true,
89
83
  excludedPaths: ['/ping', '/api/*', '/webhooks/*'],
90
84
  }),
91
- netlify(),
92
85
  ],
93
86
  })
94
87
  ```
@@ -159,12 +152,6 @@ export default function Example() {
159
152
  }
160
153
  ```
161
154
 
162
- > [!IMPORTANT]
163
- >
164
- > Note that in local development, `netlifyRouterContext` requires Netlify platform emulation, which is provided
165
- > seamlessly by [`@netlify/vite-plugin`](https://www.npmjs.com/package/@netlify/vite-plugin) (or Netlify CLI - up to
166
- > you).
167
-
168
155
  ### Middleware context
169
156
 
170
157
  React Router introduced a stable middleware feature in 7.9.0.
@@ -193,9 +180,3 @@ export default function Home() {
193
180
  return <h1>Hello world</h1>
194
181
  }
195
182
  ```
196
-
197
- > [!IMPORTANT]
198
- >
199
- > Note that in local development, `netlifyRouterContext` requires Netlify platform emulation, which is provided
200
- > seamlessly by [`@netlify/vite-plugin`](https://www.npmjs.com/package/@netlify/vite-plugin) (or Netlify CLI - up to
201
- > you).
package/dist/index.d.mts CHANGED
@@ -21,6 +21,6 @@ interface NetlifyPluginOptions {
21
21
  */
22
22
  excludedPaths?: string[];
23
23
  }
24
- declare function netlifyPlugin(options?: NetlifyPluginOptions): Plugin;
24
+ declare function netlifyPlugin(options?: NetlifyPluginOptions): Plugin[];
25
25
 
26
26
  export { netlifyPlugin as default };
package/dist/index.d.ts CHANGED
@@ -60,6 +60,6 @@ interface NetlifyPluginOptions {
60
60
  */
61
61
  excludedPaths?: string[];
62
62
  }
63
- declare function netlifyPlugin(options?: NetlifyPluginOptions): Plugin;
63
+ declare function netlifyPlugin(options?: NetlifyPluginOptions): Plugin[];
64
64
 
65
65
  export { type GetLoadContextFunction, type RequestHandler, createRequestHandler, netlifyPlugin as default, netlifyRouterContext };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name2 in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -109,11 +119,13 @@ function createRequestHandler({
109
119
  var import_promises = require("fs/promises");
110
120
  var import_node_path2 = require("path");
111
121
  var import_posix = require("path/posix");
122
+ var import_vite_plugin = __toESM(require("@netlify/vite-plugin"));
123
+ var import_node_fetch_server = require("@remix-run/node-fetch-server");
112
124
  var import_tinyglobby = require("tinyglobby");
113
125
 
114
126
  // package.json
115
127
  var name = "@netlify/vite-plugin-react-router";
116
- var version = "3.1.0-next.1";
128
+ var version = "3.1.0-next.2";
117
129
 
118
130
  // src/lib/rollup.ts
119
131
  var import_node_path = require("path");
@@ -228,7 +240,8 @@ function netlifyPlugin(options = {}) {
228
240
  let isProductionSsrBuild = false;
229
241
  let currentCommand;
230
242
  let isHydrogenSite = false;
231
- return {
243
+ let userServerFile;
244
+ const reactRouterPlugin = {
232
245
  name: "vite-plugin-netlify-react-router",
233
246
  config(_config, { command, isSsrBuild }) {
234
247
  currentCommand = command;
@@ -296,14 +309,52 @@ function netlifyPlugin(options = {}) {
296
309
  async handler(config) {
297
310
  resolvedConfig = config;
298
311
  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;
312
+ if (isHydrogenSite && edge) {
313
+ userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
314
+ if (isProductionSsrBuild) {
315
+ if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
316
+ config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
317
+ }
303
318
  }
304
319
  }
305
320
  }
306
321
  },
322
+ // In dev, Hydrogen sites need their server.ts to be loaded and called for each request so that
323
+ // it can provide `getLoadContext` (storefront, cart, session, etc.) to React Router's request
324
+ // handler. Without this, React Router's dev middleware would handle SSR with no load context.
325
+ configureServer: {
326
+ order: "pre",
327
+ handler(viteDevServer) {
328
+ if (!isHydrogenSite || !edge) return;
329
+ if (!userServerFile) {
330
+ viteDevServer.config.logger.warn(
331
+ "Hydrogen site detected but no server.ts found. Dev SSR will fall through to React Router defaults."
332
+ );
333
+ return;
334
+ }
335
+ const serverEntryFile = userServerFile;
336
+ return () => {
337
+ viteDevServer.middlewares.use(async (req, res, next) => {
338
+ try {
339
+ const serverModule = await viteDevServer.ssrLoadModule((0, import_node_path2.join)(viteDevServer.config.root, serverEntryFile));
340
+ const handler = serverModule.default;
341
+ req.url = req.originalUrl ?? req.url;
342
+ const request = (0, import_node_fetch_server.createRequest)(req, res);
343
+ const netlifyContext = { waitUntil: () => {
344
+ }, ...globalThis.Netlify?.context };
345
+ const response = await handler(request, netlifyContext);
346
+ if (response) {
347
+ await (0, import_node_fetch_server.sendResponse)(res, response);
348
+ } else {
349
+ next();
350
+ }
351
+ } catch (error) {
352
+ next(error);
353
+ }
354
+ });
355
+ };
356
+ }
357
+ },
307
358
  // See https://rollupjs.org/plugin-development/#writebundle.
308
359
  async writeBundle() {
309
360
  if (isProductionSsrBuild) {
@@ -338,6 +389,7 @@ function netlifyPlugin(options = {}) {
338
389
  }
339
390
  }
340
391
  };
392
+ return [reactRouterPlugin, ...(0, import_vite_plugin.default)()];
341
393
  }
342
394
  // Annotate the CommonJS export names for ESM import in node:
343
395
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -8,11 +8,13 @@ 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 netlifyVitePlugin from "@netlify/vite-plugin";
12
+ import { createRequest, sendResponse } from "@remix-run/node-fetch-server";
11
13
  import { glob } from "tinyglobby";
12
14
 
13
15
  // package.json
14
16
  var name = "@netlify/vite-plugin-react-router";
15
- var version = "3.1.0-next.1";
17
+ var version = "3.1.0-next.2";
16
18
 
17
19
  // src/lib/rollup.ts
18
20
  import { basename, extname } from "node:path";
@@ -127,7 +129,8 @@ function netlifyPlugin(options = {}) {
127
129
  let isProductionSsrBuild = false;
128
130
  let currentCommand;
129
131
  let isHydrogenSite = false;
130
- return {
132
+ let userServerFile;
133
+ const reactRouterPlugin = {
131
134
  name: "vite-plugin-netlify-react-router",
132
135
  config(_config, { command, isSsrBuild }) {
133
136
  currentCommand = command;
@@ -195,14 +198,52 @@ function netlifyPlugin(options = {}) {
195
198
  async handler(config) {
196
199
  resolvedConfig = config;
197
200
  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;
201
+ if (isHydrogenSite && edge) {
202
+ userServerFile = await findUserEdgeFunctionHandlerFile(config.root);
203
+ if (isProductionSsrBuild) {
204
+ if (config.build?.rollupOptions?.input && typeof config.build.rollupOptions.input === "object" && !Array.isArray(config.build.rollupOptions.input)) {
205
+ config.build.rollupOptions.input[FUNCTION_HANDLER_CHUNK] = userServerFile;
206
+ }
202
207
  }
203
208
  }
204
209
  }
205
210
  },
211
+ // In dev, Hydrogen sites need their server.ts to be loaded and called for each request so that
212
+ // it can provide `getLoadContext` (storefront, cart, session, etc.) to React Router's request
213
+ // handler. Without this, React Router's dev middleware would handle SSR with no load context.
214
+ configureServer: {
215
+ order: "pre",
216
+ handler(viteDevServer) {
217
+ if (!isHydrogenSite || !edge) return;
218
+ if (!userServerFile) {
219
+ viteDevServer.config.logger.warn(
220
+ "Hydrogen site detected but no server.ts found. Dev SSR will fall through to React Router defaults."
221
+ );
222
+ return;
223
+ }
224
+ const serverEntryFile = userServerFile;
225
+ return () => {
226
+ viteDevServer.middlewares.use(async (req, res, next) => {
227
+ try {
228
+ const serverModule = await viteDevServer.ssrLoadModule(join(viteDevServer.config.root, serverEntryFile));
229
+ const handler = serverModule.default;
230
+ req.url = req.originalUrl ?? req.url;
231
+ const request = createRequest(req, res);
232
+ const netlifyContext = { waitUntil: () => {
233
+ }, ...globalThis.Netlify?.context };
234
+ const response = await handler(request, netlifyContext);
235
+ if (response) {
236
+ await sendResponse(res, response);
237
+ } else {
238
+ next();
239
+ }
240
+ } catch (error) {
241
+ next(error);
242
+ }
243
+ });
244
+ };
245
+ }
246
+ },
206
247
  // See https://rollupjs.org/plugin-development/#writebundle.
207
248
  async writeBundle() {
208
249
  if (isProductionSsrBuild) {
@@ -237,6 +278,7 @@ function netlifyPlugin(options = {}) {
237
278
  }
238
279
  }
239
280
  };
281
+ return [reactRouterPlugin, ...netlifyVitePlugin()];
240
282
  }
241
283
  export {
242
284
  createRequestHandler,
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-next.2",
4
4
  "description": "React Router 7+ Vite plugin for Netlify",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -54,6 +54,8 @@
54
54
  "dependencies": {
55
55
  "@netlify/edge-functions": "^3.0.4",
56
56
  "@netlify/functions": "^5.1.3",
57
+ "@netlify/vite-plugin": "^2.11.0",
58
+ "@remix-run/node-fetch-server": "^0.9.0",
57
59
  "isbot": "^5.1.25",
58
60
  "tinyglobby": "^0.2.10"
59
61
  },
@@ -64,7 +66,7 @@
64
66
  "react-dom": "^18.2.0",
65
67
  "react-router": "^7.9.4",
66
68
  "tsup": "^8.0.2",
67
- "vite": "^6.2.5"
69
+ "vite": "^8.0.0"
68
70
  },
69
71
  "peerDependencies": {
70
72
  "react-router": ">=7.9.0",