next-vite-router 1.2.2 → 1.2.3

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
@@ -6,33 +6,19 @@ Define routes with folders and let the package generate the
6
6
  [React Router](https://reactrouter.com/) `RouteObject[]`. It does not replace
7
7
  React Router, navigation, history, loaders, or application state.
8
8
 
9
- ## Release notes
10
-
11
- ### Plugin import
12
-
13
- The Vite plugin is no longer exported from the main
14
- `next-vite-router` entry point. Existing imports must be migrated:
15
-
16
- ```ts
17
- // Previous import
18
- import { nextViteRouter } from "next-vite-router";
19
-
20
- // Current import
21
- import { nextViteRouter } from "next-vite-router/plugin";
22
- ```
23
-
24
- The plugin remains available through `next-vite-router/plugin`. This separation
25
- prevents the plugin's Node dependencies from being included in the application's
26
- browser dependency graph.
27
-
28
9
  ## Start here
29
10
 
30
11
  ```bash
31
12
  npm create vite@latest my-app -- --template react-ts
32
13
  cd my-app
33
- npm install next-vite-router react-router-dom
14
+ npm install next-vite-router
34
15
  ```
35
16
 
17
+ `next-vite-router` declares `react-router-dom` as a peer dependency. Recent
18
+ versions of npm install this dependency automatically; if your package manager
19
+ does not resolve peer dependencies automatically, install
20
+ `react-router-dom` explicitly.
21
+
36
22
  Add the plugin to `vite.config.ts`:
37
23
 
38
24
  ```ts
@@ -203,8 +189,14 @@ No manual declaration for the virtual module is required.
203
189
 
204
190
  Pages and `not-found.tsx` files use Vite's non-eager `import.meta.glob`, so
205
191
  Vite can emit separate chunks for pages. Layouts are eager because they wrap
206
- the generated route tree; changing a layout can therefore cause a full
207
- development reload. Lazy loading is enabled by default:
192
+ the generated route tree. Vite handles ordinary content changes to pages,
193
+ layouts, and `not-found.tsx` through its normal HMR mechanism. Creating,
194
+ deleting, or renaming a route-related file also refreshes the generated route
195
+ module and route declarations. Because Vite cannot reliably preserve a cached
196
+ route tree when an `import.meta.glob` entry is added or removed, these
197
+ structural changes trigger a full-page reload as a fallback. Lazy-loaded route
198
+ components remain lazy-loaded during normal navigation. Lazy loading is
199
+ enabled by default:
208
200
 
209
201
  ```tsx
210
202
  import { configureRouter } from "next-vite-router";
package/dist/cli.cjs CHANGED
@@ -548,7 +548,7 @@ const init = new commander.Command().name("init").description(
548
548
  Project "${projectName}" is ready!
549
549
  `);
550
550
  });
551
- const version = "1.2.2";
551
+ const version = "1.2.3";
552
552
  const pkg = {
553
553
  version
554
554
  };
package/dist/plugin.js CHANGED
@@ -1,60 +1,60 @@
1
1
  import h from "node:fs";
2
2
  import l from "node:path";
3
- import { a as v, n as b } from "./tree-HwBRWJNI.js";
4
- function x(r) {
5
- const e = r.split(l.sep).filter(Boolean).map(b).filter(Boolean);
3
+ import { a as b, n as j } from "./tree-HwBRWJNI.js";
4
+ function $(n) {
5
+ const e = n.split(l.sep).filter(Boolean).map(j).filter(Boolean);
6
6
  return e.length > 0 ? `/${e.join("/")}` : "/";
7
7
  }
8
- function $(r, e) {
9
- const n = /* @__PURE__ */ new Map();
10
- function s(a) {
11
- for (const t of h.readdirSync(a, { withFileTypes: !0 })) {
12
- const c = l.join(a, t.name);
13
- if (t.isDirectory())
14
- s(c);
15
- else if (t.isFile() && t.name === e) {
16
- const i = l.relative(r, a), u = i.split(l.sep).filter(Boolean), y = u.map((p) => {
17
- const m = p.match(/^\[\[\.\.\.(.+)\]\]$/);
18
- if (m)
19
- return { name: m[1], optional: !0 };
20
- const d = p.match(/^\[\.\.\.(.+)\]$/);
21
- return d ? { name: d[1], optional: !1 } : void 0;
22
- }).filter((p) => !!p), f = x(i);
23
- n.set(f, { path: f, params: y });
24
- const o = u[u.length - 1];
25
- if (o == null ? void 0 : o.match(/^\[\[\.\.\.(.+)\]\]$/)) {
26
- const p = u.slice(0, -1).join(l.sep), m = x(p);
27
- n.has(m) || n.set(m, { path: m, params: [] });
8
+ function T(n, e) {
9
+ const r = /* @__PURE__ */ new Map();
10
+ function i(a) {
11
+ for (const o of h.readdirSync(a, { withFileTypes: !0 })) {
12
+ const p = l.join(a, o.name);
13
+ if (o.isDirectory())
14
+ i(p);
15
+ else if (o.isFile() && o.name === e) {
16
+ const s = l.relative(n, a), u = s.split(l.sep).filter(Boolean), y = u.map((t) => {
17
+ const c = t.match(/^\[\[\.\.\.(.+)\]\]$/);
18
+ if (c)
19
+ return { name: c[1], optional: !0 };
20
+ const m = t.match(/^\[\.\.\.(.+)\]$/);
21
+ return m ? { name: m[1], optional: !1 } : void 0;
22
+ }).filter((t) => !!t), d = $(s);
23
+ r.set(d, { path: d, params: y });
24
+ const f = u[u.length - 1];
25
+ if (f == null ? void 0 : f.match(/^\[\[\.\.\.(.+)\]\]$/)) {
26
+ const t = u.slice(0, -1).join(l.sep), c = $(t);
27
+ r.has(c) || r.set(c, { path: c, params: [] });
28
28
  }
29
29
  }
30
30
  }
31
31
  }
32
- return h.existsSync(r) && s(r), [...n.values()].sort((a, t) => a.path.localeCompare(t.path));
32
+ return h.existsSync(n) && i(n), [...r.values()].sort((a, o) => a.path.localeCompare(o.path));
33
33
  }
34
- function P(r, e) {
35
- const n = [];
36
- function s(a) {
37
- for (const t of h.readdirSync(a, { withFileTypes: !0 })) {
38
- const c = l.join(a, t.name);
39
- t.isDirectory() ? s(c) : t.isFile() && t.name === e && n.push(l.relative(r, c));
34
+ function F(n, e) {
35
+ const r = [];
36
+ function i(a) {
37
+ for (const o of h.readdirSync(a, { withFileTypes: !0 })) {
38
+ const p = l.join(a, o.name);
39
+ o.isDirectory() ? i(p) : o.isFile() && o.name === e && r.push(l.relative(n, p));
40
40
  }
41
41
  }
42
- return h.existsSync(r) && s(r), n;
42
+ return h.existsSync(n) && i(n), r;
43
43
  }
44
- function F(r) {
45
- const e = r.match(/^\/(?:\[\.\.\.|:)([^/\]]+)\]?$/);
44
+ function k(n) {
45
+ const e = n.match(/^\/(?:\[\.\.\.|:)([^/\]]+)\]?$/);
46
46
  return e == null ? void 0 : e[1];
47
47
  }
48
- function j(r) {
49
- const e = r.map(({ path: s }) => ` | "${s}"`).join(`
50
- `), n = r.map(({ path: s, params: a }) => {
51
- const t = s.split("/").map((i) => F(`/${i}`)).filter((i) => !!i), c = t.length > 0 || a.length > 0 ? [
52
- ...t.map((i) => ` ${i}: string;`),
53
- ...a.map(({ name: i, optional: u }) => ` ${i}${u ? "?" : ""}: string;`)
48
+ function w(n) {
49
+ const e = n.map(({ path: i }) => ` | "${i}"`).join(`
50
+ `), r = n.map(({ path: i, params: a }) => {
51
+ const o = i.split("/").map((s) => k(`/${s}`)).filter((s) => !!s), p = o.length > 0 || a.length > 0 ? [
52
+ ...o.map((s) => ` ${s}: string;`),
53
+ ...a.map(({ name: s, optional: u }) => ` ${s}${u ? "?" : ""}: string;`)
54
54
  ].join(`
55
55
  `) : " [key: string]: never;";
56
- return ` "${s}": {
57
- ${c}
56
+ return ` "${i}": {
57
+ ${p}
58
58
  };`;
59
59
  }).join(`
60
60
  `);
@@ -70,7 +70,7 @@ ${e || ' | "/"'};
70
70
  : never;
71
71
 
72
72
  export interface RoutePathParams {
73
- ${n}
73
+ ${r}
74
74
  }
75
75
 
76
76
  export const generateRoutes: () => RouteObject[];
@@ -80,53 +80,62 @@ ${n}
80
80
  }
