@markless/router 0.9.0 → 0.10.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.
@@ -12,7 +12,9 @@ export async function resumeContainerEvent(input: {
12
12
  const routeWakeModule = loadRouteWakeModule ? await loadRouteWakeModule() : undefined;
13
13
  const resume = (routeWakeModule as RouteWakeModule | undefined)?.resumeContainerEvent;
14
14
  if (typeof resume !== 'function') {
15
- throw new Error(`Markless Router could not wake prerendered route module: ${file ?? '<unknown>'}`);
15
+ throw new Error(
16
+ `Markless Router could not wake prerendered route module: ${file ?? '<unknown>'}`,
17
+ );
16
18
  }
17
19
  await resume(input);
18
20
  }
@@ -1,21 +1,18 @@
1
- const mdxPageModuleLoaders = import.meta.glob('/pages/**/*.mdx', {
2
- query: '?markless-resume',
3
- });
4
- const tsrxResumeModuleLoaders = import.meta.glob('/pages/**/*.tsrx', {
5
- query: '?markless-resume',
6
- });
7
- const routeResumeModules = new WeakMap<() => Promise<unknown>, Promise<unknown>>();
1
+ import { mdxResumeModules, tsrxResumeModules } from 'virtual:markless-router/dev-resume-modules';
2
+
3
+ const routeResumeModules = new Map<unknown, Promise<unknown>>();
8
4
 
9
5
  export async function resumeContainerEvent(input: {
10
6
  readonly root: ParentNode;
11
7
  readonly [key: string]: unknown;
12
8
  }) {
13
- const file = routeFileFromRoot(input.root);
9
+ const route = routeFromRoot(input.root);
10
+ const file = route?.file;
11
+ // The page this event belongs to: a navigation that keeps the container starts a new one while the route module loads.
12
+ const life = (input.root as { readonly __mL?: object }).__mL;
14
13
  try {
15
- const loadRouteResumeModule = file && routeResumeModuleLoader(file);
16
- const routeResumeModule = loadRouteResumeModule
17
- ? await loadRouteModuleOnce(loadRouteResumeModule)
18
- : undefined;
14
+ const routeResumeModule = route ? await loadRouteResumeModule(route) : undefined;
15
+ if ((input.root as { readonly __mL?: object }).__mL !== life) return;
19
16
  const resume = (routeResumeModule as RouteResumeModule | undefined)?.resumeContainerEvent;
20
17
  if (typeof resume !== 'function') {
21
18
  throw new Error(
@@ -43,24 +40,40 @@ interface RouteResumeModule {
43
40
  readonly resumeContainerEvent?: (input: unknown) => unknown;
44
41
  }
45
42
 
46
- function loadRouteModuleOnce(load: () => Promise<unknown>): Promise<unknown> {
47
- let pending = routeResumeModules.get(load);
43
+ interface RouteScript {
44
+ readonly file?: string;
45
+ // The built chunk holding the route's resume module, then the export evaluating it inside a pack and the one holding it.
46
+ readonly resume?: readonly [url: string, evaluate?: string, read?: string];
47
+ }
48
+
49
+ function loadRouteResumeModule(route: RouteScript): Promise<unknown> | undefined {
50
+ const [url, evaluate, read] = route.resume ?? [];
51
+ const key = url ?? (route.file && devResumeModuleLoader(route.file));
52
+ if (!key) return undefined;
53
+ let pending = routeResumeModules.get(key);
48
54
  if (!pending) {
49
- pending = load().catch((error: unknown) => {
50
- routeResumeModules.delete(load);
55
+ pending = (
56
+ typeof key === 'string'
57
+ ? import(/* @vite-ignore */ key).then((module: Record<string, () => unknown>) => {
58
+ const evaluated = evaluate ? module[evaluate]!() : module;
59
+ return read ? module[read] : evaluated;
60
+ })
61
+ : key()
62
+ ).catch((error: unknown) => {
63
+ routeResumeModules.delete(key);
51
64
  throw error;
52
65
  });
53
- routeResumeModules.set(load, pending);
66
+ routeResumeModules.set(key, pending);
54
67
  }
55
68
  return pending;
56
69
  }
57
70
 
58
- function routeResumeModuleLoader(file: string): (() => Promise<unknown>) | undefined {
59
- const loaders = file.endsWith('.mdx') ? mdxPageModuleLoaders : tsrxResumeModuleLoaders;
60
- return loaders[file] ?? loaders[`/${file}`];
71
+ function devResumeModuleLoader(file: string): (() => Promise<unknown>) | undefined {
72
+ const loaders = file.endsWith('.mdx') ? mdxResumeModules : tsrxResumeModules;
73
+ return loaders?.[file] ?? loaders?.[`/${file}`];
61
74
  }
62
75
 
63
- function routeFileFromRoot(root: ParentNode): string | undefined {
76
+ function routeFromRoot(root: ParentNode): RouteScript | undefined {
64
77
  const script = root.querySelector?.('script[type="@markless/core/route"]');
65
78
  const text = script?.textContent;
66
79
  if (!text) {
@@ -68,8 +81,8 @@ function routeFileFromRoot(root: ParentNode): string | undefined {
68
81
  }
69
82
 
70
83
  try {
71
- const route = JSON.parse(text) as { readonly file?: unknown };
72
- return typeof route.file === 'string' ? route.file : undefined;
84
+ const route = JSON.parse(text) as RouteScript;
85
+ return typeof route.file === 'string' ? route : undefined;
73
86
  } catch {
74
87
  return undefined;
75
88
  }
@@ -0,0 +1,7 @@
1
+ // Every route's resume module: a build entry no page loads, so each module gets its chunk; dev resumes through it.
2
+ export const mdxResumeModules = import.meta.glob('/pages/**/*.mdx', {
3
+ query: '?markless-resume',
4
+ });
5
+ export const tsrxResumeModules = import.meta.glob('/pages/**/*.tsrx', {
6
+ query: '?markless-resume',
7
+ });