@void/react 0.7.13 → 0.8.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.
Files changed (2) hide show
  1. package/dist/plugin.mjs +46 -43
  2. package/package.json +3 -3
package/dist/plugin.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import react from "@vitejs/plugin-react";
2
+ import { generateComponentManifest, resolveEffectiveLayoutChain, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages } from "void/pages";
2
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
4
  import { normalizePath } from "vite";
4
- import { generateComponentManifest, resolveEffectiveLayoutChain, resolveStaticPageDataBuildOptions, scanPages } from "void/pages";
5
5
  import { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, extractCssImports, needsIslandClientBundle, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan } from "void/pages-islands-plugin";
6
6
  //#region ../../node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
7
7
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
@@ -9,42 +9,9 @@ function normalizeWindowsPath(input = "") {
9
9
  if (!input) return input;
10
10
  return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
11
11
  }
12
- const _UNC_REGEX = /^[/\\]{2}/;
13
12
  const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
14
13
  const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
15
14
  const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
16
- const normalize = function(path) {
17
- if (path.length === 0) return ".";
18
- path = normalizeWindowsPath(path);
19
- const isUNCPath = path.match(_UNC_REGEX);
20
- const isPathAbsolute = isAbsolute(path);
21
- const trailingSeparator = path[path.length - 1] === "/";
22
- path = normalizeString(path, !isPathAbsolute);
23
- if (path.length === 0) {
24
- if (isPathAbsolute) return "/";
25
- return trailingSeparator ? "./" : ".";
26
- }
27
- if (trailingSeparator) path += "/";
28
- if (_DRIVE_LETTER_RE.test(path)) path += "/";
29
- if (isUNCPath) {
30
- if (!isPathAbsolute) return `//./${path}`;
31
- return `//${path}`;
32
- }
33
- return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
34
- };
35
- const join = function(...segments) {
36
- let path = "";
37
- for (const seg of segments) {
38
- if (!seg) continue;
39
- if (path.length > 0) {
40
- const pathTrailing = path[path.length - 1] === "/";
41
- const segLeading = seg[0] === "/";
42
- if (pathTrailing && segLeading) path += seg.slice(1);
43
- else path += pathTrailing || segLeading ? seg : `/${seg}`;
44
- } else path += seg;
45
- }
46
- return normalize(path);
47
- };
48
15
  function cwd() {
49
16
  if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
50
17
  return "/";
@@ -158,10 +125,10 @@ function findIslandImports(code) {
158
125
  }
159
126
  return imports;
160
127
  }