81
81
  `;
82
82
  }
83
- function S(r = {}) {
83
+ function D(n = {}) {
84
84
  const {
85
85
  pagesDir: e = "src/app",
86
- pageFile: n = "page.tsx",
87
- layoutFile: s = "layout.tsx",
86
+ pageFile: r = "page.tsx",
87
+ layoutFile: i = "layout.tsx",
88
88
  notFoundFile: a = "not-found.tsx"
89
- } = r, t = { pagesDir: e, pageFile: n, layoutFile: s, notFoundFile: a }, c = "virtual:next-vite-router", i = "\0" + c;
90
- let u = "", y = "";
91
- function f() {
92
- const o = j($(u, n));
93
- h.writeFileSync(y, o, "utf-8");
89
+ } = n, o = { pagesDir: e, pageFile: r, layoutFile: i, notFoundFile: a }, p = "virtual:next-vite-router", s = "\0" + p;
90
+ let u = "", y = "", d, f;
91
+ function g() {
92
+ const t = w(T(u, r));
93
+ h.writeFileSync(y, t, "utf-8");
94
94
  }
95
95
  return {
96
96
  name: "next-vite-router",
97
- configResolved(o) {
98
- u = l.resolve(o.root, e), y = l.join(l.dirname(u), "virtual-next-vite-router.d.ts"), v(P(u, n), t), f();
97
+ configResolved(t) {
98
+ u = l.resolve(t.root, e), y = l.join(l.dirname(u), "virtual-next-vite-router.d.ts"), b(F(u, r), o), g();
99
99
  },
100
- configureServer(o) {
101
- const g = (p) => {
102
- if (l.relative(u, p).startsWith("..") || ![n, s, a].includes(l.basename(p)))
100
+ configureServer(t) {
101
+ if (d === t)
102
+ return;
103
+ f == null || f(), d = t;
104
+ const c = (P) => {
105
+ if (l.relative(u, P).startsWith("..") || ![r, i, a].includes(l.basename(P)))
103
106
  return;
104
107
  try {
105
- v(P(u, n), t);
106
- } catch (R) {
107
- o.config.logger.error(
108
- R instanceof Error ? R.message : String(R)
108
+ b(F(u, r), o);
109
+ } catch (x) {
110
+ t.config.logger.error(
111
+ x instanceof Error ? x.message : String(x)
109
112
  );
110
113
  return;
111
114
  }
112
- f();
113
- const d = o.moduleGraph.getModuleById(i);
114
- d && (o.moduleGraph.invalidateModule(d), o.ws.send({ type: "full-reload", path: "*" }));
115
+ g();
116
+ const v = t.moduleGraph.getModuleById(s);
117
+ v && (t.moduleGraph.invalidateModule(v), m && clearTimeout(m), m = setTimeout(() => {
118
+ m = void 0, t.ws.send({ type: "full-reload", path: "*" });
119
+ }, 0));
115
120
  };
116
- o.watcher.on("add", g), o.watcher.on("unlink", g);
121
+ let m;
122
+ const R = () => {
123
+ m && (clearTimeout(m), m = void 0), t.watcher.off("add", c), t.watcher.off("unlink", c), t.watcher.off("close", R), d === t && (d = void 0, f = void 0);
124
+ };
125
+ t.watcher.on("add", c), t.watcher.on("unlink", c), t.watcher.once("close", R), f = R;
117
126
  },
118
- resolveId(o) {
119
- if (o === c)
120
- return i;
127
+ resolveId(t) {
128
+ if (t === p)
129
+ return s;
121
130
  },
122
- load(o) {
123
- if (o === i)
131
+ load(t) {
132
+ if (t === s)
124
133
  return `
