@ecopages/lit 0.2.0-beta.9 → 0.2.0-rc.1
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 +2 -2
- package/src/STATIC_RENDER.md +36 -14
- package/src/console.js +12 -6
- package/src/dom-shim.js +13 -12
- package/src/lit-element-hydrate.js +1 -4
- package/src/lit-renderer.d.ts +26 -5
- package/src/lit-renderer.js +215 -241
- package/src/lit-ssr-lazy-preloader.d.ts +1 -1
- package/src/lit-ssr-lazy-preloader.js +155 -153
- package/src/lit-static-render-protocol.d.ts +7 -1
- package/src/lit-static-render-protocol.js +1 -0
- package/src/lit-static-render-session.d.ts +32 -6
- package/src/lit-static-render-session.js +111 -76
- package/src/lit-static-render-worker-client.d.ts +8 -2
- package/src/lit-static-render-worker-client.js +101 -107
- package/src/lit-static-render-worker.js +68 -62
- package/src/lit.constants.js +1 -4
- package/src/lit.plugin.d.ts +8 -0
- package/src/lit.plugin.js +109 -91
- package/src/styled-mixin.js +20 -12
- package/src/utils/lit-html-rendering.js +39 -46
- package/src/lit-static-render-coordinator.d.ts +0 -3
- package/src/lit-static-render-coordinator.js +0 -11
|
@@ -1,167 +1,169 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { getComponentIdentity } from '@ecopages/core';
|
|
2
|
+
import { AssetFactory } from '@ecopages/core/services/asset-processing-service';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
/**
|
|
6
|
+
* Encapsulates SSR lazy script preload behavior for Lit components.
|
|
7
|
+
*
|
|
8
|
+
* Collects `dependencies.scripts` lazy entries with `ssr: true`, resolves the
|
|
9
|
+
* processed entrypoint through the asset pipeline, and imports the module so
|
|
10
|
+
* custom elements are registered before SSR rendering.
|
|
11
|
+
*/
|
|
12
|
+
export class LitSsrLazyPreloader {
|
|
13
|
+
resolveDependencyPath;
|
|
14
|
+
processDependencies;
|
|
15
|
+
preferSourceImports;
|
|
16
|
+
ssrPreloadedScripts = new Set();
|
|
17
|
+
ssrPreloadFailedScripts = new Set();
|
|
18
|
+
ssrPreloadEntrypointCache = new Map();
|
|
19
|
+
constructor({ resolveDependencyPath, processDependencies, preferSourceImports }) {
|
|
20
|
+
this.resolveDependencyPath = resolveDependencyPath;
|
|
21
|
+
this.processDependencies = processDependencies;
|
|
22
|
+
this.preferSourceImports = preferSourceImports ?? typeof Bun !== 'undefined';
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
isExpectedSsrPreloadError(error) {
|
|
27
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
28
|
-
const errorCode = this.getErrorCode(error);
|
|
29
|
-
if (errorCode === "ERR_UNKNOWN_FILE_EXTENSION") {
|
|
30
|
-
return true;
|
|
24
|
+
getErrorCode(error) {
|
|
25
|
+
if (typeof error !== 'object' || error === null) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
const code = Reflect.get(error, 'code');
|
|
29
|
+
return code === undefined ? '' : String(code);
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const collect = (component) => {
|
|
41
|
-
const config = component?.config;
|
|
42
|
-
if (!config || visitedConfigs.has(config)) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
visitedConfigs.add(config);
|
|
46
|
-
const scriptEntries = config.dependencies?.scripts ?? [];
|
|
47
|
-
const componentFile = config.__eco?.file;
|
|
48
|
-
if (componentFile) {
|
|
49
|
-
const componentDir = path.dirname(componentFile);
|
|
50
|
-
for (const script of scriptEntries) {
|
|
51
|
-
if (typeof script === "string") {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
if (!script.lazy || script.ssr !== true) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
if (!script.src) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
scriptPaths.add(this.resolveDependencyPath(componentDir, script.src));
|
|
31
|
+
/**
|
|
32
|
+
* Detects preload failures that are expected for browser-only modules.
|
|
33
|
+
*/
|
|
34
|
+
isExpectedSsrPreloadError(error) {
|
|
35
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
36
|
+
const errorCode = this.getErrorCode(error);
|
|
37
|
+
if (errorCode === 'ERR_UNKNOWN_FILE_EXTENSION') {
|
|
38
|
+
return true;
|
|
61
39
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
for (const nestedComponent of config.dependencies?.components || []) {
|
|
67
|
-
collect(nestedComponent);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
for (const component of components) {
|
|
71
|
-
collect(component);
|
|
40
|
+
return (errorMessage.includes(`reading 'Element'`) ||
|
|
41
|
+
errorMessage.includes('window is not defined') ||
|
|
42
|
+
errorMessage.includes('document is not defined') ||
|
|
43
|
+
errorMessage.includes('navigator is not defined'));
|
|
72
44
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Collects lazy script file paths eligible for SSR preloading.
|
|
47
|
+
*/
|
|
48
|
+
collectSsrPreloadScripts(components) {
|
|
49
|
+
const scriptPaths = new Set();
|
|
50
|
+
const visitedConfigs = new Set();
|
|
51
|
+
const collect = (component) => {
|
|
52
|
+
const config = component?.config;
|
|
53
|
+
if (!config || visitedConfigs.has(config)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
visitedConfigs.add(config);
|
|
57
|
+
const scriptEntries = config.dependencies?.scripts ?? [];
|
|
58
|
+
const componentFile = getComponentIdentity(component)?.file;
|
|
59
|
+
if (componentFile) {
|
|
60
|
+
const componentDir = path.dirname(componentFile);
|
|
61
|
+
for (const script of scriptEntries) {
|
|
62
|
+
if (typeof script === 'string') {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (!script.lazy || script.ssr !== true) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (!script.src) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
scriptPaths.add(this.resolveDependencyPath(componentDir, script.src));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const layout of config.layouts ?? []) {
|
|
75
|
+
collect(layout);
|
|
76
|
+
}
|
|
77
|
+
for (const nestedComponent of config.dependencies?.components || []) {
|
|
78
|
+
collect(nestedComponent);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
for (const component of components) {
|
|
82
|
+
collect(component);
|
|
83
|
+
}
|
|
84
|
+
return Array.from(scriptPaths);
|
|
82
85
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Preloads SSR-eligible lazy scripts to register custom elements before render.
|
|
88
|
+
*/
|
|
89
|
+
async preloadSsrLazyScripts(components) {
|
|
90
|
+
const scripts = this.collectSsrPreloadScripts(components);
|
|
91
|
+
if (scripts.length === 0) {
|
|
92
|
+
return;
|
|
87
93
|
}
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
await Promise.all(scripts
|
|
95
|
+
.filter((scriptPath) => {
|
|
96
|
+
if (this.ssrPreloadedScripts.has(scriptPath)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
if (this.ssrPreloadFailedScripts.has(scriptPath)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
})
|
|
104
|
+
.map(async (scriptPath) => {
|
|
105
|
+
const preloadEntrypoint = await this.resolveSsrPreloadEntrypoint(scriptPath);
|
|
106
|
+
if (!preloadEntrypoint) {
|
|
107
|
+
this.ssrPreloadFailedScripts.add(scriptPath);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await import(/* @vite-ignore */ pathToFileURL(preloadEntrypoint).href);
|
|
112
|
+
this.ssrPreloadedScripts.add(scriptPath);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.ssrPreloadFailedScripts.add(scriptPath);
|
|
116
|
+
if (this.isExpectedSsrPreloadError(error)) {
|
|
117
|
+
if (process.env.ECOPAGES_DEBUG === 'true') {
|
|
118
|
+
console.warn(`[ecopages][lit] Skipping SSR preload for browser-only lazy script: ${scriptPath}`);
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.warn(`[ecopages][lit] Failed to preload lazy SSR script: ${scriptPath}`, error);
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolves the concrete JS entrypoint used for SSR preloading.
|
|
128
|
+
*/
|
|
129
|
+
async resolveSsrPreloadEntrypoint(scriptPath) {
|
|
130
|
+
const cachedEntrypoint = this.ssrPreloadEntrypointCache.get(scriptPath);
|
|
131
|
+
if (cachedEntrypoint) {
|
|
132
|
+
return cachedEntrypoint;
|
|
90
133
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
134
|
+
if (this.preferSourceImports) {
|
|
135
|
+
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
136
|
+
return scriptPath;
|
|
137
|
+
}
|
|
138
|
+
if (!this.processDependencies) {
|
|
139
|
+
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
140
|
+
return scriptPath;
|
|
97
141
|
}
|
|
98
142
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
143
|
+
const processed = await this.processDependencies([
|
|
144
|
+
AssetFactory.createInlineFileScript({
|
|
145
|
+
filepath: scriptPath,
|
|
146
|
+
position: 'head',
|
|
147
|
+
bundle: true,
|
|
148
|
+
attributes: {
|
|
149
|
+
type: 'module',
|
|
150
|
+
defer: '',
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
], `lit-ssr-preload:${scriptPath}`);
|
|
154
|
+
const entrypoint = processed[0]?.filepath;
|
|
155
|
+
if (!entrypoint) {
|
|
156
|
+
return scriptPath;
|
|
111
157
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
console.warn(`[ecopages][lit] Failed to preload lazy SSR script: ${scriptPath}`, error);
|
|
158
|
+
this.ssrPreloadEntrypointCache.set(scriptPath, entrypoint);
|
|
159
|
+
return entrypoint;
|
|
115
160
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Resolves the concrete JS entrypoint used for SSR preloading.
|
|
121
|
-
*/
|
|
122
|
-
async resolveSsrPreloadEntrypoint(scriptPath) {
|
|
123
|
-
const cachedEntrypoint = this.ssrPreloadEntrypointCache.get(scriptPath);
|
|
124
|
-
if (cachedEntrypoint) {
|
|
125
|
-
return cachedEntrypoint;
|
|
126
|
-
}
|
|
127
|
-
if (this.preferSourceImports) {
|
|
128
|
-
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
129
|
-
return scriptPath;
|
|
130
|
-
}
|
|
131
|
-
if (!this.processDependencies) {
|
|
132
|
-
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
133
|
-
return scriptPath;
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
const processed = await this.processDependencies(
|
|
137
|
-
[
|
|
138
|
-
AssetFactory.createInlineFileScript({
|
|
139
|
-
filepath: scriptPath,
|
|
140
|
-
position: "head",
|
|
141
|
-
bundle: true,
|
|
142
|
-
attributes: {
|
|
143
|
-
type: "module",
|
|
144
|
-
defer: ""
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (process.env.ECOPAGES_DEBUG === 'true') {
|
|
163
|
+
console.warn(`[ecopages][lit] Failed to resolve SSR preload entrypoint for: ${scriptPath}`, error);
|
|
145
164
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
);
|
|
150
|
-
const entrypoint = processed[0]?.filepath;
|
|
151
|
-
if (!entrypoint) {
|
|
152
|
-
return scriptPath;
|
|
153
|
-
}
|
|
154
|
-
this.ssrPreloadEntrypointCache.set(scriptPath, entrypoint);
|
|
155
|
-
return entrypoint;
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (process.env.ECOPAGES_DEBUG === "true") {
|
|
158
|
-
console.warn(`[ecopages][lit] Failed to resolve SSR preload entrypoint for: ${scriptPath}`, error);
|
|
159
|
-
}
|
|
160
|
-
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
161
|
-
return scriptPath;
|
|
165
|
+
this.ssrPreloadEntrypointCache.set(scriptPath, scriptPath);
|
|
166
|
+
return scriptPath;
|
|
167
|
+
}
|
|
162
168
|
}
|
|
163
|
-
}
|
|
164
169
|
}
|
|
165
|
-
export {
|
|
166
|
-
LitSsrLazyPreloader
|
|
167
|
-
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { PageParams, PageQuery, RouteRenderResult } from '@ecopages/core';
|
|
2
|
+
export type LitStaticRenderCacheStrategy = RouteRenderResult['cacheStrategy'];
|
|
1
3
|
export type LitStaticRenderWorkerInitMessage = {
|
|
2
4
|
type: 'init';
|
|
3
5
|
configModulePath: string;
|
|
@@ -7,7 +9,10 @@ export type LitStaticRenderWorkerRenderMessage = {
|
|
|
7
9
|
type: 'render';
|
|
8
10
|
id: string;
|
|
9
11
|
filePath: string;
|
|
10
|
-
params
|
|
12
|
+
/** Route params; multi-value keys stay as `string[]`. */
|
|
13
|
+
params: PageParams;
|
|
14
|
+
/** Serializable route query; preserves multi-value keys as `string[]`. */
|
|
15
|
+
query?: PageQuery;
|
|
11
16
|
};
|
|
12
17
|
export type LitStaticRenderWorkerShutdownMessage = {
|
|
13
18
|
type: 'shutdown';
|
|
@@ -20,6 +25,7 @@ export type LitStaticRenderWorkerResultMessage = {
|
|
|
20
25
|
type: 'result';
|
|
21
26
|
id: string;
|
|
22
27
|
html: string;
|
|
28
|
+
cacheStrategy?: LitStaticRenderCacheStrategy;
|
|
23
29
|
};
|
|
24
30
|
export type LitStaticRenderWorkerErrorMessage = {
|
|
25
31
|
type: 'error';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,23 +1,45 @@
|
|
|
1
|
-
import type { EcoComponent } from '@ecopages/core';
|
|
1
|
+
import type { EcoComponent, PageParams, PageQuery } from '@ecopages/core';
|
|
2
2
|
import type { StaticExportContext } from '@ecopages/core/plugins/integration-plugin';
|
|
3
3
|
import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
|
|
4
|
+
import { LitStaticRenderWorkerClient } from './lit-static-render-worker-client.js';
|
|
5
|
+
import type { LitStaticRenderCacheStrategy } from './lit-static-render-protocol.js';
|
|
6
|
+
type LitStaticRenderWorkerClientContract = Pick<LitStaticRenderWorkerClient, 'start' | 'renderPage' | 'dispose'>;
|
|
4
7
|
type LitStaticRenderSessionOptions = {
|
|
5
8
|
resolveDependencyPath: (componentDir: string, sourcePath: string) => string;
|
|
6
9
|
processDependencies?: (dependencies: AssetDefinition[], integrationName: string) => Promise<Array<{
|
|
7
10
|
filepath?: string;
|
|
8
11
|
}>>;
|
|
9
12
|
preferSourceImports?: boolean;
|
|
13
|
+
createWorkerClient?: (input: {
|
|
14
|
+
configModulePath: string;
|
|
15
|
+
runtimeOrigin: string;
|
|
16
|
+
}) => LitStaticRenderWorkerClientContract;
|
|
10
17
|
};
|
|
11
18
|
/**
|
|
12
|
-
*
|
|
19
|
+
* Plugin-runtime-scoped Lit server render session.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Owns worker lifecycle and SSR preload for Lit page routes during static export
|
|
23
|
+
* and runtime/dev requests. Injected into `LitRenderer` via a lazy accessor from
|
|
24
|
+
* `LitPlugin`; there is no process-global coordinator.
|
|
13
25
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
26
|
+
* Worker init identity is sticky for the first `{ configModulePath, runtimeOrigin }`.
|
|
27
|
+
* Later `ensureWorker` calls with the same identity are no-ops; a different identity
|
|
28
|
+
* recreates the worker so stale config/origin is never silently reused.
|
|
16
29
|
*/
|
|
17
30
|
export declare class LitStaticRenderSession {
|
|
18
31
|
private readonly preloader;
|
|
32
|
+
private readonly createWorkerClient;
|
|
19
33
|
private workerClient;
|
|
34
|
+
private workerIdentity;
|
|
20
35
|
constructor(options: LitStaticRenderSessionOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Ensures the static render worker is running for the given identity.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* First successful start sticks that identity. Matching re-entry is a no-op.
|
|
41
|
+
* A different `configModulePath` or `runtimeOrigin` disposes and recreates.
|
|
42
|
+
*/
|
|
21
43
|
ensureWorker(input: {
|
|
22
44
|
configModulePath: string;
|
|
23
45
|
runtimeOrigin: string;
|
|
@@ -27,8 +49,12 @@ export declare class LitStaticRenderSession {
|
|
|
27
49
|
collectSsrPreloadScripts(components: Array<EcoComponent | undefined>): string[];
|
|
28
50
|
renderPageInWorker(input: {
|
|
29
51
|
filePath: string;
|
|
30
|
-
params:
|
|
31
|
-
|
|
52
|
+
params: PageParams;
|
|
53
|
+
query?: PageQuery;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
html: string;
|
|
56
|
+
cacheStrategy?: LitStaticRenderCacheStrategy;
|
|
57
|
+
}>;
|
|
32
58
|
isExpectedSsrPreloadError(error: unknown): boolean;
|
|
33
59
|
dispose(): Promise<void>;
|
|
34
60
|
private preloadLitRoutes;
|
|
@@ -1,84 +1,119 @@
|
|
|
1
|
-
import path from
|
|
2
|
-
import { LitSsrLazyPreloader } from
|
|
3
|
-
import { LIT_PLUGIN_NAME } from
|
|
4
|
-
import { LitStaticRenderWorkerClient } from
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { LitSsrLazyPreloader } from './lit-ssr-lazy-preloader.js';
|
|
3
|
+
import { LIT_PLUGIN_NAME } from './lit.constants.js';
|
|
4
|
+
import { LitStaticRenderWorkerClient } from './lit-static-render-worker-client.js';
|
|
5
|
+
/**
|
|
6
|
+
* Plugin-runtime-scoped Lit server render session.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Owns worker lifecycle and SSR preload for Lit page routes during static export
|
|
10
|
+
* and runtime/dev requests. Injected into `LitRenderer` via a lazy accessor from
|
|
11
|
+
* `LitPlugin`; there is no process-global coordinator.
|
|
12
|
+
*
|
|
13
|
+
* Worker init identity is sticky for the first `{ configModulePath, runtimeOrigin }`.
|
|
14
|
+
* Later `ensureWorker` calls with the same identity are no-ops; a different identity
|
|
15
|
+
* recreates the worker so stale config/origin is never silently reused.
|
|
16
|
+
*/
|
|
17
|
+
export class LitStaticRenderSession {
|
|
18
|
+
preloader;
|
|
19
|
+
createWorkerClient;
|
|
20
|
+
workerClient = null;
|
|
21
|
+
workerIdentity = null;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.preloader = new LitSsrLazyPreloader({
|
|
24
|
+
resolveDependencyPath: options.resolveDependencyPath,
|
|
25
|
+
processDependencies: options.processDependencies,
|
|
26
|
+
preferSourceImports: options.preferSourceImports,
|
|
27
|
+
});
|
|
28
|
+
this.createWorkerClient =
|
|
29
|
+
options.createWorkerClient ??
|
|
30
|
+
((input) => new LitStaticRenderWorkerClient({
|
|
31
|
+
configModulePath: input.configModulePath,
|
|
32
|
+
runtimeOrigin: input.runtimeOrigin,
|
|
33
|
+
}));
|
|
18
34
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Ensures the static render worker is running for the given identity.
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* First successful start sticks that identity. Matching re-entry is a no-op.
|
|
40
|
+
* A different `configModulePath` or `runtimeOrigin` disposes and recreates.
|
|
41
|
+
*/
|
|
42
|
+
async ensureWorker(input) {
|
|
43
|
+
if (this.workerClient &&
|
|
44
|
+
this.workerIdentity &&
|
|
45
|
+
this.workerIdentity.configModulePath === input.configModulePath &&
|
|
46
|
+
this.workerIdentity.runtimeOrigin === input.runtimeOrigin) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (this.workerClient) {
|
|
50
|
+
await this.dispose();
|
|
51
|
+
}
|
|
52
|
+
this.workerIdentity = {
|
|
53
|
+
configModulePath: input.configModulePath,
|
|
54
|
+
runtimeOrigin: input.runtimeOrigin,
|
|
55
|
+
};
|
|
56
|
+
this.workerClient = this.createWorkerClient({
|
|
57
|
+
configModulePath: input.configModulePath,
|
|
58
|
+
runtimeOrigin: input.runtimeOrigin,
|
|
59
|
+
});
|
|
60
|
+
await this.workerClient.start();
|
|
61
|
+
}
|
|
62
|
+
async preloadStaticRoutes(context) {
|
|
63
|
+
await this.preloadLitRoutes(context);
|
|
37
64
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
isExpectedSsrPreloadError(error) {
|
|
41
|
-
return this.preloader.isExpectedSsrPreloadError(error);
|
|
42
|
-
}
|
|
43
|
-
async dispose() {
|
|
44
|
-
await this.workerClient?.dispose();
|
|
45
|
-
this.workerClient = null;
|
|
46
|
-
}
|
|
47
|
-
async preloadLitRoutes(context) {
|
|
48
|
-
if (!context.routeRendererFactory) {
|
|
49
|
-
return;
|
|
65
|
+
async preloadSsrLazyScripts(components) {
|
|
66
|
+
await this.preloader.preloadSsrLazyScripts(components);
|
|
50
67
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
const pageRenderer = context.routeRendererFactory.getPageRenderer(filePath);
|
|
59
|
-
const pageModule = await pageRenderer.loadPageModule(filePath);
|
|
60
|
-
const page = pageModule.default;
|
|
61
|
-
if (page) {
|
|
62
|
-
components.push(page);
|
|
63
|
-
if (page.config?.layout) {
|
|
64
|
-
components.push(page.config.layout);
|
|
68
|
+
collectSsrPreloadScripts(components) {
|
|
69
|
+
return this.preloader.collectSsrPreloadScripts(components);
|
|
70
|
+
}
|
|
71
|
+
async renderPageInWorker(input) {
|
|
72
|
+
if (!this.workerClient) {
|
|
73
|
+
throw new Error('Lit static render worker is not active');
|
|
65
74
|
}
|
|
66
|
-
|
|
67
|
-
|
|
75
|
+
return this.workerClient.renderPage(input);
|
|
76
|
+
}
|
|
77
|
+
isExpectedSsrPreloadError(error) {
|
|
78
|
+
return this.preloader.isExpectedSsrPreloadError(error);
|
|
79
|
+
}
|
|
80
|
+
async dispose() {
|
|
81
|
+
await this.workerClient?.dispose();
|
|
82
|
+
this.workerClient = null;
|
|
83
|
+
this.workerIdentity = null;
|
|
84
|
+
}
|
|
85
|
+
async preloadLitRoutes(context) {
|
|
86
|
+
if (!context.routeRendererFactory) {
|
|
87
|
+
return;
|
|
68
88
|
}
|
|
69
|
-
|
|
89
|
+
const routes = await context.router.listStaticGenerationRoutes({ runtimeOrigin: context.baseUrl });
|
|
90
|
+
const components = [];
|
|
91
|
+
for (const route of routes) {
|
|
92
|
+
const filePath = route.templateRoute.filePath;
|
|
93
|
+
if (!this.isLitRoute(filePath, context.appConfig)) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const pageRenderer = context.routeRendererFactory.getPageRenderer(filePath);
|
|
97
|
+
const pageModule = await pageRenderer.loadPageModule(filePath);
|
|
98
|
+
const page = pageModule.default;
|
|
99
|
+
if (page) {
|
|
100
|
+
components.push(page);
|
|
101
|
+
for (const layout of page.config?.layouts ?? []) {
|
|
102
|
+
components.push(layout);
|
|
103
|
+
}
|
|
104
|
+
for (const nestedComponent of page.config?.dependencies?.components ?? []) {
|
|
105
|
+
components.push(nestedComponent);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
await this.preloadSsrLazyScripts(components);
|
|
70
110
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
111
|
+
isLitRoute(filePath, appConfig) {
|
|
112
|
+
const litIntegration = appConfig.integrations.find((plugin) => plugin.name === LIT_PLUGIN_NAME);
|
|
113
|
+
if (!litIntegration) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
const normalizedPath = path.normalize(filePath);
|
|
117
|
+
return litIntegration.extensions.some((extension) => normalizedPath.endsWith(extension));
|
|
77
118
|
}
|
|
78
|
-
const normalizedPath = path.normalize(filePath);
|
|
79
|
-
return litIntegration.extensions.some((extension) => normalizedPath.endsWith(extension));
|
|
80
|
-
}
|
|
81
119
|
}
|
|
82
|
-
export {
|
|
83
|
-
LitStaticRenderSession
|
|
84
|
-
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { PageParams, PageQuery } from '@ecopages/core';
|
|
2
|
+
import type { LitStaticRenderCacheStrategy } from './lit-static-render-protocol.js';
|
|
1
3
|
export declare class LitStaticRenderWorkerClient {
|
|
2
4
|
private readonly configModulePath;
|
|
3
5
|
private readonly runtimeOrigin;
|
|
@@ -13,8 +15,12 @@ export declare class LitStaticRenderWorkerClient {
|
|
|
13
15
|
start(): Promise<void>;
|
|
14
16
|
renderPage(input: {
|
|
15
17
|
filePath: string;
|
|
16
|
-
params:
|
|
17
|
-
|
|
18
|
+
params: PageParams;
|
|
19
|
+
query?: PageQuery;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
html: string;
|
|
22
|
+
cacheStrategy?: LitStaticRenderCacheStrategy;
|
|
23
|
+
}>;
|
|
18
24
|
dispose(): Promise<void>;
|
|
19
25
|
}
|
|
20
26
|
export declare const litStaticRenderWorkerEntryPath: string;
|