161
- function islandsPlugin(pagesDir) {
128
+ function islandsPlugin(pagesDir, options) {
162
129
  let pageScan = null;
163
130
  let isDev = false;
164
- const root = dirname(pagesDir);
131
+ const root = options?.root ?? dirname(pagesDir);
165
132
  const islandManifest = /* @__PURE__ */ new Map();
166
133
  const islandCssFiles = /* @__PURE__ */ new Set();
167
134
  let viteRoot = "";
@@ -184,7 +151,7 @@ function islandsPlugin(pagesDir) {
184
151
  },
185
152
  async buildStart() {
186
153
  if (existsSync(pagesDir)) {
187
- pageScan = await scanPages(root);
154
+ pageScan = await scanPages(root, { pagesDir });
188
155
  const filesToScan = [
189
156
  ...pageScan.pages.map((page) => ({
190
157
  filePath: page.componentPath,
@@ -422,6 +389,7 @@ const REACT_OPTIMIZE_DEPS = [
422
389
  "react-dom/client",
423
390
  "react-dom/server"
424
391
  ];
392
+ const WORKER_OPTIMIZE_DEPS = [...REACT_OPTIMIZE_DEPS, "void/live/client"];
425
393
  /** Check if the pages directory has any non-island page files (.tsx/.jsx without .island.). */
426
394
  function hasNonIslandPages(dir) {
427
395
  try {
@@ -441,11 +409,29 @@ function pagesPlugin(pagesDir, options) {
441
409
  let pageScan = null;
442
410
  let isDev = false;
443
411
  let viteConfig;
444
- const root = dirname(pagesDir);
412
+ const root = options?.root ?? dirname(pagesDir);
413
+ const normalizedPagesDir = normalizePath(pagesDir);
414
+ const pagesOptimizeEntries = `${relative(root, pagesDir)}/**/*.{js,jsx,ts,tsx}`;
415
+ let pendingRescan = null;
416
+ const rescanPages = async () => {
417
+ pageScan = existsSync(pagesDir) ? await scanPages(root, { pagesDir }) : null;
418
+ };
419
+ const runRescan = () => {
420
+ pendingRescan ??= rescanPages().finally(() => {
421
+ pendingRescan = null;
422
+ });
423
+ return pendingRescan;
424
+ };
425
+ const invalidatePageModules = (server) => {
426
+ for (const env of Object.values(server.environments)) for (const id of ["\0" + RENDERER_ID, "\0" + CLIENT_ENTRY_ID]) {
427
+ const mod = env.moduleGraph.getModuleById(id);
428
+ if (mod) env.moduleGraph.invalidateModule(mod);
429
+ }
430
+ };
445
431
  return {
446
432
  name: "void-react:pages",
447
433
  async buildStart() {
448
- if (existsSync(pagesDir)) pageScan = await scanPages(root);
434
+ await runRescan();
449
435
  },
450
436
  resolveId: {
451
437
  filter: { id: /^virtual:void-pages-(renderer|client)$/ },
@@ -455,7 +441,9 @@ function pagesPlugin(pagesDir, options) {
455
441
  },
456
442
  load: {
457
443
  filter: { id: /^\0virtual:void-pages-(renderer|client)$/ },
458
- handler(id) {
444
+ async handler(id) {
445
+ if (isDev && pendingRescan) await pendingRescan;
446
+ if (!pageScan && existsSync(pagesDir)) await runRescan();
459
447
  if (id === "\0" + RENDERER_ID) {
460
448
  if (!pageScan) return "export function renderPage() { throw new Error('No pages found'); }";
461
449
  return generateRendererModule(pageScan, pagesDir, isDev);
@@ -466,6 +454,18 @@ function pagesPlugin(pagesDir, options) {
466
454
  }
467
455
  }
468
456
  },
457
+ configureServer(server) {
458
+ const handlePagesChange = async (path, event) => {
459
+ const normalizedPath = normalizePath(path);
460
+ if (normalizedPath !== normalizedPagesDir && !normalizedPath.startsWith(normalizedPagesDir + "/")) return;
461
+ if (event === "change" && !normalizedPath.endsWith(".md")) return;
462
+ await runRescan();
463
+ invalidatePageModules(server);
464
+ };
465
+ server.watcher.on("add", (path) => handlePagesChange(path, "add"));
466
+ server.watcher.on("change", (path) => handlePagesChange(path, "change"));
467
+ server.watcher.on("unlink", (path) => handlePagesChange(path, "unlink"));
468
+ },
469
469
  configResolved(config) {
470
470
  viteConfig = config;
471
471
  },
@@ -482,7 +482,8 @@ function pagesPlugin(pagesDir, options) {
482
482
  ssr: { optimizeDeps: { include: REACT_OPTIMIZE_DEPS } },
483
483
  environments: { [WORKER_ENVIRONMENT_NAME]: { optimizeDeps: {
484
484
  exclude: ["@void/react"],
485
- include: REACT_OPTIMIZE_DEPS
485
+ entries: [pagesOptimizeEntries],
486
+ include: WORKER_OPTIMIZE_DEPS
486
487
  } } }
487
488
  };
488
489
  }
@@ -548,14 +549,16 @@ function generateClientEntry(scan, pagesDir, viewTransitions, prefetch, staticPa
548
549
  //#endregion
549
550
  //#region src/plugin.ts
550
551
  function voidReact(options) {
551
- const pagesDir = join(process.cwd(), "pages");
552
+ const root = process.cwd();
553
+ const pagesDir = resolvePagesDir(root);
552
554
  return [
553
555
  ...react(options?.react),
554
556
  pagesPlugin(pagesDir, {
557
+ root,
555
558
  viewTransitions: options?.viewTransitions,
556
559
  prefetch: options?.prefetch
557
560
  }),
558
- ...islandsPlugin(pagesDir)
561
+ ...islandsPlugin(pagesDir, { root })
559
562
  ];
560
563
  }
561
564
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/react",
3
- "version": "0.7.13",
3
+ "version": "0.8.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -51,13 +51,13 @@
51
51
  "react-dom": "^19.2.6",
52
52
  "vite": "npm:@voidzero-dev/vite-plus-core@0.1.20",
53
53
  "vite-plus": "^0.1.20",
54
- "void": "0.7.13"
54
+ "void": "0.8.0"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "react": "^19.0.0",
58
58
  "react-dom": "^19.0.0",
59
59
  "vite": "^8.0.0",
60
- "void": "0.7.13"
60
+ "void": "0.8.0"
61
61
  },
62
62
  "scripts": {
63
63
  "build": "vp pack",