@rudderjs/vite 0.0.5 → 0.0.7
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 +16 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -1
- package/dist/index.js.map +1 -1
- package/dist/views-scanner.d.ts +25 -0
- package/dist/views-scanner.d.ts.map +1 -0
- package/dist/views-scanner.js +355 -0
- package/dist/views-scanner.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @rudderjs/vite
|
|
2
2
|
|
|
3
|
-
Vite plugin for RudderJS. Registers Vike (SSR), sets the `@/` path alias, externalizes server-only packages from the client bundle, and wires up WebSocket upgrade handling for `@rudderjs/broadcast` and `@rudderjs/
|
|
3
|
+
Vite plugin for RudderJS. Registers Vike (SSR), sets the `@/` path alias, externalizes server-only packages from the client bundle, and wires up WebSocket upgrade handling for `@rudderjs/broadcast` and `@rudderjs/sync`.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
pnpm add @rudderjs/vite
|
|
@@ -25,23 +25,34 @@ export default defineConfig({
|
|
|
25
25
|
That's it. `rudderjs()` handles:
|
|
26
26
|
|
|
27
27
|
- **Vike registration** — auto-detects and registers `vike/plugin` for SSR + file-based routing
|
|
28
|
-
- **
|
|
28
|
+
- **View scanner** — scans `app/Views/**` and generates virtual Vike pages under `pages/__view/` for `@rudderjs/view`
|
|
29
|
+
- **HMR route reload** — watches `routes/`, `bootstrap/`, and `app/` so edits there invalidate the SSR module graph without restarting the dev server
|
|
30
|
+
- **Path alias** — `@/` and `App/` resolve to the app directory
|
|
29
31
|
- **SSR externals** — server-only packages (database drivers, Redis, queue adapters) are externalized from the client bundle
|
|
30
32
|
- **SSR no-externals** — `@rudderjs/server-hono` is forced non-external so Vite processes virtual module imports
|
|
31
|
-
- **WebSocket upgrade** — intercepts `http.createServer` to attach the `__rudderjs_ws_upgrade__` handler for `@rudderjs/broadcast` and `@rudderjs/
|
|
33
|
+
- **WebSocket upgrade** — intercepts `http.createServer` to attach the `__rudderjs_ws_upgrade__` handler for `@rudderjs/broadcast` and `@rudderjs/sync`
|
|
34
|
+
- **`x-real-ip` injection** — dev-only, populates the header from the Node socket so `req.ip` works through Vike's universal middleware
|
|
32
35
|
- **Sourcemap warnings** — suppresses noisy "missing source files" warnings for `@rudderjs/*` packages
|
|
33
36
|
- **Build externals** — server-only packages are excluded from production builds
|
|
34
37
|
|
|
35
38
|
## What it produces
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
Five Vite plugins:
|
|
38
41
|
|
|
39
42
|
| Plugin | Purpose |
|
|
40
43
|
|--------|---------|
|
|
41
|
-
| `rudderjs:ws` | WebSocket upgrade handler via `configureServer` |
|
|
42
44
|
| `rudderjs:config` | SSR externals, path alias, warning suppression |
|
|
45
|
+
| `rudderjs:ws` | WebSocket upgrade handler via `configureServer` |
|
|
46
|
+
| `rudderjs:ip` | Dev-only `x-real-ip` injection from Node socket |
|
|
47
|
+
| `rudderjs:routes` | HMR watcher for `routes/` + `bootstrap/` + `app/`; invalidates SSR modules + clears `__rudderjs_instance__` and `__rudderjs_app__` globals so the next request re-bootstraps cleanly |
|
|
48
|
+
| `rudderjs:views` | View scanner — generates virtual Vike pages from `app/Views/**` |
|
|
43
49
|
| *(vike plugins)* | SSR rendering, file-based routing (auto-registered) |
|
|
44
50
|
|
|
51
|
+
### HMR notes
|
|
52
|
+
|
|
53
|
+
- `rudderjs:routes` never calls `server.restart()` — doing so closes Vite's module runner and breaks in-flight SSR requests. Module invalidation + globalThis cleanup is enough to force a full re-bootstrap on the next request.
|
|
54
|
+
- Changes under `app/` require the full cleanup (not just invalidation) because models, controllers, and resources are captured in provider closures during boot.
|
|
55
|
+
|
|
45
56
|
## SSR Externals
|
|
46
57
|
|
|
47
58
|
These packages are externalized from the SSR bundle (Node.js-only, not browser-compatible):
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAqDlC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CA8M5C;AAED,eAAe,QAAQ,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
import { viewsScannerPlugin } from './views-scanner.js';
|
|
3
4
|
// ─── SSR / build externals ─────────────────────────────────
|
|
4
5
|
const SSR_EXTERNALS = [
|
|
6
|
+
// @rudderjs/view — linked package, Vite's SSR module runner can't resolve
|
|
7
|
+
// it via its internal fetchModule path in non-workspace consumers (fresh
|
|
8
|
+
// scaffolded app + pnpm link). Loading it through Node's native ESM
|
|
9
|
+
// (which handles the symlink correctly) sidesteps the issue.
|
|
10
|
+
'@rudderjs/view',
|
|
5
11
|
// CLI-only — uses node:process stdin/readline
|
|
6
12
|
'@clack/core',
|
|
7
13
|
'@clack/prompts',
|
|
@@ -62,6 +68,11 @@ export function rudderjs() {
|
|
|
62
68
|
// Build plugins asynchronously — we need a dynamic import to guarantee we
|
|
63
69
|
// load vike from the *app root* (not packages/vite/node_modules).
|
|
64
70
|
const promise = (async () => {
|
|
71
|
+
// Construct the views scanner BEFORE loading Vike's plugin — the scanner's
|
|
72
|
+
// factory eagerly writes generated stubs to `pages/__view/`, and Vike scans
|
|
73
|
+
// the pages directory during its own plugin instantiation. If we load Vike
|
|
74
|
+
// first, the stubs don't exist yet and Vike will 404 on /__view/* routes.
|
|
75
|
+
const viewsScanner = viewsScannerPlugin();
|
|
65
76
|
let vikePlugins = [];
|
|
66
77
|
try {
|
|
67
78
|
const vikePath = _require.resolve('vike/plugin');
|
|
@@ -73,11 +84,28 @@ export function rudderjs() {
|
|
|
73
84
|
}
|
|
74
85
|
return [
|
|
75
86
|
...vikePlugins,
|
|
87
|
+
viewsScanner,
|
|
88
|
+
{
|
|
89
|
+
// Inject x-real-ip header from the Node socket so downstream Hono
|
|
90
|
+
// middleware can read the client IP. Vike's universal-middleware
|
|
91
|
+
// converts the Express request to a Web Request which loses socket info.
|
|
92
|
+
name: 'rudderjs:ip',
|
|
93
|
+
configureServer(server) {
|
|
94
|
+
server.middlewares.use((req, _res, next) => {
|
|
95
|
+
if (!req.headers['x-real-ip'] && !req.headers['x-forwarded-for']) {
|
|
96
|
+
const ip = req.socket?.remoteAddress;
|
|
97
|
+
if (ip)
|
|
98
|
+
req.headers['x-real-ip'] = ip;
|
|
99
|
+
}
|
|
100
|
+
next();
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
},
|
|
76
104
|
{
|
|
77
105
|
name: 'rudderjs:ws',
|
|
78
106
|
configureServer(server) {
|
|
79
107
|
// Attach the WebSocket upgrade handler to Vite's own HTTP server.
|
|
80
|
-
// @rudderjs/broadcast and @rudderjs/
|
|
108
|
+
// @rudderjs/broadcast and @rudderjs/sync register their handlers on
|
|
81
109
|
// globalThis['__rudderjs_ws_upgrade__'] during provider boot. We listen
|
|
82
110
|
// for 'upgrade' events and forward them to that handler.
|
|
83
111
|
//
|
|
@@ -127,6 +155,43 @@ export function rudderjs() {
|
|
|
127
155
|
});
|
|
128
156
|
},
|
|
129
157
|
},
|
|
158
|
+
{
|
|
159
|
+
name: 'rudderjs:routes',
|
|
160
|
+
configureServer(server) {
|
|
161
|
+
// Watch route, bootstrap, and app files for SSR changes. These files
|
|
162
|
+
// are dynamically imported during bootstrap or within route handlers
|
|
163
|
+
// so Vite doesn't track them in its SSR module graph — changes go
|
|
164
|
+
// unnoticed without an explicit watcher.
|
|
165
|
+
const cwd = process.cwd();
|
|
166
|
+
const watchDirs = [
|
|
167
|
+
path.resolve(cwd, 'routes'),
|
|
168
|
+
path.resolve(cwd, 'bootstrap'),
|
|
169
|
+
path.resolve(cwd, 'app'),
|
|
170
|
+
];
|
|
171
|
+
for (const dir of watchDirs)
|
|
172
|
+
server.watcher.add(dir);
|
|
173
|
+
server.watcher.on('change', (file) => {
|
|
174
|
+
if (!watchDirs.some(d => file.startsWith(d)))
|
|
175
|
+
return;
|
|
176
|
+
// Clear the two top-level singletons so a new RudderJS + Application
|
|
177
|
+
// pair is created when the module re-executes. App files (models,
|
|
178
|
+
// resources, controllers) are captured in closures during bootstrap
|
|
179
|
+
// so they also need a full re-bootstrap to pick up changes.
|
|
180
|
+
const g = globalThis;
|
|
181
|
+
delete g['__rudderjs_instance__'];
|
|
182
|
+
delete g['__rudderjs_app__'];
|
|
183
|
+
// Invalidate all SSR modules so Vike re-executes bootstrap/app.ts
|
|
184
|
+
// (and transitively all app code) on the next request. This is
|
|
185
|
+
// lighter than server.restart() and avoids closing the module runner
|
|
186
|
+
// while requests may still be in flight.
|
|
187
|
+
server.environments.ssr.moduleGraph.invalidateAll();
|
|
188
|
+
// Tell the browser to do a full page reload so it picks up the
|
|
189
|
+
// changes via a fresh SSR request.
|
|
190
|
+
server.hot.send({ type: 'full-reload' });
|
|
191
|
+
console.log(`[RudderJS] change detected — reloading (${path.relative(cwd, file)}`);
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
},
|
|
130
195
|
{
|
|
131
196
|
name: 'rudderjs:config',
|
|
132
197
|
configResolved(config) {
|
|
@@ -153,6 +218,18 @@ export function rudderjs() {
|
|
|
153
218
|
{ find: /^App\//, replacement: path.resolve(process.cwd(), 'app') + '/' },
|
|
154
219
|
],
|
|
155
220
|
},
|
|
221
|
+
// `@rudderjs/view` is imported from routes/web.ts during SSR. Vite's
|
|
222
|
+
// first-run dep pre-bundler can't resolve it when the package is
|
|
223
|
+
// linked via pnpm overrides in a non-workspace project (e.g. a
|
|
224
|
+
// fresh scaffolded app pointing at a local rudderjs checkout) —
|
|
225
|
+
// the second `vike dev` invocation succeeds because Vite's cache
|
|
226
|
+
// is warm, but the first cold boot fails with a cryptic
|
|
227
|
+
// "Cannot find module '@rudderjs/view'" error. Excluding it from
|
|
228
|
+
// dep optimization lets Vite resolve it via normal Node ESM and
|
|
229
|
+
// skips the flaky scan.
|
|
230
|
+
optimizeDeps: {
|
|
231
|
+
exclude: ['@rudderjs/view'],
|
|
232
|
+
},
|
|
156
233
|
ssr: {
|
|
157
234
|
external: SSR_EXTERNALS,
|
|
158
235
|
noExternal: SSR_NO_EXTERNALS,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* app/Views scanner — generates virtual Vike pages for files in `app/Views/**`.
|
|
3
|
+
*
|
|
4
|
+
* For a React project `app/Views/Dashboard.tsx` we emit:
|
|
5
|
+
*
|
|
6
|
+
* pages/__view/dashboard/+Page.tsx → re-exports user's view + reads viewProps from pageContext
|
|
7
|
+
* pages/__view/dashboard/+route.ts → pins the route to /dashboard
|
|
8
|
+
* pages/__view/dashboard/+data.ts → no-op; forces Vike client router to fetch pageContext
|
|
9
|
+
*
|
|
10
|
+
* The generated `pages/__view/` directory is gitignored. The plugin watches
|
|
11
|
+
* `app/Views/**` and regenerates on add/remove/rename.
|
|
12
|
+
*
|
|
13
|
+
* Framework selection is automatic — the scanner resolves `vike-react`,
|
|
14
|
+
* `vike-vue`, or `vike-solid` from the project's package.json at plugin
|
|
15
|
+
* construction time. If none are installed, the scanner falls back to
|
|
16
|
+
* **vanilla mode** (the "Blade equivalent"): `.ts`/`.js` views that export a
|
|
17
|
+
* function returning an HTML string, no client hydration.
|
|
18
|
+
*/
|
|
19
|
+
import type { Plugin } from 'vite';
|
|
20
|
+
/**
|
|
21
|
+
* Vite plugin that scans `app/Views/**` and emits virtual Vike pages
|
|
22
|
+
* under `pages/__view/`. Watches the source directory in dev mode.
|
|
23
|
+
*/
|
|
24
|
+
export declare function viewsScannerPlugin(): Plugin;
|
|
25
|
+
//# sourceMappingURL=views-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views-scanner.d.ts","sourceRoot":"","sources":["../src/views-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AA2UlC;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAgD3C"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* app/Views scanner — generates virtual Vike pages for files in `app/Views/**`.
|
|
3
|
+
*
|
|
4
|
+
* For a React project `app/Views/Dashboard.tsx` we emit:
|
|
5
|
+
*
|
|
6
|
+
* pages/__view/dashboard/+Page.tsx → re-exports user's view + reads viewProps from pageContext
|
|
7
|
+
* pages/__view/dashboard/+route.ts → pins the route to /dashboard
|
|
8
|
+
* pages/__view/dashboard/+data.ts → no-op; forces Vike client router to fetch pageContext
|
|
9
|
+
*
|
|
10
|
+
* The generated `pages/__view/` directory is gitignored. The plugin watches
|
|
11
|
+
* `app/Views/**` and regenerates on add/remove/rename.
|
|
12
|
+
*
|
|
13
|
+
* Framework selection is automatic — the scanner resolves `vike-react`,
|
|
14
|
+
* `vike-vue`, or `vike-solid` from the project's package.json at plugin
|
|
15
|
+
* construction time. If none are installed, the scanner falls back to
|
|
16
|
+
* **vanilla mode** (the "Blade equivalent"): `.ts`/`.js` views that export a
|
|
17
|
+
* function returning an HTML string, no client hydration.
|
|
18
|
+
*/
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
// ─── Framework detection ───────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Resolve which UI framework the project uses by probing `vike-*` packages
|
|
24
|
+
* in the app-root's node_modules. Runs once at plugin construction.
|
|
25
|
+
*
|
|
26
|
+
* Uses a direct fs check rather than `require.resolve` to avoid Node's
|
|
27
|
+
* module resolution cache (which can return stale hits in tests and when
|
|
28
|
+
* dependencies are swapped without a process restart).
|
|
29
|
+
*/
|
|
30
|
+
function detectFramework(cwd) {
|
|
31
|
+
const nodeModules = path.join(cwd, 'node_modules');
|
|
32
|
+
const installed = [];
|
|
33
|
+
for (const [pkg, fw] of [
|
|
34
|
+
['vike-react', 'react'],
|
|
35
|
+
['vike-vue', 'vue'],
|
|
36
|
+
['vike-solid', 'solid'],
|
|
37
|
+
]) {
|
|
38
|
+
if (fs.existsSync(path.join(nodeModules, pkg, 'package.json'))) {
|
|
39
|
+
installed.push(fw);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (installed.length > 1) {
|
|
43
|
+
throw new Error(`[rudderjs:views-scanner] Multiple Vike renderers found (${installed.join(', ')}). ` +
|
|
44
|
+
`Install only one of vike-react, vike-vue, vike-solid.`);
|
|
45
|
+
}
|
|
46
|
+
return installed[0] ?? 'vanilla';
|
|
47
|
+
}
|
|
48
|
+
// ─── Extensions per framework ──────────────────────────────
|
|
49
|
+
const EXTENSIONS_BY_FRAMEWORK = {
|
|
50
|
+
react: ['.tsx', '.jsx'],
|
|
51
|
+
vue: ['.vue'],
|
|
52
|
+
solid: ['.tsx', '.jsx'],
|
|
53
|
+
vanilla: ['.ts', '.js'],
|
|
54
|
+
};
|
|
55
|
+
// ─── Id / path helpers ─────────────────────────────────────
|
|
56
|
+
function stripExt(file) {
|
|
57
|
+
return file.replace(/\.(tsx|jsx|vue|ts|js)$/i, '');
|
|
58
|
+
}
|
|
59
|
+
/** Convert `Dashboard.tsx` → `dashboard`, `Users/Show.tsx` → `users.show` */
|
|
60
|
+
function fileToId(relPath) {
|
|
61
|
+
return stripExt(relPath)
|
|
62
|
+
.split(path.sep)
|
|
63
|
+
.map(seg => seg.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase())
|
|
64
|
+
.join('.');
|
|
65
|
+
}
|
|
66
|
+
function walk(dir, extensions, base = dir) {
|
|
67
|
+
if (!fs.existsSync(dir))
|
|
68
|
+
return [];
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
71
|
+
const full = path.join(dir, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
out.push(...walk(full, extensions, base));
|
|
74
|
+
}
|
|
75
|
+
else if (extensions.some(e => entry.name.toLowerCase().endsWith(e))) {
|
|
76
|
+
out.push(path.relative(base, full));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Scan the view source for an optional `export const route = '...'` or
|
|
83
|
+
* `export const route = "..."` declaration and return its value. Matches
|
|
84
|
+
* TypeScript, JavaScript, and the <script setup> block inside a .vue file.
|
|
85
|
+
*
|
|
86
|
+
* Regex-based on purpose — parsing TS ASTs here would be overkill and
|
|
87
|
+
* introduce a dep. The pattern is strict enough that false positives require
|
|
88
|
+
* deliberate obfuscation.
|
|
89
|
+
*/
|
|
90
|
+
const ROUTE_EXPORT_RE = /(?:^|[\s;])export\s+const\s+route\s*(?::\s*string)?\s*=\s*['"`]([^'"`]+)['"`]/m;
|
|
91
|
+
function readRouteOverride(absPath) {
|
|
92
|
+
try {
|
|
93
|
+
const source = fs.readFileSync(absPath, 'utf8');
|
|
94
|
+
const m = source.match(ROUTE_EXPORT_RE);
|
|
95
|
+
return m ? m[1] ?? null : null;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function discover(viewsRoot, pagesRoot, framework) {
|
|
102
|
+
const exts = EXTENSIONS_BY_FRAMEWORK[framework];
|
|
103
|
+
return walk(viewsRoot, exts).map(rel => {
|
|
104
|
+
const id = fileToId(rel);
|
|
105
|
+
const absPath = path.join(viewsRoot, rel);
|
|
106
|
+
// Use the App/ alias (already configured in @rudderjs/vite) so the
|
|
107
|
+
// generated import is portable across machines.
|
|
108
|
+
const importPath = `App/Views/${rel.replace(/\\/g, '/')}`;
|
|
109
|
+
const outDir = path.join(pagesRoot, '__view', ...id.split('.'));
|
|
110
|
+
const url = readRouteOverride(absPath) ?? '/' + id.replace(/\./g, '/');
|
|
111
|
+
return { id, absPath, importPath, outDir, url };
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// ─── Stub generators ───────────────────────────────────────
|
|
115
|
+
function reactStub(view) {
|
|
116
|
+
return {
|
|
117
|
+
filename: '+Page.tsx',
|
|
118
|
+
contents: `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
119
|
+
// Source: ${view.importPath}
|
|
120
|
+
import ViewComponent from '${view.importPath}'
|
|
121
|
+
import { usePageContext } from 'vike-react/usePageContext'
|
|
122
|
+
|
|
123
|
+
// Cast to a permissive component type — controller-supplied props are validated
|
|
124
|
+
// at the call site (view('id', props)), not in this generated stub.
|
|
125
|
+
const View = ViewComponent as unknown as (props: Record<string, unknown>) => JSX.Element
|
|
126
|
+
|
|
127
|
+
export default function Page() {
|
|
128
|
+
const ctx = usePageContext() as unknown as { viewProps?: Record<string, unknown> }
|
|
129
|
+
const props = ctx.viewProps ?? {}
|
|
130
|
+
return <View {...props} />
|
|
131
|
+
}
|
|
132
|
+
`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function solidStub(view) {
|
|
136
|
+
return {
|
|
137
|
+
filename: '+Page.tsx',
|
|
138
|
+
contents: `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
139
|
+
// Source: ${view.importPath}
|
|
140
|
+
import ViewComponent from '${view.importPath}'
|
|
141
|
+
import { usePageContext } from 'vike-solid/usePageContext'
|
|
142
|
+
|
|
143
|
+
const View = ViewComponent as unknown as (props: Record<string, unknown>) => JSX.Element
|
|
144
|
+
|
|
145
|
+
export default function Page() {
|
|
146
|
+
const ctx = usePageContext() as unknown as { viewProps?: Record<string, unknown> }
|
|
147
|
+
return <View {...(ctx.viewProps ?? {})} />
|
|
148
|
+
}
|
|
149
|
+
`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function vueStub(view) {
|
|
153
|
+
return {
|
|
154
|
+
filename: '+Page.vue',
|
|
155
|
+
contents: `<!-- AUTO-GENERATED by @rudderjs/vite — do not edit. -->
|
|
156
|
+
<!-- Source: ${view.importPath} -->
|
|
157
|
+
<script setup lang="ts">
|
|
158
|
+
import ViewComponent from '${view.importPath}'
|
|
159
|
+
import { usePageContext } from 'vike-vue/usePageContext'
|
|
160
|
+
|
|
161
|
+
const pageContext = usePageContext()
|
|
162
|
+
const viewProps = (pageContext as { viewProps?: Record<string, unknown> }).viewProps ?? {}
|
|
163
|
+
</script>
|
|
164
|
+
<template>
|
|
165
|
+
<ViewComponent v-bind="viewProps" />
|
|
166
|
+
</template>
|
|
167
|
+
`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function vanillaStub(view) {
|
|
171
|
+
return {
|
|
172
|
+
filename: '+Page.ts',
|
|
173
|
+
contents: `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
174
|
+
// Source: ${view.importPath}
|
|
175
|
+
import renderView from '${view.importPath}'
|
|
176
|
+
import type { PageContext } from 'vike/types'
|
|
177
|
+
|
|
178
|
+
export function Page(pageContext: PageContext): string {
|
|
179
|
+
const viewProps = (pageContext as { viewProps?: Record<string, unknown> }).viewProps ?? {}
|
|
180
|
+
// View functions may return a plain string or a SafeString from @rudderjs/view's
|
|
181
|
+
// html\`\` tag. String(...) coerces both uniformly (SafeString.toString() returns
|
|
182
|
+
// its already-safe value).
|
|
183
|
+
const result = (renderView as (props: Record<string, unknown>) => unknown)(viewProps)
|
|
184
|
+
return typeof result === 'string' ? result : String(result)
|
|
185
|
+
}
|
|
186
|
+
`,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const STUB_GENERATORS = {
|
|
190
|
+
react: reactStub,
|
|
191
|
+
vue: vueStub,
|
|
192
|
+
solid: solidStub,
|
|
193
|
+
vanilla: vanillaStub,
|
|
194
|
+
};
|
|
195
|
+
// ─── Shared framework-agnostic files ───────────────────────
|
|
196
|
+
/**
|
|
197
|
+
* No-op +data hook. Its presence forces Vike's client router to recognize
|
|
198
|
+
* this page as having a server-side hook (`hasServerOnlyHook: true`), which
|
|
199
|
+
* makes it fetch `pageContext.json` on every SPA navigation. Without this,
|
|
200
|
+
* navigating from a regular Vike page into a controller view skips the fetch
|
|
201
|
+
* entirely and renders the view with `viewProps = {}` — crashing the page.
|
|
202
|
+
* The actual viewProps are injected via `pageContextInit` from the controller's
|
|
203
|
+
* `renderPage()` call, not via this hook.
|
|
204
|
+
*/
|
|
205
|
+
const DATA_FILE_SOURCE = `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
206
|
+
import type { PageContextServer } from 'vike/types'
|
|
207
|
+
export const data = (_pageContext: PageContextServer): null => null
|
|
208
|
+
`;
|
|
209
|
+
function routeFileSource(view) {
|
|
210
|
+
// CRITICAL: the route URL must match the controller route the user registers
|
|
211
|
+
// (e.g. `Route.get('/home', () => view('home'))`). Vike's client router does
|
|
212
|
+
// its own route table lookup before fetching pageContext.json — if `/home`
|
|
213
|
+
// is not in the table, it falls back to a full page reload.
|
|
214
|
+
//
|
|
215
|
+
// By default, the view id maps 1:1 to the URL path ('home' → /home). A view
|
|
216
|
+
// file can override this by exporting a `route` constant at the top-level —
|
|
217
|
+
// useful when the controller's URL differs from the natural id path
|
|
218
|
+
// (e.g. `app/Views/Welcome.tsx` served at `/` instead of `/welcome`).
|
|
219
|
+
return `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
220
|
+
export default '${view.url}'
|
|
221
|
+
`;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Single shared config at the views root that tells Vike to serialize
|
|
225
|
+
* `viewProps` from server pageContext to the client. Without this, the
|
|
226
|
+
* server SSR works but hydration crashes because the client component
|
|
227
|
+
* receives `props = {}` (viewProps is undefined client-side).
|
|
228
|
+
*/
|
|
229
|
+
const VIEW_ROOT_CONFIG = `// AUTO-GENERATED by @rudderjs/vite — do not edit.
|
|
230
|
+
// Forwards controller-supplied viewProps from server SSR to client hydration.
|
|
231
|
+
import type { Config } from 'vike/types'
|
|
232
|
+
|
|
233
|
+
export default {
|
|
234
|
+
passToClient: ['viewProps'],
|
|
235
|
+
} satisfies Config
|
|
236
|
+
`;
|
|
237
|
+
// ─── File IO ───────────────────────────────────────────────
|
|
238
|
+
const ALL_PAGE_FILENAMES = ['+Page.tsx', '+Page.jsx', '+Page.vue', '+Page.ts', '+Page.js'];
|
|
239
|
+
function writeIfChanged(file, contents) {
|
|
240
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
241
|
+
if (fs.existsSync(file)) {
|
|
242
|
+
const existing = fs.readFileSync(file, 'utf8');
|
|
243
|
+
if (existing === contents)
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
fs.writeFileSync(file, contents);
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
/** Remove any `+Page.*` file in this view's dir that isn't the current target. */
|
|
250
|
+
function purgeStalePageFiles(outDir, keep) {
|
|
251
|
+
if (!fs.existsSync(outDir))
|
|
252
|
+
return;
|
|
253
|
+
for (const name of ALL_PAGE_FILENAMES) {
|
|
254
|
+
if (name === keep)
|
|
255
|
+
continue;
|
|
256
|
+
const p = path.join(outDir, name);
|
|
257
|
+
if (fs.existsSync(p))
|
|
258
|
+
fs.rmSync(p);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function generate(generatedRoot, views, framework) {
|
|
262
|
+
if (views.length === 0)
|
|
263
|
+
return;
|
|
264
|
+
writeIfChanged(path.join(generatedRoot, '+config.ts'), VIEW_ROOT_CONFIG);
|
|
265
|
+
const generator = STUB_GENERATORS[framework];
|
|
266
|
+
for (const v of views) {
|
|
267
|
+
const stub = generator(v);
|
|
268
|
+
purgeStalePageFiles(v.outDir, stub.filename);
|
|
269
|
+
writeIfChanged(path.join(v.outDir, stub.filename), stub.contents);
|
|
270
|
+
writeIfChanged(path.join(v.outDir, '+route.ts'), routeFileSource(v));
|
|
271
|
+
writeIfChanged(path.join(v.outDir, '+data.ts'), DATA_FILE_SOURCE);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function cleanStale(generatedRoot, current) {
|
|
275
|
+
if (!fs.existsSync(generatedRoot))
|
|
276
|
+
return;
|
|
277
|
+
const expected = new Set(current.map(v => v.outDir));
|
|
278
|
+
const walkDirs = (dir) => {
|
|
279
|
+
const out = [];
|
|
280
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
281
|
+
if (!entry.isDirectory())
|
|
282
|
+
continue;
|
|
283
|
+
const full = path.join(dir, entry.name);
|
|
284
|
+
// Leaf dirs are identified by a generated +route.ts (framework-agnostic).
|
|
285
|
+
if (fs.existsSync(path.join(full, '+route.ts'))) {
|
|
286
|
+
out.push(full);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
out.push(...walkDirs(full));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return out;
|
|
293
|
+
};
|
|
294
|
+
for (const dir of walkDirs(generatedRoot)) {
|
|
295
|
+
if (!expected.has(dir)) {
|
|
296
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// ─── Plugin ────────────────────────────────────────────────
|
|
301
|
+
/**
|
|
302
|
+
* Vite plugin that scans `app/Views/**` and emits virtual Vike pages
|
|
303
|
+
* under `pages/__view/`. Watches the source directory in dev mode.
|
|
304
|
+
*/
|
|
305
|
+
export function viewsScannerPlugin() {
|
|
306
|
+
const cwd = process.cwd();
|
|
307
|
+
const viewsRoot = path.join(cwd, 'app', 'Views');
|
|
308
|
+
const pagesRoot = path.join(cwd, 'pages');
|
|
309
|
+
const generatedRoot = path.join(pagesRoot, '__view');
|
|
310
|
+
// Detect the framework lazily — only when we actually need to scan views.
|
|
311
|
+
// This keeps the plugin silent on projects that don't use app/Views/ at
|
|
312
|
+
// all (e.g. multi-framework scaffolder setups that install vike-react AND
|
|
313
|
+
// vike-vue for demo pages but never call view()). If detection is done
|
|
314
|
+
// eagerly, those projects crash at plugin construction with a "multiple
|
|
315
|
+
// renderers" error even though they don't touch @rudderjs/view.
|
|
316
|
+
let framework = null;
|
|
317
|
+
const getFramework = () => framework ??= detectFramework(cwd);
|
|
318
|
+
const sync = () => {
|
|
319
|
+
const fw = getFramework();
|
|
320
|
+
const views = discover(viewsRoot, pagesRoot, fw);
|
|
321
|
+
cleanStale(generatedRoot, views);
|
|
322
|
+
generate(generatedRoot, views, fw);
|
|
323
|
+
};
|
|
324
|
+
// Eager sync at plugin construction time — Vike scans `pages/` during its
|
|
325
|
+
// own plugin init, so the generated stubs MUST exist on disk before any
|
|
326
|
+
// Vite/Vike hook fires. configureServer/buildStart are too late.
|
|
327
|
+
if (fs.existsSync(viewsRoot))
|
|
328
|
+
sync();
|
|
329
|
+
return {
|
|
330
|
+
name: 'rudderjs:views-scanner',
|
|
331
|
+
enforce: 'pre',
|
|
332
|
+
buildStart() {
|
|
333
|
+
if (!fs.existsSync(viewsRoot))
|
|
334
|
+
return;
|
|
335
|
+
sync();
|
|
336
|
+
},
|
|
337
|
+
configureServer(server) {
|
|
338
|
+
if (!fs.existsSync(viewsRoot))
|
|
339
|
+
return;
|
|
340
|
+
server.watcher.add(viewsRoot);
|
|
341
|
+
const onChange = (file) => {
|
|
342
|
+
if (!file.startsWith(viewsRoot))
|
|
343
|
+
return;
|
|
344
|
+
const exts = EXTENSIONS_BY_FRAMEWORK[getFramework()];
|
|
345
|
+
if (!exts.some(e => file.toLowerCase().endsWith(e)))
|
|
346
|
+
return;
|
|
347
|
+
sync();
|
|
348
|
+
};
|
|
349
|
+
server.watcher.on('add', onChange);
|
|
350
|
+
server.watcher.on('unlink', onChange);
|
|
351
|
+
server.watcher.on('change', onChange);
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=views-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views-scanner.js","sourceRoot":"","sources":["../src/views-scanner.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudderjs/vite",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"dev": "tsc -p tsconfig.build.json --watch",
|
|
53
53
|
"typecheck": "tsc --noEmit",
|
|
54
54
|
"lint": "eslint src",
|
|
55
|
-
"test": "tsc -p tsconfig.test.json && node --test dist-test/index.test.js; EXIT=$?; rm -rf dist-test; exit $EXIT",
|
|
55
|
+
"test": "tsc -p tsconfig.test.json && node --test dist-test/index.test.js dist-test/views-scanner.test.js; EXIT=$?; rm -rf dist-test; exit $EXIT",
|
|
56
56
|
"clean": "rm -rf dist"
|
|
57
57
|
}
|
|
58
58
|
}
|