next-vite-router 1.0.3 → 1.0.4

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 (3) hide show
  1. package/README.md +42 -12
  2. package/dist/index.js +53 -48
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Next Vite Router is an npm package that provides Next.js-style, file-based routing for React applications built with Vite. It generates React Router route objects from a filesystem layout (pages, layouts, not-found), and it exposes a Vite plugin that injects a virtual module to generate routes at build/dev time.
4
4
 
5
- This README focuses on how consumers install and use the package (no publishing instructions).
6
-
7
5
  ## Installation
8
6
 
9
7
  Install with your package manager of choice:
@@ -37,28 +35,60 @@ export default defineConfig({
37
35
  });
38
36
  ```
39
37
 
40
- Example usage inside your app (client entry):
38
+ Example usage inside your app. **Important: generate routes once at module level** (not inside the component) to avoid infinite re-renders.
39
+
40
+ File: `src/App.tsx`
41
41
 
42
42
  ```tsx
43
- import React from 'react';
44
- import { BrowserRouter } from 'react-router-dom';
45
- import { generateRoutes, useRoutes } from 'virtual:next-vite-router';
43
+ import { useRoutes } from 'react-router-dom';
44
+ import { generateRoutes } from 'virtual:next-vite-router';
46
45
 
47
46
  const routes = generateRoutes();
48
47
 
