@lwrjs/lwc-ssr 0.11.0-alpha.8 → 0.11.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 +38 -1
- package/build/cjs/moduleProvider/index.cjs +41 -12
- package/build/cjs/utils/amd-utils.cjs +23 -12
- package/build/cjs/utils/sandbox-locker.cjs +3 -3
- package/build/cjs/utils/sandbox-worker.cjs +4 -3
- package/build/cjs/utils/sandbox.cjs +3 -3
- package/build/cjs/utils/ssr-element.cjs +14 -6
- package/build/cjs/utils/utils.cjs +34 -0
- package/build/cjs/viewProvider/index.cjs +39 -7
- package/build/cjs/viewTransformer/index.cjs +65 -38
- package/build/es/moduleProvider/index.js +42 -13
- package/build/es/utils/amd-utils.d.ts +2 -2
- package/build/es/utils/amd-utils.js +29 -13
- package/build/es/utils/sandbox-locker.d.ts +1 -1
- package/build/es/utils/sandbox-locker.js +5 -5
- package/build/es/utils/sandbox-worker.d.ts +1 -1
- package/build/es/utils/sandbox-worker.js +4 -3
- package/build/es/utils/sandbox.d.ts +1 -1
- package/build/es/utils/sandbox.js +3 -3
- package/build/es/utils/ssr-element.d.ts +2 -4
- package/build/es/utils/ssr-element.js +17 -6
- package/build/es/utils/utils.d.ts +3 -0
- package/build/es/utils/utils.js +20 -0
- package/build/es/viewProvider/index.d.ts +2 -2
- package/build/es/viewProvider/index.js +46 -9
- package/build/es/viewTransformer/index.d.ts +1 -1
- package/build/es/viewTransformer/index.js +71 -48
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
- [Debug logging](#debug-logging)
|
|
23
23
|
- [Breakpoints](#breakpoints)
|
|
24
24
|
- [Inspect bundles](#inspect-bundles)
|
|
25
|
+
- [Diagrams](#diagrams)
|
|
26
|
+
- [Sequence](#sequence)
|
|
25
27
|
|
|
26
28
|
## Overview
|
|
27
29
|
|
|
@@ -136,12 +138,16 @@ type GetServerDataHook = (context: SsrRequestContext) => Promise<SsrDataResponse
|
|
|
136
138
|
interface SsrRequestContext {
|
|
137
139
|
// props from template attributes
|
|
138
140
|
props: Json;
|
|
141
|
+
// URL for the request
|
|
142
|
+
url: string;
|
|
139
143
|
// values from a parameterized route defined in lwr.config.json
|
|
140
144
|
params: { [key: string]: string };
|
|
141
145
|
// search parameters from the request URL
|
|
142
|
-
query: { [key: string]: string };
|
|
146
|
+
query: { [key: string]: undefined | string | string[] };
|
|
143
147
|
// locale string for the request, eg: 'en-US'
|
|
144
148
|
locale: string;
|
|
149
|
+
// base path for the request, eg: '/shop'
|
|
150
|
+
basePath: string;
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
interface SsrDataResponse {
|
|
@@ -403,3 +409,34 @@ When SSR fails due to a [portability](#portability), it can be difficult to figu
|
|
|
403
409
|
4. When the problematic code is found, scroll up to find the component to which it belongs.
|
|
404
410
|
|
|
405
411
|
For example, if SSR fails with this error:`ReferenceError: window is not defined`, then turn off SSR and search the module bundles for prohibited usages of the `window` object.
|
|
412
|
+
|
|
413
|
+
## Diagrams
|
|
414
|
+
|
|
415
|
+
### Sequence
|
|
416
|
+
|
|
417
|
+
```mermaid
|
|
418
|
+
sequenceDiagram
|
|
419
|
+
%% SSR with Data
|
|
420
|
+
actor client as Client
|
|
421
|
+
box LWR-Node
|
|
422
|
+
participant registry as View Registry
|
|
423
|
+
participant transformer as SSR View<br>Transformer
|
|
424
|
+
participant sandbox as SSR Sandbox
|
|
425
|
+
end
|
|
426
|
+
client ->> registry: Requests a page
|
|
427
|
+
registry ->> registry: Generates an HTML base document from layout and content templates
|
|
428
|
+
registry ->> transformer: Sends the base document to get islands processed
|
|
429
|
+
loop For each non-client-only island
|
|
430
|
+
transformer ->> sandbox: Sends the island to be SSRed
|
|
431
|
+
sandbox ->> sandbox: Runs the component's getServerData hook
|
|
432
|
+
sandbox ->> sandbox: Runs the route's SSR bootstrap services
|
|
433
|
+
sandbox ->> sandbox: Converts the island to HTML via LWC SSR
|
|
434
|
+
sandbox ->> transformer: Returns the HTML for the island
|
|
435
|
+
transformer ->> transformer: Replaces the island's HTML element with its SSRed HTML
|
|
436
|
+
end
|
|
437
|
+
transformer -->> registry: Return
|
|
438
|
+
registry ->> registry: Serializes the serverData into the base document
|
|
439
|
+
registry -->> client: Responds with the base document
|
|
440
|
+
client ->> client: Runs the route's SSR bootstrap services
|
|
441
|
+
client ->> client: Hydrates SSRed islands with serialized serverData
|
|
442
|
+
```
|
|
@@ -28,38 +28,68 @@ __export(exports, {
|
|
|
28
28
|
default: () => moduleProvider_default
|
|
29
29
|
});
|
|
30
30
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
31
|
+
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
31
32
|
var import_identity = __toModule(require("../identity.cjs"));
|
|
32
33
|
function createSsrBootstrapModule(rootSpecifier, services) {
|
|
33
34
|
let serviceImports = "";
|
|
34
35
|
let serviceCalls = "";
|
|
35
36
|
services.forEach((service) => {
|
|
36
|
-
const importName = `service_${service
|
|
37
|
+
const importName = (0, import_shared_utils.stringToVariableName)(`service_${service}`);
|
|
37
38
|
serviceImports += `
|
|
38
39
|
import ${importName} from '${service}';`;
|
|
39
40
|
serviceCalls += `
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
globalThis.trace({
|
|
43
|
+
name: '${import_instrumentation.ViewSpan.BootstrapService}',
|
|
44
|
+
attributes: {
|
|
45
|
+
specifier: '${rootSpecifier}',
|
|
46
|
+
serviceSpecifier: '${service}',
|
|
47
|
+
}
|
|
48
|
+
}, () => {
|
|
49
|
+
try {
|
|
50
|
+
${importName}({ serverData });
|
|
51
|
+
} catch(e) {
|
|
52
|
+
const message = e.message || e;
|
|
53
|
+
// we need to re-throw with the service specifier in the error message
|
|
54
|
+
throw new Error('An SSR error occurred in bootstrap service "${service}": ' + message);
|
|
55
|
+
}
|
|
56
|
+
});`;
|
|
41
57
|
});
|
|
42
58
|
return `
|
|
43
59
|
import { renderComponent } from '@lwc/engine-server';
|
|
44
60
|
import Ctor, * as rootComponent from '${rootSpecifier}';${serviceImports}
|
|
45
61
|
|
|
46
62
|
(async () => {
|
|
47
|
-
let result, props, markup, existingTaskCount;
|
|
63
|
+
let result, props, markup, serverData = globalThis.LWR?.serverData || {}, existingTaskCount;
|
|
64
|
+
// remove the LWR global properties before any customer code is run
|
|
65
|
+
if (globalThis.LWR?.define) {
|
|
66
|
+
// AMD: support dynamic imports in getServerData
|
|
67
|
+
globalThis.LWR = Object.freeze({ define: globalThis.LWR.define });
|
|
68
|
+
} else {
|
|
69
|
+
delete globalThis.LWR; // ESM
|
|
70
|
+
}
|
|
71
|
+
|
|
48
72
|
try {
|
|
49
73
|
// 1. setup page data
|
|
50
74
|
const context = globalThis.getContext();
|
|
51
75
|
props = context.props;
|
|
52
76
|
if (rootComponent.getServerData) {
|
|
53
77
|
const data = await globalThis.trace({
|
|
54
|
-
name: '
|
|
78
|
+
name: '${import_instrumentation.ViewSpan.GetServerData}',
|
|
55
79
|
attributes: {
|
|
56
80
|
specifier: '${rootSpecifier}'
|
|
57
81
|
}
|
|
58
|
-
}, () =>
|
|
59
|
-
|
|
82
|
+
}, async() => {
|
|
83
|
+
try {
|
|
84
|
+
return await rootComponent.getServerData(context)
|
|
85
|
+
} catch(e) {
|
|
86
|
+
const message = e.message || e;
|
|
87
|
+
// we need to re-throw with rootSpecifier in the error message
|
|
88
|
+
throw new Error('Error in "getServerData" for "${rootSpecifier}": ' + message);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
60
91
|
props = data.props; // overwrite public props
|
|
61
|
-
|
|
62
|
-
Object.assign(globalThis.LWR.serverData, data.props); // add props to server data
|
|
92
|
+
Object.assign(serverData, data.props); // add props to server data
|
|
63
93
|
markup = data.markup;
|
|
64
94
|
}${serviceCalls}
|
|
65
95
|
|
|
@@ -69,7 +99,7 @@ import Ctor, * as rootComponent from '${rootSpecifier}';${serviceImports}
|
|
|
69
99
|
|
|
70
100
|
// 2. render component
|
|
71
101
|
result = globalThis.trace({
|
|
72
|
-
name: '
|
|
102
|
+
name: '${import_instrumentation.ViewSpan.RenderComponent}',
|
|
73
103
|
attributes: {
|
|
74
104
|
specifier: '${rootSpecifier}'
|
|
75
105
|
}
|
|
@@ -77,8 +107,8 @@ import Ctor, * as rootComponent from '${rootSpecifier}';${serviceImports}
|
|
|
77
107
|
|
|
78
108
|
} catch(e) {
|
|
79
109
|
const message = e.message || e;
|
|
80
|
-
|
|
81
|
-
|
|
110
|
+
|
|
111
|
+
// add the LWC rendering stack
|
|
82
112
|
const error = e.wcStack ?
|
|
83
113
|
'An error occurred during server-side rendering for component stack: ' + e.wcStack + '. Error was: ' + message :
|
|
84
114
|
'An error occured during server-side rendering: ' + message;
|
|
@@ -90,7 +120,6 @@ import Ctor, * as rootComponent from '${rootSpecifier}';${serviceImports}
|
|
|
90
120
|
const currentTaskCount = process.getActiveResourcesInfo
|
|
91
121
|
? process.getActiveResourcesInfo().length
|
|
92
122
|
: 0;
|
|
93
|
-
|
|
94
123
|
if (currentTaskCount - existingTaskCount > 0) {
|
|
95
124
|
console.warn('[warn] async tasks encountered while server rendering "${rootSpecifier}"');
|
|
96
125
|
}
|
|
@@ -92,7 +92,7 @@ async function getCode(runtimeEnvironment, serverData, lwrVersion, bundleSpecifi
|
|
|
92
92
|
}
|
|
93
93
|
async function getBundle(specifier, moduleBundler, routes, runtimeEnvironment, runtimeParams) {
|
|
94
94
|
if ((0, import_shared_utils.getFeatureFlags)().SSR_STATIC_BUNDLES) {
|
|
95
|
-
return buildBundle(specifier, moduleBundler, routes, runtimeEnvironment, runtimeParams);
|
|
95
|
+
return buildBundle(specifier, moduleBundler, routes, {...runtimeEnvironment, debug: false}, runtimeParams);
|
|
96
96
|
}
|
|
97
97
|
return bundle(specifier, moduleBundler, runtimeEnvironment, runtimeParams, {
|
|
98
98
|
appendExcludes: false,
|
|
@@ -102,27 +102,38 @@ async function getBundle(specifier, moduleBundler, routes, runtimeEnvironment, r
|
|
|
102
102
|
async function bundle(specifier, moduleBundler, runtimeEnvironment, runtimeParams, bundleConfigOverrides) {
|
|
103
103
|
return await moduleBundler.getModuleBundle({specifier}, runtimeEnvironment, runtimeParams, bundleConfigOverrides);
|
|
104
104
|
}
|
|
105
|
-
async function bundleImports(bundleCode, imports = [], visited, moduleBundler, runtimeEnvironment, runtimeParams) {
|
|
105
|
+
async function bundleImports(bundleCode, dynamicImports = [], imports = [], visited, moduleBundler, runtimeEnvironment, runtimeParams) {
|
|
106
106
|
for (const {specifier} of imports) {
|
|
107
107
|
if (!visited.has(specifier)) {
|
|
108
108
|
visited.add(specifier);
|
|
109
109
|
const {code, bundleRecord, version} = await bundle(specifier, moduleBundler, runtimeEnvironment, runtimeParams);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
bundleCode
|
|
110
|
+
const bundledCode = getBundledCode(runtimeEnvironment, specifier, version, code);
|
|
111
|
+
bundleCode = await bundleImports(bundledCode, bundleRecord.dynamicImports, bundleRecord.imports, visited, moduleBundler, runtimeEnvironment, runtimeParams) + bundleCode;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const {specifier} of dynamicImports) {
|
|
115
|
+
if (!visited.has(specifier)) {
|
|
116
|
+
visited.add(specifier);
|
|
117
|
+
const {code, version} = await bundle(specifier, moduleBundler, runtimeEnvironment, runtimeParams);
|
|
118
|
+
bundleCode += getBundledCode(runtimeEnvironment, specifier, version, code);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
return bundleCode;
|
|
122
122
|
}
|
|
123
|
+
function getBundledCode(runtimeEnvironment, specifier, version, code) {
|
|
124
|
+
let bundledCode;
|
|
125
|
+
if (runtimeEnvironment.featureFlags?.EXPERIMENTAL_UNVERSIONED_ALIASES) {
|
|
126
|
+
const versionedSpecifier = (0, import_shared_utils.getSpecifier)({specifier, version});
|
|
127
|
+
const aliasCode = (0, import_shared_utils.createAmdAlias)(versionedSpecifier, specifier);
|
|
128
|
+
bundledCode = [code, aliasCode].filter(Boolean).join("");
|
|
129
|
+
} else {
|
|
130
|
+
bundledCode = code;
|
|
131
|
+
}
|
|
132
|
+
return bundledCode;
|
|
133
|
+
}
|
|
123
134
|
async function getBundleWithImports(specifier, moduleBundler, runtimeEnvironment, runtimeParams) {
|
|
124
135
|
const {code, bundleRecord} = await bundle(specifier, moduleBundler, runtimeEnvironment, runtimeParams);
|
|
125
|
-
return await bundleImports(code, bundleRecord.imports, new Set(["lwc", specifier]), moduleBundler, runtimeEnvironment, runtimeParams);
|
|
136
|
+
return await bundleImports(code, bundleRecord.dynamicImports, bundleRecord.imports, new Set(["lwc", specifier]), moduleBundler, runtimeEnvironment, runtimeParams);
|
|
126
137
|
}
|
|
127
138
|
async function buildBundle(ssrSpecifier, moduleBundler, routes, runtimeEnvironment, runtimeParams) {
|
|
128
139
|
const {rootSpecifier, route} = (0, import_identity.parseSpecifier)(ssrSpecifier, routes);
|
|
@@ -28,11 +28,10 @@ __export(exports, {
|
|
|
28
28
|
});
|
|
29
29
|
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
30
30
|
var import_near_membrane_node = __toModule(require("@locker/near-membrane-node"));
|
|
31
|
-
var import_node_fetch = __toModule(require("node-fetch"));
|
|
32
31
|
var import_crypto = __toModule(require("crypto"));
|
|
33
32
|
var import_url = __toModule(require("url"));
|
|
34
33
|
var import_utils = __toModule(require("./utils.cjs"));
|
|
35
|
-
function runCode(codes, context) {
|
|
34
|
+
function runCode(codes, context, host) {
|
|
36
35
|
return new Promise((resolve, reject) => {
|
|
37
36
|
let resolver;
|
|
38
37
|
const p = new Promise((r) => resolver = r);
|
|
@@ -46,9 +45,10 @@ function runCode(codes, context) {
|
|
|
46
45
|
crypto: import_crypto.webcrypto,
|
|
47
46
|
getContext,
|
|
48
47
|
trace,
|
|
49
|
-
fetch:
|
|
48
|
+
fetch: (0, import_utils.createFetchEndowment)(host),
|
|
50
49
|
resolver,
|
|
51
50
|
URL: import_url.URL,
|
|
51
|
+
URLSearchParams: import_url.URLSearchParams,
|
|
52
52
|
process,
|
|
53
53
|
setTimeout,
|
|
54
54
|
clearTimeout,
|
|
@@ -31,17 +31,18 @@ var import_utils = __toModule(require("./utils.cjs"));
|
|
|
31
31
|
var HEADER = "/* This module is generated and meant to be used in a Server context */";
|
|
32
32
|
var WORKER_CODE_SANDBOX_APIS = [
|
|
33
33
|
`const { parentPort, workerData } = require('worker_threads');`,
|
|
34
|
+
`globalThis.fetch = require('@lwrjs/lwc-ssr/viewTransformer').createFetchEndowment(workerData.host);`,
|
|
35
|
+
`delete workerData.host`,
|
|
34
36
|
`globalThis.getContext = () => workerData;`,
|
|
35
|
-
`globalThis.fetch = require('node-fetch');`,
|
|
36
37
|
`globalThis.crypto = require('crypto').webcrypto;`,
|
|
37
38
|
`globalThis.resolver = (...args) => parentPort.postMessage(...args);`,
|
|
38
39
|
`globalThis.trace = (id, fn) => fn()`
|
|
39
40
|
];
|
|
40
|
-
function runCode(codes, workerData) {
|
|
41
|
+
function runCode(codes, workerData, host) {
|
|
41
42
|
const time = (0, import_utils.getWatchdogTime)();
|
|
42
43
|
const workerCode = [HEADER, ...WORKER_CODE_SANDBOX_APIS, ...codes].join("\n");
|
|
43
44
|
return new Promise((resolve, reject) => {
|
|
44
|
-
const worker = new import_worker_threads.Worker(workerCode, {eval: true, workerData});
|
|
45
|
+
const worker = new import_worker_threads.Worker(workerCode, {eval: true, workerData: {...workerData, host}});
|
|
45
46
|
const timerId = (0, import_utils.startWatchdogTimer)(() => {
|
|
46
47
|
worker.terminate();
|
|
47
48
|
reject(new Error(`SSR timed out after ${time}ms`));
|
|
@@ -29,9 +29,9 @@ __export(exports, {
|
|
|
29
29
|
var import_sandbox_worker = __toModule(require("./sandbox-worker.cjs"));
|
|
30
30
|
var import_sandbox_locker = __toModule(require("./sandbox-locker.cjs"));
|
|
31
31
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
32
|
-
function runCode(codes, context) {
|
|
32
|
+
function runCode(codes, context, host) {
|
|
33
33
|
if ((0, import_shared_utils.getFeatureFlags)().SSR_SANDBOX_WORKER) {
|
|
34
|
-
return (0, import_sandbox_worker.default)(codes, context);
|
|
34
|
+
return (0, import_sandbox_worker.default)(codes, context, host);
|
|
35
35
|
}
|
|
36
|
-
return (0, import_sandbox_locker.default)(codes, context);
|
|
36
|
+
return (0, import_sandbox_locker.default)(codes, context, host);
|
|
37
37
|
}
|
|
@@ -29,9 +29,9 @@ __export(exports, {
|
|
|
29
29
|
var import_amd_utils = __toModule(require("./amd-utils.cjs"));
|
|
30
30
|
var import_sandbox = __toModule(require("./sandbox.cjs"));
|
|
31
31
|
var import_perf_hooks = __toModule(require("perf_hooks"));
|
|
32
|
-
var
|
|
32
|
+
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
33
33
|
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
34
|
-
var
|
|
34
|
+
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
35
35
|
var EMIT_WIRES = `globalThis.lwcRuntimeFlags = { ENABLE_WIRE_SYNC_EMIT: true };`;
|
|
36
36
|
async function ssrElement({
|
|
37
37
|
specifier,
|
|
@@ -52,10 +52,18 @@ async function ssrElement({
|
|
|
52
52
|
}) : await (0, import_amd_utils.getBundle)(specifier, moduleBundler, routes, runtimeEnvironment, runtimeParams);
|
|
53
53
|
const context = {
|
|
54
54
|
props: templateProps,
|
|
55
|
+
url: runtimeParams.url,
|
|
55
56
|
params: runtimeParams.params || {},
|
|
56
57
|
query: runtimeParams.query || {},
|
|
57
|
-
locale: runtimeParams.locale || runtimeEnvironment.defaultLocale
|
|
58
|
+
locale: runtimeParams.locale || runtimeEnvironment.i18n.defaultLocale,
|
|
59
|
+
basePath: runtimeParams.basePath || runtimeEnvironment.basePath
|
|
60
|
+
};
|
|
61
|
+
const environment = {
|
|
62
|
+
SSR: true,
|
|
63
|
+
...(0, import_shared_utils.buildEnvironmentContext)(runtimeParams)
|
|
58
64
|
};
|
|
65
|
+
const environmentCode = `process.env = ${JSON.stringify(environment)}`;
|
|
66
|
+
const host = runtimeParams.host;
|
|
59
67
|
const startTime = import_perf_hooks.performance.now();
|
|
60
68
|
return (0, import_instrumentation.getTracer)().trace({
|
|
61
69
|
name: import_instrumentation.ViewSpan.ServerSideRender,
|
|
@@ -64,14 +72,14 @@ async function ssrElement({
|
|
|
64
72
|
}
|
|
65
73
|
}, async () => {
|
|
66
74
|
const {result, props, markup, cache, error} = format === "amd" ? await (0, import_sandbox.default)([
|
|
67
|
-
SSR_FLAG,
|
|
68
75
|
EMIT_WIRES,
|
|
76
|
+
environmentCode,
|
|
69
77
|
...await (0, import_amd_utils.getCode)(runtimeEnvironment, serverData, version.replace(/\./g, "_"), bundleSpecifier, bundleRecord.includedModules, resourceRegistry),
|
|
70
78
|
code
|
|
71
|
-
], context) : await (0, import_sandbox.default)([
|
|
79
|
+
], context, host) : await (0, import_sandbox.default)([EMIT_WIRES, environmentCode, code], context, host);
|
|
72
80
|
const endTime = import_perf_hooks.performance.now();
|
|
73
81
|
const timeDiff = endTime - startTime;
|
|
74
|
-
|
|
82
|
+
import_diagnostics.logger.info(`[Server-side Rendering] ${specifier} in ${Math.round(timeDiff)} ms`);
|
|
75
83
|
if (error)
|
|
76
84
|
throw new Error(error);
|
|
77
85
|
return {html: result, props, markup, cache};
|
|
@@ -1,17 +1,36 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
2
7
|
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
|
|
3
8
|
var __export = (target, all) => {
|
|
4
9
|
for (var name in all)
|
|
5
10
|
__defProp(target, name, {get: all[name], enumerable: true});
|
|
6
11
|
};
|
|
12
|
+
var __exportStar = (target, module2, desc) => {
|
|
13
|
+
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(module2))
|
|
15
|
+
if (!__hasOwnProp.call(target, key) && key !== "default")
|
|
16
|
+
__defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
|
|
17
|
+
}
|
|
18
|
+
return target;
|
|
19
|
+
};
|
|
20
|
+
var __toModule = (module2) => {
|
|
21
|
+
return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2);
|
|
22
|
+
};
|
|
7
23
|
|
|
8
24
|
// packages/@lwrjs/lwc-ssr/src/utils/utils.ts
|
|
9
25
|
__markAsModule(exports);
|
|
10
26
|
__export(exports, {
|
|
27
|
+
createFetchEndowment: () => createFetchEndowment,
|
|
28
|
+
createSsrErrorMessage: () => createSsrErrorMessage,
|
|
11
29
|
getWatchdogTime: () => getWatchdogTime,
|
|
12
30
|
startWatchdogTimer: () => startWatchdogTimer,
|
|
13
31
|
stopWatchdogTimer: () => stopWatchdogTimer
|
|
14
32
|
});
|
|
33
|
+
var import_node_fetch = __toModule(require("node-fetch"));
|
|
15
34
|
var DEFAULT_SSR_TIMEOUT = 5e3;
|
|
16
35
|
function getWatchdogTime() {
|
|
17
36
|
const override = process.env.SSR_TIMEOUT;
|
|
@@ -23,3 +42,18 @@ function startWatchdogTimer(callback, time) {
|
|
|
23
42
|
function stopWatchdogTimer(timerId) {
|
|
24
43
|
clearTimeout(timerId);
|
|
25
44
|
}
|
|
45
|
+
function createFetchEndowment(host) {
|
|
46
|
+
if (!host) {
|
|
47
|
+
return import_node_fetch.default;
|
|
48
|
+
}
|
|
49
|
+
return (url, init) => {
|
|
50
|
+
const urlStr = typeof url === "string" ? url : url.toString();
|
|
51
|
+
if (urlStr.startsWith("/")) {
|
|
52
|
+
return (0, import_node_fetch.default)(host + url, init);
|
|
53
|
+
}
|
|
54
|
+
return (0, import_node_fetch.default)(url, init);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function createSsrErrorMessage(specifier, e) {
|
|
58
|
+
return `Server-side rendering for "${specifier}" failed. Falling back to client-side rendering. Reason: ${e.message || e}`;
|
|
59
|
+
}
|
|
@@ -27,9 +27,12 @@ __export(exports, {
|
|
|
27
27
|
default: () => viewProvider_default
|
|
28
28
|
});
|
|
29
29
|
var import_base_view_provider = __toModule(require("@lwrjs/base-view-provider"));
|
|
30
|
+
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
31
|
+
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
30
32
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
31
33
|
var import_identity = __toModule(require("../identity.cjs"));
|
|
32
34
|
var import_ssr_element = __toModule(require("../utils/ssr-element.cjs"));
|
|
35
|
+
var import_utils = __toModule(require("../utils/utils.cjs"));
|
|
33
36
|
var LwcViewProvider = class extends import_base_view_provider.default {
|
|
34
37
|
constructor(pluginConfig, providerConfig) {
|
|
35
38
|
super();
|
|
@@ -42,13 +45,11 @@ var LwcViewProvider = class extends import_base_view_provider.default {
|
|
|
42
45
|
async initialize() {
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
|
-
async getView(viewId
|
|
48
|
+
async getView(viewId) {
|
|
46
49
|
const specifier = viewId.contentTemplate?.component;
|
|
47
50
|
if (!specifier || !(0, import_shared_utils.isSpecifier)(specifier)) {
|
|
48
51
|
return;
|
|
49
52
|
}
|
|
50
|
-
const {moduleBundler, resourceRegistry, runtimeEnvironment} = this;
|
|
51
|
-
const {html: renderedView, props} = await (0, import_ssr_element.ssrElement)({specifier: `${import_identity.LWC_SSR_PREFIX}${viewId.id}/${specifier}`, props: {}}, moduleBundler, resourceRegistry, this.routes, {runtimeEnvironment, runtimeParams});
|
|
52
53
|
return {
|
|
53
54
|
name: specifier,
|
|
54
55
|
slug: (0, import_shared_utils.slugify)(specifier),
|
|
@@ -56,10 +57,41 @@ var LwcViewProvider = class extends import_base_view_provider.default {
|
|
|
56
57
|
originalSource: specifier,
|
|
57
58
|
filePath: specifier,
|
|
58
59
|
viewId,
|
|
59
|
-
render: async () =>
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
render: async (runtimeParams) => {
|
|
61
|
+
const {moduleBundler, resourceRegistry, runtimeEnvironment} = this;
|
|
62
|
+
const debug = runtimeParams.query?.debug !== void 0;
|
|
63
|
+
const element = (0, import_shared_utils.moduleSpecifierToKebabCase)(specifier);
|
|
64
|
+
return (0, import_instrumentation.getTracer)().trace({
|
|
65
|
+
name: import_instrumentation.ViewSpan.RenderPage,
|
|
66
|
+
attributes: {specifier}
|
|
67
|
+
}, async () => {
|
|
68
|
+
try {
|
|
69
|
+
const {html, props} = await (0, import_ssr_element.ssrElement)({specifier: `${import_identity.LWC_SSR_PREFIX}${viewId.id}/${specifier}`, props: {}}, moduleBundler, resourceRegistry, this.routes, {
|
|
70
|
+
runtimeEnvironment: {...runtimeEnvironment, debug},
|
|
71
|
+
runtimeParams
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
renderedView: html.replace(`<${element}`, `<${element} lwc:external`),
|
|
75
|
+
metadata: {serverData: props, customElements: [], assetReferences: []}
|
|
76
|
+
};
|
|
77
|
+
} catch (e) {
|
|
78
|
+
if (debug || (0, import_shared_utils.getFeatureFlags)().SSR_WITH_CSR_FALLBACK) {
|
|
79
|
+
const message = (0, import_utils.createSsrErrorMessage)(specifier, e);
|
|
80
|
+
import_diagnostics.logger.warn(message, e.stack);
|
|
81
|
+
return {
|
|
82
|
+
renderedView: `<${element} ${import_shared_utils.HYDRATE_DIRECTIVE}="${import_shared_utils.HYDRATE_CLIENT_VALUE}"></${element}>`,
|
|
83
|
+
metadata: {
|
|
84
|
+
serverDebug: {message: debug ? message : void 0},
|
|
85
|
+
customElements: [],
|
|
86
|
+
assetReferences: []
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
} else {
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
63
95
|
};
|
|
64
96
|
}
|
|
65
97
|
};
|
|
@@ -24,25 +24,34 @@ var __toModule = (module2) => {
|
|
|
24
24
|
// packages/@lwrjs/lwc-ssr/src/viewTransformer/index.ts
|
|
25
25
|
__markAsModule(exports);
|
|
26
26
|
__export(exports, {
|
|
27
|
+
createFetchEndowment: () => import_utils2.createFetchEndowment,
|
|
27
28
|
default: () => lwcSsrViewTransformer
|
|
28
29
|
});
|
|
30
|
+
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
31
|
+
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
29
32
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
30
33
|
var import_identity = __toModule(require("../identity.cjs"));
|
|
31
34
|
var import_ssr_element = __toModule(require("../utils/ssr-element.cjs"));
|
|
35
|
+
var import_utils = __toModule(require("../utils/utils.cjs"));
|
|
36
|
+
var import_utils2 = __toModule(require("../utils/utils.cjs"));
|
|
32
37
|
function lwcSsrViewTransformer(options, {config, moduleBundler, resourceRegistry}) {
|
|
33
38
|
const routes = [...config.routes, ...config.errorRoutes];
|
|
34
39
|
return {
|
|
35
40
|
name: "ssr-lwc-transformer",
|
|
36
41
|
async link(stringBuilder, viewContext, metadata) {
|
|
42
|
+
const {debug} = viewContext.runtimeEnvironment;
|
|
37
43
|
if (!viewContext.view.bootstrap?.ssr) {
|
|
38
44
|
return {};
|
|
39
45
|
}
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
import_diagnostics.logger.debug("[lwcSsrViewTransformer] link");
|
|
47
|
+
import_diagnostics.logger.verbose("[lwcSsrViewTransformer] link input", stringBuilder);
|
|
42
48
|
if (!metadata.serverData) {
|
|
43
49
|
metadata.serverData = {};
|
|
44
50
|
}
|
|
45
|
-
|
|
51
|
+
if (!metadata.serverDebug) {
|
|
52
|
+
metadata.serverDebug = {};
|
|
53
|
+
}
|
|
54
|
+
const {customElements, serverData, serverDebug} = metadata;
|
|
46
55
|
const ssrModules = [];
|
|
47
56
|
for (const [index, {tagName, location, props}] of customElements.entries()) {
|
|
48
57
|
const isCsr = (0, import_shared_utils.isCsrIsland)(props);
|
|
@@ -50,7 +59,7 @@ function lwcSsrViewTransformer(options, {config, moduleBundler, resourceRegistry
|
|
|
50
59
|
const {startOffset, endOffset} = location;
|
|
51
60
|
stringBuilder.overwrite(startOffset, endOffset, `<${tagName}></${tagName}>`);
|
|
52
61
|
}
|
|
53
|
-
if (!isCsr && location) {
|
|
62
|
+
if (!isCsr && !props?.["lwc:external"] && location) {
|
|
54
63
|
const {startOffset, endOffset} = location;
|
|
55
64
|
const moduleSpecifier = (0, import_shared_utils.kebabCaseToModuleSpecifier)(tagName);
|
|
56
65
|
ssrModules.push({
|
|
@@ -59,46 +68,64 @@ function lwcSsrViewTransformer(options, {config, moduleBundler, resourceRegistry
|
|
|
59
68
|
endOffset,
|
|
60
69
|
props,
|
|
61
70
|
tagName,
|
|
62
|
-
|
|
71
|
+
bootstrapSpecifier: `${import_identity.LWC_SSR_PREFIX}${viewContext.view.id}/${moduleSpecifier}`,
|
|
72
|
+
specifier: moduleSpecifier
|
|
63
73
|
});
|
|
64
74
|
}
|
|
65
75
|
}
|
|
66
|
-
let ssrLinks = "";
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
let ssrLinks = "", pageTtl, debugMessage;
|
|
77
|
+
await Promise.all(ssrModules.map(({
|
|
78
|
+
index,
|
|
79
|
+
bootstrapSpecifier,
|
|
80
|
+
specifier,
|
|
81
|
+
tagName,
|
|
82
|
+
props: rawProps = {},
|
|
83
|
+
startOffset,
|
|
84
|
+
endOffset
|
|
85
|
+
}) => {
|
|
69
86
|
const hydrate = (0, import_shared_utils.isHydrateOnLoad)(rawProps);
|
|
70
87
|
const passProps = {...rawProps};
|
|
71
88
|
delete passProps[import_shared_utils.HYDRATE_DIRECTIVE];
|
|
72
|
-
return (0,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
return (0, import_instrumentation.getTracer)().trace({
|
|
90
|
+
name: import_instrumentation.ViewSpan.RenderIsland,
|
|
91
|
+
attributes: {specifier}
|
|
92
|
+
}, async () => {
|
|
93
|
+
return (0, import_ssr_element.ssrElement)({specifier: bootstrapSpecifier, props: passProps, serverData}, moduleBundler, resourceRegistry, routes, viewContext).then(({
|
|
94
|
+
html,
|
|
95
|
+
props = {},
|
|
96
|
+
markup: {links = []} = {links: []},
|
|
97
|
+
cache: {ttl} = {}
|
|
98
|
+
}) => {
|
|
99
|
+
pageTtl = (0, import_shared_utils.shortestTtl)(ttl, pageTtl);
|
|
100
|
+
let propsAttr = "";
|
|
101
|
+
if (hydrate) {
|
|
102
|
+
const propsId = (0, import_identity.getPropsId)();
|
|
103
|
+
propsAttr = ` ${import_identity.SSR_PROPS_ATTR}="${propsId}"`;
|
|
104
|
+
serverData[propsId] = props;
|
|
105
|
+
}
|
|
106
|
+
const [, remain] = html.split(`<${tagName}`);
|
|
107
|
+
html = [`<${tagName}`, propsAttr, remain].join("");
|
|
108
|
+
links.forEach(({href, rel, as, fetchpriority}) => {
|
|
109
|
+
const relStr = rel ? ` rel="${rel}"` : "", asStr = as ? ` as="${as}"` : "", fetchStr = fetchpriority ? ` fetchpriority="${fetchpriority}"` : "";
|
|
110
|
+
ssrLinks += `<link href="${href}"${relStr}${asStr}${fetchStr}>
|
|
90
111
|
`;
|
|
112
|
+
});
|
|
113
|
+
stringBuilder.overwrite(startOffset, endOffset, html);
|
|
114
|
+
}).catch((err) => {
|
|
115
|
+
if (debug || (0, import_shared_utils.getFeatureFlags)().SSR_WITH_CSR_FALLBACK) {
|
|
116
|
+
customElements[index].props === void 0 ? customElements[index].props = {
|
|
117
|
+
[import_shared_utils.HYDRATE_DIRECTIVE]: import_shared_utils.HYDRATE_CLIENT_VALUE
|
|
118
|
+
} : customElements[index].props[import_shared_utils.HYDRATE_DIRECTIVE] = import_shared_utils.HYDRATE_CLIENT_VALUE;
|
|
119
|
+
const errMessage = (0, import_utils.createSsrErrorMessage)(specifier, err);
|
|
120
|
+
import_diagnostics.logger.warn(errMessage, err.stack);
|
|
121
|
+
if (debug) {
|
|
122
|
+
debugMessage = errMessage;
|
|
123
|
+
serverDebug.message = debugMessage;
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
91
128
|
});
|
|
92
|
-
stringBuilder.overwrite(startOffset, endOffset, html);
|
|
93
|
-
}).catch((err) => {
|
|
94
|
-
if ((0, import_shared_utils.getFeatureFlags)().SSR_WITH_CSR_FALLBACK) {
|
|
95
|
-
customElements[index].props === void 0 ? customElements[index].props = {
|
|
96
|
-
[import_shared_utils.HYDRATE_DIRECTIVE]: import_shared_utils.HYDRATE_CLIENT_VALUE
|
|
97
|
-
} : customElements[index].props[import_shared_utils.HYDRATE_DIRECTIVE] = import_shared_utils.HYDRATE_CLIENT_VALUE;
|
|
98
|
-
import_shared_utils.logger.warn(`Server-side rendering for "${specifier}" failed. Falling back to client-side rendering. Reason: `, err.stack);
|
|
99
|
-
} else {
|
|
100
|
-
throw err;
|
|
101
|
-
}
|
|
102
129
|
});
|
|
103
130
|
}));
|
|
104
131
|
if (ssrLinks) {
|
|
@@ -106,10 +133,10 @@ function lwcSsrViewTransformer(options, {config, moduleBundler, resourceRegistry
|
|
|
106
133
|
if (headIndex >= 0) {
|
|
107
134
|
stringBuilder.prependLeft(headIndex, ssrLinks);
|
|
108
135
|
} else {
|
|
109
|
-
|
|
136
|
+
import_diagnostics.logger.error("Adding links during server-side rendering failed. Could not find the </head> tag.");
|
|
110
137
|
}
|
|
111
138
|
}
|
|
112
|
-
|
|
139
|
+
import_diagnostics.logger.verbose("lwcSsrViewTransformer response", stringBuilder);
|
|
113
140
|
return {cache: {ttl: pageTtl}};
|
|
114
141
|
}
|
|
115
142
|
};
|