@webjsdev/server 0.8.83 → 0.8.85
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/package.json +1 -1
- package/src/action-seed.js +8 -0
- package/src/actions.js +2 -2
- package/src/api.js +2 -2
- package/src/component-elision.js +96 -43
- package/src/component-scanner.js +40 -16
- package/src/dev/bun-alias-resolve.js +71 -0
- package/src/dev/bun-app-source.js +66 -0
- package/src/dev/handler.js +76 -11
- package/src/dev/hot-host.js +176 -0
- package/src/dev/serve.js +3 -3
- package/src/dev/server.js +95 -7
- package/src/dev-import.js +66 -9
- package/src/dev-reload-worker.js +33 -3
- package/src/dev-source-locations-hook.js +7 -0
- package/src/env-schema.js +2 -2
- package/src/form-action-identity.js +2 -2
- package/src/instrumentation.js +2 -2
- package/src/listener-core.js +10 -4
- package/src/metadata-routes.js +4 -4
- package/src/module-graph.js +39 -12
- package/src/ssr/render.js +2 -2
package/src/metadata-routes.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { sitemap as sitemapXml, robots as robotsTxt } from './sitemap.js';
|
|
22
22
|
import { isUrlSegment } from './router.js';
|
|
23
|
-
import {
|
|
23
|
+
import { devImport } from './dev-import.js';
|
|
24
24
|
import { siteUrlFromEnv } from './ssr/seo.js';
|
|
25
25
|
import { basePath } from './importmap.js';
|
|
26
26
|
import { withBasePath } from './base-path.js';
|
|
@@ -42,7 +42,7 @@ async function isNoindex(files, dev) {
|
|
|
42
42
|
let robots;
|
|
43
43
|
for (const file of files) {
|
|
44
44
|
try {
|
|
45
|
-
const mod = await
|
|
45
|
+
const mod = await devImport(file, dev);
|
|
46
46
|
if (mod.metadata && typeof mod.metadata === 'object' && mod.metadata.robots !== undefined) {
|
|
47
47
|
robots = mod.metadata.robots;
|
|
48
48
|
}
|
|
@@ -120,7 +120,7 @@ export async function listPages(routeTable, { siteUrl, dev }) {
|
|
|
120
120
|
}
|
|
121
121
|
let mod;
|
|
122
122
|
try {
|
|
123
|
-
mod = await
|
|
123
|
+
mod = await devImport(page.file, dev);
|
|
124
124
|
} catch {
|
|
125
125
|
continue;
|
|
126
126
|
}
|
|
@@ -167,7 +167,7 @@ function absoluteEntries(entries, siteUrl) {
|
|
|
167
167
|
* @returns {Promise<Response | null>} null when the module has no default export
|
|
168
168
|
*/
|
|
169
169
|
export async function runMetadataRoute(meta, { req, url, path, dev, routeTable }) {
|
|
170
|
-
const mod = await
|
|
170
|
+
const mod = await devImport(meta.file, dev);
|
|
171
171
|
if (typeof mod.default !== 'function') return null;
|
|
172
172
|
const siteUrl = siteUrlFromEnv() || url.origin;
|
|
173
173
|
const ctx = {
|
package/src/module-graph.js
CHANGED
|
@@ -508,7 +508,7 @@ async function walk(dir, appDir, graph, seen, dynamic, bare, bareDynamic) {
|
|
|
508
508
|
* rebuilds incremental for large apps without restructuring the caller.
|
|
509
509
|
* Keyed by mtime AND size: a same-tick edit that also changes the file length
|
|
510
510
|
* is caught even on coarse-resolution filesystems where mtime alone could miss.
|
|
511
|
-
* @type {Map<string, { mtimeMs: number, size: number,
|
|
511
|
+
* @type {Map<string, { mtimeMs: number, size: number, specs: string[], dynSpecs: string[], bareDeps: Set<string>, bareDynDeps: Set<string> }>}
|
|
512
512
|
*/
|
|
513
513
|
const PARSE_CACHE = new Map();
|
|
514
514
|
|
|
@@ -530,10 +530,7 @@ async function parseFile(file, appDir, graph, seen, dynamic, bare, bareDynamic)
|
|
|
530
530
|
seen?.add(file); // mark live (both cache-hit and miss paths) for cache eviction
|
|
531
531
|
const cached = PARSE_CACHE.get(file);
|
|
532
532
|
if (cached && cached.mtimeMs === mtimeMs && cached.size === size) {
|
|
533
|
-
|
|
534
|
-
if (cached.dynDeps && cached.dynDeps.size && dynamic) dynamic.set(file, cached.dynDeps);
|
|
535
|
-
if (cached.bareDeps && cached.bareDeps.size && bare) bare.set(file, cached.bareDeps);
|
|
536
|
-
if (cached.bareDynDeps && cached.bareDynDeps.size && bareDynamic) bareDynamic.set(file, cached.bareDynDeps);
|
|
533
|
+
addResolved(file, appDir, cached, graph, dynamic, bare, bareDynamic);
|
|
537
534
|
return;
|
|
538
535
|
}
|
|
539
536
|
|
|
@@ -574,7 +571,8 @@ async function parseFile(file, appDir, graph, seen, dynamic, bare, bareDynamic)
|
|
|
574
571
|
// string (blanked here), so it is read back from raw `src` via the match's
|
|
575
572
|
// group indices (the `d` flag).
|
|
576
573
|
const masked = redactStringsAndTemplates(src, true);
|
|
577
|
-
|
|
574
|
+
/** @type {string[]} local (relative / aliased) static specifiers */
|
|
575
|
+
const specs = [];
|
|
578
576
|
/** @type {Set<string>} bare npm vendor specifiers imported by this file (#754) */
|
|
579
577
|
const bareDeps = new Set();
|
|
580
578
|
for (const re of [IMPORT_RE, EXPORT_FROM_RE]) {
|
|
@@ -612,8 +610,7 @@ async function parseFile(file, appDir, graph, seen, dynamic, bare, bareDynamic)
|
|
|
612
610
|
if (isVendorSpecifier(spec)) bareDeps.add(spec);
|
|
613
611
|
continue;
|
|
614
612
|
}
|
|
615
|
-
|
|
616
|
-
if (resolved) deps.add(resolved);
|
|
613
|
+
specs.push(spec);
|
|
617
614
|
}
|
|
618
615
|
}
|
|
619
616
|
// Dynamic `import('…')` with a string-literal specifier (#751): a separate
|
|
@@ -636,7 +633,8 @@ async function parseFile(file, appDir, graph, seen, dynamic, bare, bareDynamic)
|
|
|
636
633
|
// computed `import(expr)` still falls out (its char after the quote is not
|
|
637
634
|
// `,`/`)`), preserving the documented limitation.
|
|
638
635
|
const { redacted: holeAware, literals } = redactToPlaceholders(src);
|
|
639
|
-
|
|
636
|
+
/** @type {string[]} local dynamic-import specifiers */
|
|
637
|
+
const dynSpecs = [];
|
|
640
638
|
const bareDynDeps = new Set();
|
|
641
639
|
for (const m of holeAware.matchAll(DYNAMIC_IMPORT_RE)) {
|
|
642
640
|
const token = m[1];
|
|
@@ -651,14 +649,43 @@ async function parseFile(file, appDir, graph, seen, dynamic, bare, bareDynamic)
|
|
|
651
649
|
if (isVendorSpecifier(spec)) bareDynDeps.add(spec);
|
|
652
650
|
continue;
|
|
653
651
|
}
|
|
652
|
+
dynSpecs.push(spec);
|
|
653
|
+
}
|
|
654
|
+
const parsed = { mtimeMs, size, specs, dynSpecs, bareDeps, bareDynDeps };
|
|
655
|
+
PARSE_CACHE.set(file, parsed);
|
|
656
|
+
addResolved(file, appDir, parsed, graph, dynamic, bare, bareDynamic);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Resolve a parsed file's specifiers and add its edges to the graph maps.
|
|
661
|
+
*
|
|
662
|
+
* The cache holds SPECIFIERS, not resolved paths (#1575): resolution depends on
|
|
663
|
+
* which files exist, not on the importer's own bytes, so a cached resolution
|
|
664
|
+
* outlives the file system it was made against. An importer written before the
|
|
665
|
+
* module it imports (the order an agent often writes them in) resolved to
|
|
666
|
+
* nothing, was cached that way, and kept no edge after the target appeared,
|
|
667
|
+
* because the importer's mtime never changed again; the gate then 404'd the new
|
|
668
|
+
* module. Resolving on every build costs a few `existsSync` calls per edge.
|
|
669
|
+
*
|
|
670
|
+
* @param {string} file
|
|
671
|
+
* @param {string} appDir
|
|
672
|
+
* @param {{ specs: string[], dynSpecs: string[], bareDeps: Set<string>, bareDynDeps: Set<string> }} parsed
|
|
673
|
+
*/
|
|
674
|
+
function addResolved(file, appDir, parsed, graph, dynamic, bare, bareDynamic) {
|
|
675
|
+
const deps = new Set();
|
|
676
|
+
for (const spec of parsed.specs) {
|
|
677
|
+
const resolved = resolveImport(spec, file, appDir);
|
|
678
|
+
if (resolved) deps.add(resolved);
|
|
679
|
+
}
|
|
680
|
+
const dynDeps = new Set();
|
|
681
|
+
for (const spec of parsed.dynSpecs) {
|
|
654
682
|
const resolved = resolveImport(spec, file, appDir);
|
|
655
683
|
if (resolved && !deps.has(resolved)) dynDeps.add(resolved);
|
|
656
684
|
}
|
|
657
|
-
PARSE_CACHE.set(file, { mtimeMs, size, deps, dynDeps, bareDeps, bareDynDeps });
|
|
658
685
|
if (deps.size) graph.set(file, deps);
|
|
659
686
|
if (dynDeps.size && dynamic) dynamic.set(file, dynDeps);
|
|
660
|
-
if (bareDeps.size && bare) bare.set(file, bareDeps);
|
|
661
|
-
if (bareDynDeps.size && bareDynamic) bareDynamic.set(file, bareDynDeps);
|
|
687
|
+
if (parsed.bareDeps.size && bare) bare.set(file, parsed.bareDeps);
|
|
688
|
+
if (parsed.bareDynDeps.size && bareDynamic) bareDynamic.set(file, parsed.bareDynDeps);
|
|
662
689
|
}
|
|
663
690
|
|
|
664
691
|
/**
|
package/src/ssr/render.js
CHANGED
|
@@ -17,7 +17,7 @@ import { escapeHtml } from './escape.js';
|
|
|
17
17
|
import {
|
|
18
18
|
cachedHtmlResponse, getNonce, htmlResponse, streamingHtmlResponse,
|
|
19
19
|
} from './responses.js';
|
|
20
|
-
import {
|
|
20
|
+
import { devImport } from '../dev-import.js';
|
|
21
21
|
import { applySeoDefaults } from './seo.js';
|
|
22
22
|
|
|
23
23
|
|
|
@@ -108,7 +108,7 @@ export function privateFragment(res) {
|
|
|
108
108
|
* @param {boolean} dev
|
|
109
109
|
*/
|
|
110
110
|
async function loadModule(file, dev) {
|
|
111
|
-
return
|
|
111
|
+
return devImport(file, dev);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|