49
- function App() {
48
+ export default function App() {
50
49
  const element = useRoutes(routes);
51
- return <BrowserRouter>{element}</BrowserRouter>;
50
+ return element;
52
51
  }
52
+ ```
53
+
54
+ File: `src/main.tsx`
53
55
 
54
- export default App;
56
+ ```tsx
57
+ import { StrictMode } from 'react';
58
+ import { createRoot } from 'react-dom/client';
59
+ import { BrowserRouter } from 'react-router-dom';
60
+ import App from './App';
61
+
62
+ createRoot(document.getElementById('root')!).render(
63
+ <StrictMode>
64
+ <BrowserRouter>
65
+ <App />
66
+ </BrowserRouter>
67
+ </StrictMode>
68
+ );
55
69
  ```
56
70
 
57
- Notes:
71
+ **Key points:**
58
72
 
59
- - The plugin default `pagesDir` is `src/app`. You can change it via options.
73
+ - Call `generateRoutes()` once at module level, not inside the component (prevents infinite re-renders).
74
+ - Wrap your app with `BrowserRouter` at the entry point (`main.tsx`), not inside `App`.
75
+ - `pagesDir` (default: `src/app`) is the directory where you organize your **route files** (`page.tsx`, `layout.tsx`, `not-found.tsx`). It has nothing to do with the `App.tsx` component.
60
76
  - The virtual module is `virtual:next-vite-router` (the plugin resolves it internally).
61
77
 
78
+ **Example file structure:**
79
+
80
+ ```
81
+ src/
82
+ ├── App.tsx ← Your main app component
83
+ ├── main.tsx ← Entry point (with BrowserRouter)
84
+ └── app/ ← pagesDir (routes are organized here)
85
+ ├── page.tsx ← Home page
86
+ ├── layout.tsx ← Root layout
87
+ └── dashboard/
88
+ ├── page.tsx ← /dashboard page
89
+ └── layout.tsx ← Dashboard layout
90
+ ```
91
+
62
92
  TypeScript note:
63
93
 
64
94
  If you're using TypeScript in a consuming project, add a declaration file so the virtual module is recognized by the compiler. Create a file such as `src/virtual.d.ts` (or any `*.d.ts` included by your `tsconfig.json`) with the following content:
@@ -170,4 +200,4 @@ Pass a custom `pagesDir` if your project uses `src/pages` or another convention.
170
200
 
171
201
  ## License
172
202
 
173
- MIT
203
+ MIT
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import i, { lazy as z, Suspense as b } from "react";
2
- import { nextViteRouter as N } from "./plugin.js";
1
+ import i, { Suspense as g, lazy as z } from "react";
2
+ import { nextViteRouter as D } from "./plugin.js";
3
3
  function f(e) {
4
4
  return /^\([^)]+\)$/.test(e) ? "" : /^\[\.\.\.(.+)\]$/.test(e) ? "*" : /^\[([^\]]+)\]$/.test(e) ? e.replace(/^\[([^\]]+)\]$/, ":$1") : e;
5
5
  }
@@ -7,78 +7,83 @@ function F(e) {
7
7
  return e.replace("../../app/", "").replace(/\/?(page|layout|not-found)\.tsx$/, "");
8
8
  }
9
9
  let m = {};
10
- function S(e) {
10
+ function k(e) {
11
11
  m = { ...m, ...e };
12
12
  }
13
13
  function C() {
14
14
  return m;
15
15
  }
16
16
  let d = [];
17
- function k(e, a) {
17
+ function S(e, a) {
18
18
  d.push({ pattern: e, middleware: a });
19
19
  }
20
20
  function T() {
21
21
  d = [];
22
22
  }
23
- function g(e, a) {
23
+ function E(e, a) {
24
24
  let r = a;
25
25
  for (const n of d)
26
26
  n.pattern.test(e) && (r = n.middleware(r));
27
27
  return r;
28
28
  }
29
- const x = () => i.createElement("div"), E = /* @__PURE__ */ new Map();
30
- function $(e, a, r) {
29
+ const x = () => i.createElement("div"), y = /* @__PURE__ */ new Map();
30
+ function R(e, a, r) {
31
31
  const n = C();
32
32
  if (n.enableLazyLoading === !1) {
33
- const u = i.lazy(e), c = i.createElement(u);
34
- return r ? g(r, c) : c;
33
+ const u = i.lazy(e), c = i.createElement(
34
+ g,
35
+ { fallback: null },
36
+ // No loading fallback when disabled
37
+ i.createElement(u)
38
+ );
39
+ return r ? E(r, c) : c;
35
40
  }
36
- let t = E.get(a);
37
- t || (t = z(e), E.set(a, t));
38
- const o = n.loadingFallback || x, l = i.createElement(
39
- b,
40
- { fallback: i.createElement(o) },
41
+ let t = y.get(a);
42
+ t || (t = z(e), y.set(a, t));
43
+ const l = n.loadingFallback || x, o = i.createElement(
44
+ g,
45
+ { fallback: i.createElement(l) },
41
46
  i.createElement(t)
42
47
  );
43
- return r ? g(r, l) : l;
48
+ return r ? E(r, o) : o;
44
49
  }
45
50
  function p(e, a, r, n) {
46
- const t = F(a), o = t ? t.split("/") : [];
47
- let l = e, u = "";
48
- o.forEach((c, w) => {
49
- u = u ? `${u}/${c}` : c, l.children.has(c) || l.children.set(c, {
51
+ const t = F(a), l = t ? t.split("/") : [];
52
+ let o = e, u = "";
53
+ l.forEach((c, w) => {
54
+ u = u ? `${u}/${c}` : c, o.children.has(c) || o.children.set(c, {
50
55
  segment: c,
51
56
  fullPath: u,
52
57
  children: /* @__PURE__ */ new Map()
53
- }), l = l.children.get(c), w === o.length - 1 && (l[n] = r);
54
- }), o.length === 0 && (e[n] = r);
58
+ }), o = o.children.get(c), w === l.length - 1 && (o[n] = r);
59
+ }), l.length === 0 && (e[n] = r);
55
60
  }
56
- function M(e, a, r) {
61
+ function L(e, a, r) {
57
62
  const n = {
58
63
  segment: "",
59
64
  fullPath: "",
60
65
  children: /* @__PURE__ */ new Map()
61
66
  };
62
- return Object.entries(a).forEach(([t, o]) => {
63
- p(n, t, o.default, "layout");
64
- }), Object.entries(e).forEach(([t, o]) => {
65
- p(n, t, o, "page");
66
- }), Object.entries(r).forEach(([t, o]) => {
67
- p(n, t, o, "notFound");
67
+ return Object.entries(a).forEach(([t, l]) => {
68
+ p(n, t, l.default, "layout");
69
+ }), Object.entries(e).forEach(([t, l]) => {
70
+ p(n, t, l, "page");
71
+ }), Object.entries(r).forEach(([t, l]) => {
72
+ p(n, t, l, "notFound");
68
73
  }), n;
69
74
  }
70
75
  function h(e, a, r = !1) {
71
- const n = $(
76
+ const n = R(
72
77
  async () => ({ default: (await e.page()).default }),
73
78
  `page:${e.fullPath || a}`,
74
79
  a
75
80
  );
76
81
  return r ? { index: !0, element: n } : { path: f(e.segment), element: n };
77
82
  }
78
- function y(e) {
83
+ function $(e) {
79
84
  return {
80
85
  path: "*",
81
- element: $(
86
+ element: R(
82
87
  async () => ({ default: (await e.notFound()).default }),
83
88
  `notfound:${e.fullPath}`
84
89
  )
@@ -87,15 +92,15 @@ function y(e) {
87
92
  function s(e, a) {
88
93
  const r = [];
89
94
  return e.children.forEach((n, t) => {
90
- const o = f(t), l = o ? a ? `${a}/${o}` : `/${o}` : a;
91
- r.push(...R(n, !1, l));
95
+ const l = f(t), o = l ? a ? `${a}/${l}` : `/${l}` : a;
96
+ r.push(...b(n, !1, o));
92
97
  }), r;
93
98
  }
94
- function R(e, a = !1, r = "") {
99
+ function b(e, a = !1, r = "") {
95
100
  const n = [];
96
101
  if (a && e.layout) {
97
102
  const t = [];
98
- return e.page && t.push(h(e, "/", !0)), t.push(...s(e, "")), e.notFound && t.push(y(e)), n.push({
103
+ return e.page && t.push(h(e, "/", !0)), t.push(...s(e, "")), e.notFound && t.push($(e)), n.push({
99
104
  path: "/",
100
105
  element: i.createElement(e.layout),
101
106
  children: t
@@ -105,41 +110,41 @@ function R(e, a = !1, r = "") {
105
110
  const t = f(e.segment);
106
111
  if (!t)
107
112
  return s(e, r);
108
- const o = r + "/" + t, l = [];
109
- return e.page && l.push(h(e, o, !0)), l.push(...s(e, o)), e.notFound && l.push(y(e)), n.push({
113
+ const l = r + "/" + t, o = [];
114
+ return e.page && o.push(h(e, l, !0)), o.push(...s(e, l)), e.notFound && o.push($(e)), n.push({
110
115
  path: t,
111
116
  element: i.createElement(e.layout),
112
- children: l.length > 0 ? l : void 0
117
+ children: o.length > 0 ? o : void 0
113
118
  }), n;
114
119
  }
115
120
  if (e.page) {
116
121
  const t = f(e.segment);
117
122
  if (!t)
118
123
  return s(e, r);
119
- const o = r + "/" + t, l = s(e, o), u = h(e, o, !1);
124
+ const l = r + "/" + t, o = s(e, l), u = h(e, l, !1);
120
125
  return n.push({
121
126
  path: u.path,
122
127
  element: u.element,
123
- children: l.length > 0 ? l : void 0
128
+ children: o.length > 0 ? o : void 0
124
129
  }), n;
125
130
  }
126
131
  return s(e, r);
127
132
  }
128
133
  function j(e, a, r) {
129
134
  return () => {
130
- const n = M(e, a, r);
131
- return R(n, !0);
135
+ const n = L(e, a, r);
136
+ return b(n, !0);
132
137
  };
133
138
  }
134
139
  export {
135
- M as buildRouteTree,
140
+ L as buildRouteTree,
136
141
  T as clearMiddlewares,
137
- S as configureRouter,
138
- $ as createLazyElement,
142
+ k as configureRouter,
143
+ R as createLazyElement,
139
144
  j as createRouteGenerator,
140
145
  F as extractRoutePath,
141
- N as nextViteRouter,
146
+ D as nextViteRouter,
142
147
  f as normalizeSegment,
143
- k as registerMiddleware,
144
- R as treeToRoutes
148
+ S as registerMiddleware,
149
+ b as treeToRoutes
145
150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-vite-router",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Next.js-like file-based routing for React + Vite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",