@ecopages/lit 0.2.1-beta.0 → 0.3.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.
- package/README.md +26 -16
- package/package.json +15 -4
- package/src/STATIC_RENDER.md +75 -0
- package/src/console.d.ts +0 -1
- package/src/console.js +12 -6
- package/src/dom-shim.d.ts +10 -0
- package/src/dom-shim.js +59 -12
- package/src/lit-element-hydrate.d.ts +10 -0
- package/src/lit-element-hydrate.js +11 -4
- package/src/lit-renderer.d.ts +18 -51
- package/src/lit-renderer.js +111 -231
- package/src/lit-static-render-protocol.d.ts +40 -0
- package/src/lit-static-render-protocol.js +1 -0
- package/src/lit-static-render-result.d.ts +10 -0
- package/src/lit-static-render-result.js +21 -0
- package/src/lit-static-render-session.d.ts +65 -0
- package/src/lit-static-render-session.js +145 -0
- package/src/lit-static-render-worker-client.d.ts +26 -0
- package/src/lit-static-render-worker-client.js +181 -0
- package/src/lit-static-render-worker.d.ts +1 -0
- package/src/lit-static-render-worker.js +111 -0
- package/src/lit.constants.js +1 -4
- package/src/lit.plugin.d.ts +36 -3
- package/src/lit.plugin.js +138 -48
- package/src/styled-mixin.js +20 -12
- package/src/utils/lit-html-rendering.js +39 -46
- package/src/lit-ssr-lazy-preloader.d.ts +0 -44
- package/src/lit-ssr-lazy-preloader.js +0 -167
|
@@ -1,52 +1,45 @@
|
|
|
1
|
-
import { render } from
|
|
2
|
-
import { html as staticHtml, unsafeStatic } from
|
|
3
|
-
const LIT_HTML_TEMPLATE_SLOT_MARKER =
|
|
4
|
-
const LIT_COMPONENT_CHILDREN_SLOT_MARKER =
|
|
5
|
-
const ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER =
|
|
6
|
-
const DOUBLE_ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER =
|
|
1
|
+
import { render } from '@lit-labs/ssr';
|
|
2
|
+
import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
|
|
3
|
+
export const LIT_HTML_TEMPLATE_SLOT_MARKER = '<--content-->';
|
|
4
|
+
export const LIT_COMPONENT_CHILDREN_SLOT_MARKER = '<!--eco-lit-component-children-->';
|
|
5
|
+
const ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER = '<!--eco-lit-component-children-->';
|
|
6
|
+
const DOUBLE_ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER = '&lt;!--eco-lit-component-children--&gt;';
|
|
7
7
|
const DUPLICATE_DECLARATIVE_SHADOW_ROOT_ATTRIBUTE = /\sshadowroot=(['"])(open|closed)\1(?=\sshadowrootmode=\1\2\1)/g;
|
|
8
|
-
function normalizeLitHtml(markup) {
|
|
9
|
-
|
|
8
|
+
export function normalizeLitHtml(markup) {
|
|
9
|
+
return markup.replace(DUPLICATE_DECLARATIVE_SHADOW_ROOT_ATTRIBUTE, '');
|
|
10
10
|
}
|
|
11
|
-
function injectLitRenderedChildren(template, renderedChildren) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
export function injectLitRenderedChildren(template, renderedChildren) {
|
|
12
|
+
for (const marker of [
|
|
13
|
+
LIT_COMPONENT_CHILDREN_SLOT_MARKER,
|
|
14
|
+
ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER,
|
|
15
|
+
DOUBLE_ESCAPED_COMPONENT_CHILDREN_SLOT_MARKER,
|
|
16
|
+
]) {
|
|
17
|
+
if (template.includes(marker)) {
|
|
18
|
+
return template.split(marker).join(renderedChildren);
|
|
19
|
+
}
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return `${template}${renderedChildren}`;
|
|
21
|
+
if (template.includes(LIT_HTML_TEMPLATE_SLOT_MARKER)) {
|
|
22
|
+
return template.split(LIT_HTML_TEMPLATE_SLOT_MARKER).join(renderedChildren);
|
|
23
|
+
}
|
|
24
|
+
if (template.includes('</body>')) {
|
|
25
|
+
return template.replace('</body>', `${renderedChildren}</body>`);
|
|
26
|
+
}
|
|
27
|
+
if (template.includes('</html>')) {
|
|
28
|
+
return template.replace('</html>', `${renderedChildren}</html>`);
|
|
29
|
+
}
|
|
30
|
+
return `${template}${renderedChildren}`;
|
|
31
31
|
}
|
|
32
|
-
async function renderLitValueToString(value) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
export async function renderLitValueToString(value) {
|
|
33
|
+
if (typeof value === 'string') {
|
|
34
|
+
let renderedHtml = '';
|
|
35
|
+
for (const chunk of render(staticHtml `${unsafeStatic(value)}`)) {
|
|
36
|
+
renderedHtml += chunk;
|
|
37
|
+
}
|
|
38
|
+
return normalizeLitHtml(renderedHtml);
|
|
39
|
+
}
|
|
40
|
+
let renderedHtml = '';
|
|
41
|
+
for (const chunk of render(value)) {
|
|
42
|
+
renderedHtml += chunk;
|
|
37
43
|
}
|
|
38
|
-
return normalizeLitHtml(
|
|
39
|
-
}
|
|
40
|
-
let renderedHtml = "";
|
|
41
|
-
for (const chunk of render(value)) {
|
|
42
|
-
renderedHtml += chunk;
|
|
43
|
-
}
|
|
44
|
-
return normalizeLitHtml(renderedHtml);
|
|
44
|
+
return normalizeLitHtml(renderedHtml);
|
|
45
45
|
}
|
|
46
|
-
export {
|
|
47
|
-
LIT_COMPONENT_CHILDREN_SLOT_MARKER,
|
|
48
|
-
LIT_HTML_TEMPLATE_SLOT_MARKER,
|
|
49
|
-
injectLitRenderedChildren,
|
|
50
|
-
normalizeLitHtml,
|
|
51
|
-
renderLitValueToString
|
|
52
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { EcoComponent } from '@ecopages/core';
|
|
2
|
-
import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
|
|
3
|
-
type ProcessDependencies = (dependencies: AssetDefinition[], integrationName: string) => Promise<Array<{
|
|
4
|
-
filepath?: string;
|
|
5
|
-
}>>;
|
|
6
|
-
export interface LitSsrLazyPreloaderOptions {
|
|
7
|
-
resolveDependencyPath: (componentDir: string, sourcePath: string) => string;
|
|
8
|
-
processDependencies?: ProcessDependencies;
|
|
9
|
-
preferSourceImports?: boolean;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Encapsulates SSR lazy script preload behavior for Lit components.
|
|
13
|
-
*
|
|
14
|
-
* Collects `dependencies.scripts` lazy entries with `ssr: true`, resolves the
|
|
15
|
-
* processed entrypoint through the asset pipeline, and imports the module so
|
|
16
|
-
* custom elements are registered before SSR rendering.
|
|
17
|
-
*/
|
|
18
|
-
export declare class LitSsrLazyPreloader {
|
|
19
|
-
private readonly resolveDependencyPath;
|
|
20
|
-
private readonly processDependencies?;
|
|
21
|
-
private readonly preferSourceImports;
|
|
22
|
-
private readonly ssrPreloadedScripts;
|
|
23
|
-
private readonly ssrPreloadFailedScripts;
|
|
24
|
-
private readonly ssrPreloadEntrypointCache;
|
|
25
|
-
constructor({ resolveDependencyPath, processDependencies, preferSourceImports }: LitSsrLazyPreloaderOptions);
|
|
26
|
-
private getErrorCode;
|
|
27
|
-
/**
|
|
28
|
-
* Detects preload failures that are expected for browser-only modules.
|
|
29
|
-
*/
|
|
30
|
-
isExpectedSsrPreloadError(error: unknown): boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Collects lazy script file paths eligible for SSR preloading.
|
|
33
|
-
*/
|
|
34
|
-
collectSsrPreloadScripts(components: Array<EcoComponent | undefined>): string[];
|
|
35
|
-
/**
|
|
36
|
-
* Preloads SSR-eligible lazy scripts to register custom elements before render.
|
|
37
|
-
*/
|
|
38
|
-
preloadSsrLazyScripts(components: Array<EcoComponent | undefined>): Promise<void>;
|
|
39
|
-
/**
|
|
40
|
-
* Resolves the concrete JS entrypoint used for SSR preloading.
|
|
41
|
-
*/
|
|
42
|
-
resolveSsrPreloadEntrypoint(scriptPath: string): Promise<string | null>;
|
|
43
|
-
}
|
|
44
|
-
export {};
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { AssetFactory } from "@ecopages/core/services/asset-processing-service";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { pathToFileURL } from "node:url";
|
|
4
|
-
class LitSsrLazyPreloader {
|
|
5
|
-
resolveDependencyPath;
|
|
6
|
-
processDependencies;
|
|
7
|
-
preferSourceImports;
|
|
8
|
-
ssrPreloadedScripts = /* @__PURE__ */ new Set();
|
|
9
|
-
ssrPreloadFailedScripts = /* @__PURE__ */ new Set();
|
|
10
|
-
ssrPreloadEntrypointCache = /* @__PURE__ */ new Map();
|
|
11
|
-
constructor({ resolveDependencyPath, processDependencies, preferSourceImports }) {
|
|
12
|
-
this.resolveDependencyPath = resolveDependencyPath;
|
|
13
|
-
this.processDependencies = processDependencies;
|
|
14
|
-
this.preferSourceImports = preferSourceImports ?? typeof Bun !== "undefined";
|
|
15
|
-
}
|
|
16
|
-
getErrorCode(error) {
|
|
17
|
-
if (typeof error !== "object" || error === null) {
|
|
18
|
-
return "";
|
|
19
|
-
}
|
|
20
|
-
const code = Reflect.get(error, "code");
|
|
21
|
-
return code === void 0 ? "" : String(code);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Detects preload failures that are expected for browser-only modules.
|
|
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;
|
|
31
|
-
}
|
|
32
|
-
return errorMessage.includes(`reading 'Element'`) || errorMessage.includes("window is not defined") || errorMessage.includes("document is not defined") || errorMessage.includes("navigator is not defined");
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Collects lazy script file paths eligible for SSR preloading.
|
|
36
|
-
*/
|
|
37
|
-
collectSsrPreloadScripts(components) {
|
|
38
|
-
const scriptPaths = /* @__PURE__ */ new Set();
|
|
39
|
-
const visitedConfigs = /* @__PURE__ */ new Set();
|
|
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));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (config.layout) {
|
|
64
|
-
collect(config.layout);
|
|
65
|
-
}
|
|
66
|
-
for (const nestedComponent of config.dependencies?.components || []) {
|
|
67
|
-
collect(nestedComponent);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
for (const component of components) {
|
|
71
|
-
collect(component);
|
|
72
|
-
}
|
|
73
|
-
return Array.from(scriptPaths);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Preloads SSR-eligible lazy scripts to register custom elements before render.
|
|
77
|
-
*/
|
|
78
|
-
async preloadSsrLazyScripts(components) {
|
|
79
|
-
const scripts = this.collectSsrPreloadScripts(components);
|
|
80
|
-
if (scripts.length === 0) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
await Promise.all(
|
|
84
|
-
scripts.filter((scriptPath) => {
|
|
85
|
-
if (this.ssrPreloadedScripts.has(scriptPath)) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
if (this.ssrPreloadFailedScripts.has(scriptPath)) {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
}).map(async (scriptPath) => {
|
|
93
|
-
const preloadEntrypoint = await this.resolveSsrPreloadEntrypoint(scriptPath);
|
|
94
|
-
if (!preloadEntrypoint) {
|
|
95
|
-
this.ssrPreloadFailedScripts.add(scriptPath);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
await import(
|
|
100
|
-
/* @vite-ignore */
|
|
101
|
-
pathToFileURL(preloadEntrypoint).href
|
|
102
|
-
);
|
|
103
|
-
this.ssrPreloadedScripts.add(scriptPath);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
this.ssrPreloadFailedScripts.add(scriptPath);
|
|
106
|
-
if (this.isExpectedSsrPreloadError(error)) {
|
|
107
|
-
if (process.env.ECOPAGES_DEBUG === "true") {
|
|
108
|
-
console.warn(
|
|
109
|
-
`[ecopages][lit] Skipping SSR preload for browser-only lazy script: ${scriptPath}`
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
console.warn(`[ecopages][lit] Failed to preload lazy SSR script: ${scriptPath}`, error);
|
|
115
|
-
}
|
|
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: ""
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
],
|
|
148
|
-
`lit-ssr-preload:${scriptPath}`
|
|
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;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
export {
|
|
166
|
-
LitSsrLazyPreloader
|
|
167
|
-
};
|