125
134
  import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement, useParams } from 'next-vite-router';
126
135
  import { Link, useRoutes } from 'react-router-dom';
127
136
 
128
- const pagesGlob = import.meta.glob('/${e}/**/${n}');
129
- const layoutsGlob = import.meta.glob('/${e}/**/${s}', { eager: true });
137
+ const pagesGlob = import.meta.glob('/${e}/**/${r}');
138
+ const layoutsGlob = import.meta.glob('/${e}/**/${i}', { eager: true });
130
139
  const notFoundsGlob = import.meta.glob('/${e}/**/${a}');
131
140
 
132
141
  const transformPath = (path) => path.replace('/${e}/', '');
@@ -142,7 +151,7 @@ const notFounds = Object.fromEntries(
142
151
  );
143
152
 
144
153
  export function generateRoutes() {
145
- const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(t)});
154
+ const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(o)});
146
155
  const routes = treeToRoutes(tree, true);
147
156
  return routes;
148
157
  }
@@ -154,6 +163,12 @@ export function Router() {
154
163
 
155
164
  let routes;
156
165
 
166
+ if (import.meta.hot) {
167
+ import.meta.hot.accept(() => {
168
+ routes = undefined;
169
+ });
170
+ }
171
+
157
172
  export { Link, useRoutes };
158
173
  export { useParams };
159
174
  `;
@@ -161,5 +176,5 @@ export { useParams };
161
176
  };
162
177
  }
163
178
  export {
164
- S as nextViteRouter
179
+ D as nextViteRouter
165
180
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-vite-router",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Next.js-like file-based routing for React + Vite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",