@lwrjs/view-registry 0.17.2-alpha.2 → 0.17.2-alpha.20
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/build/cjs/index.cjs +41 -21
- package/build/cjs/linkers/legacy_view_bootstrap.cjs +2 -2
- package/build/cjs/linkers/preload-utils.cjs +1 -1
- package/build/cjs/linkers/utils.cjs +7 -2
- package/build/cjs/linkers/view_bootstrap.cjs +2 -2
- package/build/cjs/utils.cjs +9 -7
- package/build/es/index.d.ts +1 -0
- package/build/es/index.js +44 -20
- package/build/es/linkers/legacy_view_bootstrap.js +2 -2
- package/build/es/linkers/preload-utils.js +2 -2
- package/build/es/linkers/utils.d.ts +1 -1
- package/build/es/linkers/utils.js +7 -2
- package/build/es/linkers/view_bootstrap.js +2 -2
- package/build/es/utils.d.ts +1 -1
- package/build/es/utils.js +8 -4
- package/package.json +8 -8
package/build/cjs/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
|
32
32
|
var import_utils = __toModule(require("./utils.cjs"));
|
|
33
33
|
var import_link_lwr_resources = __toModule(require("./linkers/link-lwr-resources.cjs"));
|
|
34
34
|
var import_lru_cache = __toModule(require("lru-cache"));
|
|
35
|
+
var import_crypto = __toModule(require("crypto"));
|
|
35
36
|
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
36
37
|
var import_view_handler = __toModule(require("./view-handler.cjs"));
|
|
37
38
|
var LwrViewRegistry = class {
|
|
@@ -57,6 +58,12 @@ var LwrViewRegistry = class {
|
|
|
57
58
|
import_diagnostics.logger.verbose(`View evicted from cache ${key}`);
|
|
58
59
|
}
|
|
59
60
|
});
|
|
61
|
+
this.metadataCache = new import_lru_cache.LRUCache({
|
|
62
|
+
max: parseInt(process.env.VIEW_METADATA_CACHE_SIZE ?? "500", 10),
|
|
63
|
+
dispose: (_value, key) => {
|
|
64
|
+
import_diagnostics.logger.verbose(`Metadata evicted from cache ${key}`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
60
67
|
observer.onViewSourceChange(({payload}) => this.onViewSourceChange(payload));
|
|
61
68
|
observer.onModuleDefinitionChange(({payload}) => this.onModuleDefinitionChange(payload));
|
|
62
69
|
observer.onAssetSourceChange(({payload}) => this.onAssetSourceChange(payload));
|
|
@@ -187,13 +194,14 @@ var LwrViewRegistry = class {
|
|
|
187
194
|
const updatableViewParams = {...viewParams};
|
|
188
195
|
(0, import_utils.generateViewNonce)(updatableViewParams);
|
|
189
196
|
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
190
|
-
const
|
|
197
|
+
const pendingViewDefCacheKeyHashed = (0, import_crypto.createHash)("md5").update(pendingViewDefCacheKey).digest("hex");
|
|
198
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKeyHashed, () => (0, import_instrumentation.getTracer)().trace({
|
|
191
199
|
name: import_instrumentation.ViewSpan.RenderView,
|
|
192
200
|
attributes: {
|
|
193
201
|
view: view.id,
|
|
194
202
|
ssr: view.bootstrap?.ssr === true
|
|
195
203
|
}
|
|
196
|
-
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams,
|
|
204
|
+
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKeyHashed, renderOptions)));
|
|
197
205
|
viewDefinition.nonce = (0, import_utils.getViewNonce)(updatableViewParams);
|
|
198
206
|
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
199
207
|
const maxViewCacheTtl = (0, import_shared_utils.getFeatureFlags)().MAX_VIEW_CACHE_TTL;
|
|
@@ -219,7 +227,7 @@ var LwrViewRegistry = class {
|
|
|
219
227
|
}
|
|
220
228
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams, viewCacheKey, renderOptions) {
|
|
221
229
|
const {id, contentTemplate, rootComponent, layoutTemplate} = view;
|
|
222
|
-
const lwrResourcesId = `__LWR_RESOURCES__${
|
|
230
|
+
const lwrResourcesId = `__LWR_RESOURCES__${viewCacheKey}`;
|
|
223
231
|
const renderedContent = await this.render({id, contentTemplate, rootComponent}, {...viewParams, lwr_resources: lwrResourcesId}, runtimeParams, runtimeEnvironment);
|
|
224
232
|
let normalizedRenderOptions = (0, import_utils.normalizeRenderOptions)(this.runtimeEnvironment, renderedContent.options, renderOptions);
|
|
225
233
|
const layout = layoutTemplate || renderedContent.compiledView.layoutTemplate;
|
|
@@ -243,6 +251,10 @@ var LwrViewRegistry = class {
|
|
|
243
251
|
lwr_resources: lwrResourcesId
|
|
244
252
|
}, runtimeParams, runtimeEnvironment);
|
|
245
253
|
normalizedRenderOptions = (0, import_utils.normalizeRenderOptions)(this.runtimeEnvironment, renderedLayout.options, normalizedRenderOptions);
|
|
254
|
+
const warnings = [
|
|
255
|
+
...renderedContent.metadata.serverDebug?.warnings || [],
|
|
256
|
+
...renderedLayout.metadata.serverDebug?.warnings || []
|
|
257
|
+
];
|
|
246
258
|
const renderedViewDef = await this.link({
|
|
247
259
|
...renderedLayout,
|
|
248
260
|
compiledView: {
|
|
@@ -262,14 +274,10 @@ var LwrViewRegistry = class {
|
|
|
262
274
|
...renderedContent.metadata.serverData,
|
|
263
275
|
...renderedLayout.metadata.serverData
|
|
264
276
|
},
|
|
265
|
-
serverDebug: {
|
|
266
|
-
...renderedContent.metadata.serverDebug,
|
|
267
|
-
...renderedLayout.metadata.serverDebug
|
|
268
|
-
},
|
|
277
|
+
serverDebug: {warnings},
|
|
269
278
|
serverBundles: renderedContent.metadata.serverBundles
|
|
270
279
|
},
|
|
271
|
-
cache: renderedContent.cache
|
|
272
|
-
status: renderedContent.status
|
|
280
|
+
cache: renderedContent.cache
|
|
273
281
|
}, {
|
|
274
282
|
view: {...view, layoutTemplate: layoutTemplatePath},
|
|
275
283
|
viewParams,
|
|
@@ -290,7 +298,8 @@ var LwrViewRegistry = class {
|
|
|
290
298
|
...runtimeParams,
|
|
291
299
|
...globalContext,
|
|
292
300
|
...compiledView.properties,
|
|
293
|
-
...viewParams
|
|
301
|
+
...viewParams,
|
|
302
|
+
runtimeParams: {...runtimeParams}
|
|
294
303
|
}, runtimeEnvironment);
|
|
295
304
|
const normalizedResult = (0, import_utils.normalizeRenderedResult)(result);
|
|
296
305
|
return {
|
|
@@ -318,17 +327,33 @@ var LwrViewRegistry = class {
|
|
|
318
327
|
metadata: renderedViewMetadata,
|
|
319
328
|
compiledView: {immutable = true}
|
|
320
329
|
} = renderedView;
|
|
330
|
+
let traceId;
|
|
321
331
|
const {linkedMetadata, stringBuilder} = (0, import_instrumentation.getTracer)().trace({
|
|
322
332
|
name: import_instrumentation.ViewSpan.ParseView,
|
|
323
333
|
attributes: {
|
|
324
334
|
view: view.id,
|
|
325
335
|
ssr: view.bootstrap?.ssr === true
|
|
326
336
|
}
|
|
327
|
-
}, () => {
|
|
328
|
-
|
|
337
|
+
}, (span) => {
|
|
338
|
+
traceId = span.traceId;
|
|
339
|
+
let linkedMetadata2 = renderedViewMetadata;
|
|
340
|
+
if (!skipMetadataCollection) {
|
|
341
|
+
const contentHash = (0, import_crypto.createHash)("md5").update(renderedViewContent).digest("hex");
|
|
342
|
+
const cacheKey = `${view.id}:${contentHash}`;
|
|
343
|
+
if (this.metadataCache.has(cacheKey)) {
|
|
344
|
+
linkedMetadata2 = this.metadataCache.get(cacheKey);
|
|
345
|
+
} else {
|
|
346
|
+
linkedMetadata2 = (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
347
|
+
this.metadataCache.set(cacheKey, linkedMetadata2);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
329
350
|
const stringBuilder2 = (0, import_shared_utils.createStringBuilder)(renderedViewContent);
|
|
330
351
|
return {linkedMetadata: linkedMetadata2, stringBuilder: stringBuilder2};
|
|
331
352
|
});
|
|
353
|
+
if (!(0, import_shared_utils.getFeatureFlags)().DISABLE_B3_TRACING && traceId && runtimeParams.viewSpanID) {
|
|
354
|
+
const content = `00-${traceId}-${runtimeParams.viewSpanID}-01`;
|
|
355
|
+
(0, import_shared_utils.addHeadMarkup)([{meta: [{name: "traceparent", content}]}], stringBuilder);
|
|
356
|
+
}
|
|
332
357
|
const mergedViewContext = {
|
|
333
358
|
...viewContext,
|
|
334
359
|
config: this.globalConfig,
|
|
@@ -336,7 +361,6 @@ var LwrViewRegistry = class {
|
|
|
336
361
|
importer: importer || renderedView.compiledView.filePath
|
|
337
362
|
};
|
|
338
363
|
let pageTtl = renderedView.cache.ttl;
|
|
339
|
-
let pageStatus = renderedView.status;
|
|
340
364
|
for (const viewTransformer of this.viewTransformers) {
|
|
341
365
|
const linkResults = await (0, import_instrumentation.getTracer)().trace({
|
|
342
366
|
name: import_instrumentation.ViewSpan.Transform,
|
|
@@ -346,9 +370,6 @@ var LwrViewRegistry = class {
|
|
|
346
370
|
}, () => viewTransformer.link?.(stringBuilder, mergedViewContext, linkedMetadata));
|
|
347
371
|
const ttl = linkResults && linkResults.cache?.ttl;
|
|
348
372
|
pageTtl = (0, import_shared_utils.shortestTtl)(ttl || void 0, pageTtl);
|
|
349
|
-
if (!pageStatus && linkResults) {
|
|
350
|
-
pageStatus = linkResults.status;
|
|
351
|
-
}
|
|
352
373
|
}
|
|
353
374
|
const linkedAssetContent = stringBuilder.toString();
|
|
354
375
|
if (linkedAssetContent.includes(lwrResourcesId)) {
|
|
@@ -370,7 +391,8 @@ var LwrViewRegistry = class {
|
|
|
370
391
|
return res;
|
|
371
392
|
res.push({
|
|
372
393
|
url: asset.src,
|
|
373
|
-
relative: (0, import_shared_utils.isRelative)(asset.src)
|
|
394
|
+
relative: (0, import_shared_utils.isRelative)(asset.src),
|
|
395
|
+
integrity: asset.integrity
|
|
374
396
|
});
|
|
375
397
|
return res;
|
|
376
398
|
}, []));
|
|
@@ -383,8 +405,7 @@ var LwrViewRegistry = class {
|
|
|
383
405
|
...viewRecord,
|
|
384
406
|
serverBundles: linkedMetadata.serverBundles
|
|
385
407
|
},
|
|
386
|
-
cache: {ttl: pageTtl}
|
|
387
|
-
status: pageStatus
|
|
408
|
+
cache: {ttl: pageTtl}
|
|
388
409
|
};
|
|
389
410
|
}
|
|
390
411
|
return {
|
|
@@ -395,8 +416,7 @@ var LwrViewRegistry = class {
|
|
|
395
416
|
moduleResources: [],
|
|
396
417
|
serverBundles: linkedMetadata.serverBundles
|
|
397
418
|
},
|
|
398
|
-
cache: {ttl: pageTtl}
|
|
399
|
-
status: pageStatus
|
|
419
|
+
cache: {ttl: pageTtl}
|
|
400
420
|
};
|
|
401
421
|
}
|
|
402
422
|
};
|
|
@@ -251,7 +251,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
}));
|
|
254
|
-
if (viewContainsLiveElements || serverDebug?.
|
|
254
|
+
if (viewContainsLiveElements || serverDebug?.warnings?.length) {
|
|
255
255
|
if ((0, import_shared_utils.isLocalDev)()) {
|
|
256
256
|
const localDevSpecifier = "lwr_local_dev/bootstrap";
|
|
257
257
|
rootComponents.push(localDevSpecifier);
|
|
@@ -278,7 +278,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
278
278
|
serverData,
|
|
279
279
|
...isAMD && {requiredModules: requiredAmdModules},
|
|
280
280
|
...isAMD && {preloadModules: viewPreloads.specifiers}
|
|
281
|
-
}, runtimeEnvironment, runtimeParams, serverDebug?.
|
|
281
|
+
}, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
|
|
282
282
|
}
|
|
283
283
|
if (!isAMD && hmrEnabled) {
|
|
284
284
|
configResources.unshift((0, import_utils2.getViewHmrConfigurationResource)(view, viewMetadata));
|
|
@@ -31,7 +31,7 @@ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
|
31
31
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
32
32
|
function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
|
|
33
33
|
if (!uri) {
|
|
34
|
-
throw new import_diagnostics.
|
|
34
|
+
throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.PRELOAD_MODULE(specifier));
|
|
35
35
|
}
|
|
36
36
|
const [removedVersion, version] = specifier.split("/v/");
|
|
37
37
|
const normalizedSpecifier = version === import_shared_utils.VERSION_NOT_PROVIDED ? removedVersion : specifier;
|
|
@@ -29,9 +29,10 @@ __export(exports, {
|
|
|
29
29
|
getViewBootstrapConfigurationResource: () => getViewBootstrapConfigurationResource,
|
|
30
30
|
getViewHmrConfigurationResource: () => getViewHmrConfigurationResource
|
|
31
31
|
});
|
|
32
|
+
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
32
33
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
33
34
|
var CONTENT_TYPE = "application/javascript";
|
|
34
|
-
function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironment, runtimeParams,
|
|
35
|
+
function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironment, runtimeParams, warnings) {
|
|
35
36
|
const {compat, debug, hmrEnabled, apiVersion, format} = runtimeEnvironment;
|
|
36
37
|
const isESM = format === "esm";
|
|
37
38
|
const defaultUrl = (0, import_shared_utils.getModuleUriPrefix)(runtimeEnvironment, runtimeParams);
|
|
@@ -51,8 +52,12 @@ function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironm
|
|
|
51
52
|
};
|
|
52
53
|
const lwrEnv = {
|
|
53
54
|
SSR: false,
|
|
55
|
+
SSREnabled: !!viewInfo.ssr,
|
|
54
56
|
...(0, import_shared_utils.buildEnvironmentContext)(runtimeParams)
|
|
55
57
|
};
|
|
58
|
+
let warnMessages = `console.group('Server-side rendering warnings:');`;
|
|
59
|
+
warnings?.forEach((warning) => warnMessages += `console.warn('${(0, import_diagnostics.stringifyError)(warning)}');`);
|
|
60
|
+
warnMessages += "console.groupEnd();";
|
|
56
61
|
const configString = [
|
|
57
62
|
"/* This script is generated */",
|
|
58
63
|
"/* Client Bootstrap configuration */",
|
|
@@ -64,7 +69,7 @@ function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironm
|
|
|
64
69
|
`globalThis.LWR = {...globalThis.LWR, env: ${JSON.stringify(lwrEnv)}};`,
|
|
65
70
|
`globalThis.process={...globalThis.process,env:{...globalThis.process?.env,...${JSON.stringify(nodeEnv)}}};`,
|
|
66
71
|
`globalThis.lwcRuntimeFlags = { ENABLE_MIXED_SHADOW_MODE: ${viewInfo.mixedMode}, ENABLE_WIRE_SYNC_EMIT: ${viewInfo.ssr} };`,
|
|
67
|
-
|
|
72
|
+
warnings?.length && warnMessages
|
|
68
73
|
].filter(Boolean).join("\n");
|
|
69
74
|
if (viewInfo.configAsSrc) {
|
|
70
75
|
const viewUrl = viewInfo.url || "/";
|
|
@@ -234,7 +234,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
234
234
|
importMetadata = await (0, import_shared_utils.toImportMetadata)(graph, importMetadata, moduleRegistry, runtimeEnvironment, runtimeParams);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
|
-
if (viewContainsLiveElements || serverDebug?.
|
|
237
|
+
if (viewContainsLiveElements || serverDebug?.warnings?.length) {
|
|
238
238
|
configResources.unshift((0, import_utils2.getViewBootstrapConfigurationResource)({
|
|
239
239
|
id: view.id,
|
|
240
240
|
url: viewParams?.page?.url,
|
|
@@ -252,7 +252,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
252
252
|
serverData,
|
|
253
253
|
...isAMD && {requiredModules: requiredAmdModules},
|
|
254
254
|
...isAMD && {preloadModules: viewPreloads.specifiers}
|
|
255
|
-
}, runtimeEnvironment, runtimeParams, serverDebug?.
|
|
255
|
+
}, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
|
|
256
256
|
}
|
|
257
257
|
if (!isAMD && hmrEnabled) {
|
|
258
258
|
configResources.unshift((0, import_utils2.getViewHmrConfigurationResource)(view, viewMetadata));
|
package/build/cjs/utils.cjs
CHANGED
|
@@ -112,8 +112,7 @@ function normalizeRenderedResult({
|
|
|
112
112
|
renderedView,
|
|
113
113
|
metadata,
|
|
114
114
|
options,
|
|
115
|
-
cache
|
|
116
|
-
status
|
|
115
|
+
cache
|
|
117
116
|
}) {
|
|
118
117
|
return {
|
|
119
118
|
renderedView,
|
|
@@ -127,16 +126,16 @@ function normalizeRenderedResult({
|
|
|
127
126
|
options: {
|
|
128
127
|
skipMetadataCollection: options ? options.skipMetadataCollection : false
|
|
129
128
|
},
|
|
130
|
-
cache: cache || {}
|
|
131
|
-
status
|
|
129
|
+
cache: cache || {}
|
|
132
130
|
};
|
|
133
131
|
}
|
|
134
132
|
function reduceSourceAssetReferences(assets) {
|
|
135
|
-
return assets.map(({url, tagName, override}) => {
|
|
133
|
+
return assets.map(({url, tagName, override, integrity}) => {
|
|
136
134
|
return {
|
|
137
135
|
url,
|
|
138
136
|
tagName,
|
|
139
|
-
override
|
|
137
|
+
override,
|
|
138
|
+
integrity
|
|
140
139
|
};
|
|
141
140
|
});
|
|
142
141
|
}
|
|
@@ -314,7 +313,7 @@ function generateLinkHeaders(assets, patterns) {
|
|
|
314
313
|
for (const filePattern of matchPatterns) {
|
|
315
314
|
const regex = new RegExp(filePattern);
|
|
316
315
|
if (regex.test(path)) {
|
|
317
|
-
matched = pattern.attributes;
|
|
316
|
+
matched = pattern.attributes || {};
|
|
318
317
|
break;
|
|
319
318
|
}
|
|
320
319
|
}
|
|
@@ -323,6 +322,9 @@ function generateLinkHeaders(assets, patterns) {
|
|
|
323
322
|
}
|
|
324
323
|
if (matched) {
|
|
325
324
|
assetConfig[path] = matched;
|
|
325
|
+
if (assetRef.integrity) {
|
|
326
|
+
assetConfig[path].integrity = assetRef.integrity;
|
|
327
|
+
}
|
|
326
328
|
}
|
|
327
329
|
}
|
|
328
330
|
return Object.keys(assetConfig).reduce((linkHeader, path) => {
|
package/build/es/index.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export declare class LwrViewRegistry implements ViewRegistry {
|
|
|
47
47
|
getViewDefinition(view: View, viewParams: ViewParams, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams, renderOptions?: RenderOptions): Promise<LinkedViewDefinition>;
|
|
48
48
|
private renderView;
|
|
49
49
|
private render;
|
|
50
|
+
private metadataCache;
|
|
50
51
|
private link;
|
|
51
52
|
}
|
|
52
53
|
//# sourceMappingURL=index.d.ts.map
|
package/build/es/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { InflightTasks, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getFeatureFlags, getSpecifier, isLocalDev, normalizeResourcePath, shortestTtl,
|
|
1
|
+
import { InflightTasks, addHeadMarkup, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getFeatureFlags, getSpecifier, isLocalDev, isRelative, normalizeResourcePath, shortestTtl, } from '@lwrjs/shared-utils';
|
|
2
2
|
import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
|
|
3
3
|
import { generateViewNonce, getViewNonce, normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences, getViewDefCacheKey, } from './utils.js';
|
|
4
4
|
import { linkLwrResources } from './linkers/link-lwr-resources.js';
|
|
5
5
|
// TODO: investigate perf impact W-16056356
|
|
6
6
|
import { LRUCache } from 'lru-cache';
|
|
7
|
+
import { createHash } from 'crypto';
|
|
7
8
|
import { LwrError, LwrServerError, descriptions, logger } from '@lwrjs/diagnostics';
|
|
8
9
|
export { LwrViewHandler } from './view-handler.js';
|
|
9
10
|
export class LwrViewRegistry {
|
|
@@ -37,6 +38,12 @@ export class LwrViewRegistry {
|
|
|
37
38
|
logger.verbose(`View evicted from cache ${key}`);
|
|
38
39
|
},
|
|
39
40
|
});
|
|
41
|
+
this.metadataCache = new LRUCache({
|
|
42
|
+
max: parseInt(process.env.VIEW_METADATA_CACHE_SIZE ?? '500', 10),
|
|
43
|
+
dispose: (_value, key) => {
|
|
44
|
+
logger.verbose(`Metadata evicted from cache ${key}`);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
40
47
|
// Observers for cached entries external dependencies -- view templates, modules, and assets
|
|
41
48
|
observer.onViewSourceChange(({ payload }) => this.onViewSourceChange(payload));
|
|
42
49
|
observer.onModuleDefinitionChange(({ payload }) => this.onModuleDefinitionChange(payload));
|
|
@@ -194,13 +201,16 @@ export class LwrViewRegistry {
|
|
|
194
201
|
const updatableViewParams = { ...viewParams };
|
|
195
202
|
generateViewNonce(updatableViewParams);
|
|
196
203
|
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
197
|
-
const
|
|
204
|
+
const pendingViewDefCacheKeyHashed = createHash('md5')
|
|
205
|
+
.update(pendingViewDefCacheKey)
|
|
206
|
+
.digest('hex');
|
|
207
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKeyHashed, () => getTracer().trace({
|
|
198
208
|
name: ViewSpan.RenderView,
|
|
199
209
|
attributes: {
|
|
200
210
|
view: view.id,
|
|
201
211
|
ssr: view.bootstrap?.ssr === true,
|
|
202
212
|
},
|
|
203
|
-
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams,
|
|
213
|
+
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKeyHashed, renderOptions)));
|
|
204
214
|
// Once the view is generated add the nonce to the response so it can be cached and then added to the headers
|
|
205
215
|
viewDefinition.nonce = getViewNonce(updatableViewParams);
|
|
206
216
|
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
@@ -236,7 +246,7 @@ export class LwrViewRegistry {
|
|
|
236
246
|
}
|
|
237
247
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams, viewCacheKey, renderOptions) {
|
|
238
248
|
const { id, contentTemplate, rootComponent, layoutTemplate } = view;
|
|
239
|
-
const lwrResourcesId = `__LWR_RESOURCES__${
|
|
249
|
+
const lwrResourcesId = `__LWR_RESOURCES__${viewCacheKey}`;
|
|
240
250
|
const renderedContent = await this.render({ id, contentTemplate, rootComponent }, { ...viewParams, lwr_resources: lwrResourcesId }, runtimeParams, runtimeEnvironment);
|
|
241
251
|
// normalize the renderOptions provided by the CompiledView content with the request options.
|
|
242
252
|
let normalizedRenderOptions = normalizeRenderOptions(this.runtimeEnvironment, renderedContent.options, renderOptions);
|
|
@@ -264,6 +274,10 @@ export class LwrViewRegistry {
|
|
|
264
274
|
lwr_resources: lwrResourcesId,
|
|
265
275
|
}, runtimeParams, runtimeEnvironment);
|
|
266
276
|
normalizedRenderOptions = normalizeRenderOptions(this.runtimeEnvironment, renderedLayout.options, normalizedRenderOptions);
|
|
277
|
+
const warnings = [
|
|
278
|
+
...(renderedContent.metadata.serverDebug?.warnings || []),
|
|
279
|
+
...(renderedLayout.metadata.serverDebug?.warnings || []),
|
|
280
|
+
];
|
|
267
281
|
const renderedViewDef = await this.link({
|
|
268
282
|
...renderedLayout,
|
|
269
283
|
// Rendered Layout view's immutability is a composite of the layouts mutability and the body's mutability
|
|
@@ -285,14 +299,10 @@ export class LwrViewRegistry {
|
|
|
285
299
|
...renderedContent.metadata.serverData,
|
|
286
300
|
...renderedLayout.metadata.serverData,
|
|
287
301
|
},
|
|
288
|
-
serverDebug: {
|
|
289
|
-
...renderedContent.metadata.serverDebug,
|
|
290
|
-
...renderedLayout.metadata.serverDebug,
|
|
291
|
-
},
|
|
302
|
+
serverDebug: { warnings },
|
|
292
303
|
serverBundles: renderedContent.metadata.serverBundles, // 1st pass of SSR
|
|
293
304
|
},
|
|
294
305
|
cache: renderedContent.cache,
|
|
295
|
-
status: renderedContent.status,
|
|
296
306
|
},
|
|
297
307
|
// Render Content now contains a layout
|
|
298
308
|
{
|
|
@@ -328,6 +338,8 @@ export class LwrViewRegistry {
|
|
|
328
338
|
...globalContext,
|
|
329
339
|
...compiledView.properties,
|
|
330
340
|
...viewParams,
|
|
341
|
+
// provides access to runtimeParams which are not overwritten by context/props/viewParams
|
|
342
|
+
runtimeParams: { ...runtimeParams },
|
|
331
343
|
}, runtimeEnvironment);
|
|
332
344
|
const normalizedResult = normalizeRenderedResult(result);
|
|
333
345
|
return {
|
|
@@ -343,19 +355,37 @@ export class LwrViewRegistry {
|
|
|
343
355
|
const runtimeEnvironment = { ...runtimeEnv, immutableAssets: freezeAssets };
|
|
344
356
|
// normalize/extract metadata
|
|
345
357
|
const { renderedView: renderedViewContent, metadata: renderedViewMetadata, compiledView: { immutable = true }, } = renderedView;
|
|
358
|
+
let traceId;
|
|
346
359
|
const { linkedMetadata, stringBuilder } = getTracer().trace({
|
|
347
360
|
name: ViewSpan.ParseView,
|
|
348
361
|
attributes: {
|
|
349
362
|
view: view.id,
|
|
350
363
|
ssr: view.bootstrap?.ssr === true,
|
|
351
364
|
},
|
|
352
|
-
}, () => {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
365
|
+
}, (span) => {
|
|
366
|
+
traceId = span.traceId;
|
|
367
|
+
let linkedMetadata = renderedViewMetadata;
|
|
368
|
+
if (!skipMetadataCollection) {
|
|
369
|
+
// Create a unique key based on view ID and content hash
|
|
370
|
+
const contentHash = createHash('md5').update(renderedViewContent).digest('hex');
|
|
371
|
+
const cacheKey = `${view.id}:${contentHash}`;
|
|
372
|
+
if (this.metadataCache.has(cacheKey)) {
|
|
373
|
+
linkedMetadata = this.metadataCache.get(cacheKey);
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
linkedMetadata = extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
377
|
+
this.metadataCache.set(cacheKey, linkedMetadata);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
356
380
|
const stringBuilder = createStringBuilder(renderedViewContent);
|
|
357
381
|
return { linkedMetadata, stringBuilder };
|
|
358
382
|
});
|
|
383
|
+
// Add distributed tracing meta tag to pass tracing info to the client
|
|
384
|
+
// {version}-{traceId}-{spanId}-{sampleDecision} and version is always 00
|
|
385
|
+
if (!getFeatureFlags().DISABLE_B3_TRACING && traceId && runtimeParams.viewSpanID) {
|
|
386
|
+
const content = `00-${traceId}-${runtimeParams.viewSpanID}-01`;
|
|
387
|
+
addHeadMarkup([{ meta: [{ name: 'traceparent', content }] }], stringBuilder);
|
|
388
|
+
}
|
|
359
389
|
const mergedViewContext = {
|
|
360
390
|
...viewContext,
|
|
361
391
|
config: this.globalConfig,
|
|
@@ -364,7 +394,6 @@ export class LwrViewRegistry {
|
|
|
364
394
|
};
|
|
365
395
|
// Note: this is the TTL for the page NOT for the view registry cache
|
|
366
396
|
let pageTtl = renderedView.cache.ttl;
|
|
367
|
-
let pageStatus = renderedView.status;
|
|
368
397
|
for (const viewTransformer of this.viewTransformers) {
|
|
369
398
|
// eslint-disable-next-line no-await-in-loop
|
|
370
399
|
const linkResults = await getTracer().trace({
|
|
@@ -376,10 +405,6 @@ export class LwrViewRegistry {
|
|
|
376
405
|
// Keep track of the shortest TTL from each view transformer (e.g. lwcSsrViewTransformer)
|
|
377
406
|
const ttl = linkResults && linkResults.cache?.ttl;
|
|
378
407
|
pageTtl = shortestTtl(ttl || undefined, pageTtl);
|
|
379
|
-
// Set the status info, if it doesn't already exist
|
|
380
|
-
if (!pageStatus && linkResults) {
|
|
381
|
-
pageStatus = linkResults.status;
|
|
382
|
-
}
|
|
383
408
|
}
|
|
384
409
|
const linkedAssetContent = stringBuilder.toString();
|
|
385
410
|
// Link LWR related resources
|
|
@@ -406,6 +431,7 @@ export class LwrViewRegistry {
|
|
|
406
431
|
res.push({
|
|
407
432
|
url: asset.src,
|
|
408
433
|
relative: isRelative(asset.src),
|
|
434
|
+
integrity: asset.integrity,
|
|
409
435
|
});
|
|
410
436
|
return res;
|
|
411
437
|
}, []));
|
|
@@ -420,7 +446,6 @@ export class LwrViewRegistry {
|
|
|
420
446
|
serverBundles: linkedMetadata.serverBundles,
|
|
421
447
|
},
|
|
422
448
|
cache: { ttl: pageTtl },
|
|
423
|
-
status: pageStatus,
|
|
424
449
|
};
|
|
425
450
|
}
|
|
426
451
|
return {
|
|
@@ -432,7 +457,6 @@ export class LwrViewRegistry {
|
|
|
432
457
|
serverBundles: linkedMetadata.serverBundles,
|
|
433
458
|
},
|
|
434
459
|
cache: { ttl: pageTtl },
|
|
435
|
-
status: pageStatus,
|
|
436
460
|
};
|
|
437
461
|
}
|
|
438
462
|
}
|
|
@@ -290,7 +290,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
}));
|
|
293
|
-
if (viewContainsLiveElements || serverDebug?.
|
|
293
|
+
if (viewContainsLiveElements || serverDebug?.warnings?.length) {
|
|
294
294
|
if (isLocalDev()) {
|
|
295
295
|
// ADD the client-side bootstrap module and mapping for local-dev
|
|
296
296
|
const localDevSpecifier = 'lwr_local_dev/bootstrap';
|
|
@@ -320,7 +320,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
320
320
|
...(isAMD && { requiredModules: requiredAmdModules }),
|
|
321
321
|
// in AMD we need to tell the loader what modules we are preloading
|
|
322
322
|
...(isAMD && { preloadModules: viewPreloads.specifiers }),
|
|
323
|
-
}, runtimeEnvironment, runtimeParams, serverDebug?.
|
|
323
|
+
}, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
|
|
324
324
|
}
|
|
325
325
|
if (!isAMD && hmrEnabled) {
|
|
326
326
|
configResources.unshift(getViewHmrConfigurationResource(view, viewMetadata));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LwrInvalidError, descriptions, logger } from '@lwrjs/diagnostics';
|
|
2
2
|
import { explodeSpecifier, getGroupName, getVersionedModuleId, normalizeVersionToUri, VERSION_NOT_PROVIDED, getSpecifier, isGroupie, } from '@lwrjs/shared-utils';
|
|
3
3
|
/**
|
|
4
4
|
* keeps track of preloadModules metadata
|
|
@@ -6,7 +6,7 @@ import { explodeSpecifier, getGroupName, getVersionedModuleId, normalizeVersionT
|
|
|
6
6
|
export function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
|
|
7
7
|
// Throw a very specific error if we get this back and the uri property is not set
|
|
8
8
|
if (!uri) {
|
|
9
|
-
throw new
|
|
9
|
+
throw new LwrInvalidError(descriptions.INVALID.PRELOAD_MODULE(specifier));
|
|
10
10
|
}
|
|
11
11
|
// We need to support version-less preloadModules, including version-less rootComponents.
|
|
12
12
|
// Removing the "/v/version_not_provided" hack from the preloadModules specifier
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientBootstrapConfig, RuntimeEnvironment, RuntimeParams, ResourceDefinition, RenderedViewMetadata, CustomElementReference, View, ViewInfo, FlattenedModuleGraphs } from '@lwrjs/types';
|
|
2
|
-
export declare function getViewBootstrapConfigurationResource(viewInfo: ViewInfo, config: ClientBootstrapConfig, runtimeEnvironment: RuntimeEnvironment, runtimeParams: RuntimeParams,
|
|
2
|
+
export declare function getViewBootstrapConfigurationResource(viewInfo: ViewInfo, config: ClientBootstrapConfig, runtimeEnvironment: RuntimeEnvironment, runtimeParams: RuntimeParams, warnings?: (Error | string)[]): ResourceDefinition;
|
|
3
3
|
export declare function getViewHmrConfigurationResource(view: View, viewMetadata: RenderedViewMetadata): ResourceDefinition;
|
|
4
4
|
export declare function flattenCustomElements(arr: CustomElementReference[], isSSR?: boolean): CustomElementReference[];
|
|
5
5
|
export declare function getBundleIntegrity(bootstrapModuleGraph: FlattenedModuleGraphs, versionedSpecifier: string): string | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { stringifyError } from '@lwrjs/diagnostics';
|
|
1
2
|
import { buildEnvironmentContext, getMappingUriPrefix, getModuleUriPrefix, getClientBootstrapConfigurationUri, hashContent, } from '@lwrjs/shared-utils';
|
|
2
3
|
const CONTENT_TYPE = 'application/javascript';
|
|
3
|
-
export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironment, runtimeParams,
|
|
4
|
+
export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironment, runtimeParams, warnings) {
|
|
4
5
|
const { compat, debug, hmrEnabled, apiVersion, format } = runtimeEnvironment;
|
|
5
6
|
const isESM = format === 'esm';
|
|
6
7
|
const defaultUrl = getModuleUriPrefix(runtimeEnvironment, runtimeParams);
|
|
@@ -24,9 +25,13 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
|
|
|
24
25
|
const lwrEnv = {
|
|
25
26
|
// Note: SSR is always false because this script is executed on the client
|
|
26
27
|
SSR: false,
|
|
28
|
+
SSREnabled: !!viewInfo.ssr,
|
|
27
29
|
// Used by `lwr/environment`
|
|
28
30
|
...buildEnvironmentContext(runtimeParams),
|
|
29
31
|
};
|
|
32
|
+
let warnMessages = `console.group('Server-side rendering warnings:');`;
|
|
33
|
+
warnings?.forEach((warning) => (warnMessages += `console.warn('${stringifyError(warning)}');`));
|
|
34
|
+
warnMessages += 'console.groupEnd();';
|
|
30
35
|
const configString = [
|
|
31
36
|
'/* This script is generated */',
|
|
32
37
|
'/* Client Bootstrap configuration */',
|
|
@@ -39,7 +44,7 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
|
|
|
39
44
|
`globalThis.process={...globalThis.process,env:{...globalThis.process?.env,...${JSON.stringify(nodeEnv)}}};`,
|
|
40
45
|
// TODO: evaluate moving these to app layer
|
|
41
46
|
`globalThis.lwcRuntimeFlags = { ENABLE_MIXED_SHADOW_MODE: ${viewInfo.mixedMode}, ENABLE_WIRE_SYNC_EMIT: ${viewInfo.ssr} };`,
|
|
42
|
-
|
|
47
|
+
warnings?.length && warnMessages,
|
|
43
48
|
]
|
|
44
49
|
.filter(Boolean)
|
|
45
50
|
.join('\n');
|
|
@@ -262,7 +262,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
262
262
|
importMetadata = await toImportMetadata(graph, importMetadata, moduleRegistry, runtimeEnvironment, runtimeParams);
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
if (viewContainsLiveElements || serverDebug?.
|
|
265
|
+
if (viewContainsLiveElements || serverDebug?.warnings?.length) {
|
|
266
266
|
// ADD configuration of the bootstrapModule
|
|
267
267
|
configResources.unshift(getViewBootstrapConfigurationResource({
|
|
268
268
|
id: view.id,
|
|
@@ -282,7 +282,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
282
282
|
...(isAMD && { requiredModules: requiredAmdModules }),
|
|
283
283
|
// in AMD we need to tell the loader what modules we are preloading
|
|
284
284
|
...(isAMD && { preloadModules: viewPreloads.specifiers }),
|
|
285
|
-
}, runtimeEnvironment, runtimeParams, serverDebug?.
|
|
285
|
+
}, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
|
|
286
286
|
}
|
|
287
287
|
if (!isAMD && hmrEnabled) {
|
|
288
288
|
configResources.unshift(getViewHmrConfigurationResource(view, viewMetadata));
|
package/build/es/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AssetReference, JsonCompatible, LinkedViewDefinition, LwrErrorRoute, LwrRoute, ModuleBundler, ModuleId, ModuleJson, ModuleRegistry, NormalizedRenderingResult, PublicModuleRegistry, RenderOptions, RenderedAssetReference, RenderingResult, ResourceDefinition, RouteHandlerViewResponse, RuntimeEnvironment, RuntimeParams, ViewModuleResourceContext, ViewPageContext, ViewParams, ViewRequest, ViewResponse, ViewDefinitionResponse, View } from '@lwrjs/types';
|
|
2
2
|
export type HTMLResource = Partial<ResourceDefinition>;
|
|
3
3
|
export declare function generateHtmlTag(definition: HTMLResource): Promise<string>;
|
|
4
|
-
export declare function normalizeRenderedResult({ renderedView, metadata, options, cache,
|
|
4
|
+
export declare function normalizeRenderedResult({ renderedView, metadata, options, cache, }: RenderingResult): NormalizedRenderingResult;
|
|
5
5
|
export declare function reduceSourceAssetReferences(assets: AssetReference[]): RenderedAssetReference[];
|
|
6
6
|
export declare function normalizeRenderOptions(runtimeEnvironment: RuntimeEnvironment, overrideRenderOptions?: RenderOptions, baseRenderOptions?: RenderOptions): Required<RenderOptions>;
|
|
7
7
|
export declare function generatePageContext({ requestPath: url }: ViewRequest, { id, contentTemplate, properties }: LwrRoute | LwrErrorRoute, runtimeParams: RuntimeParams): JsonCompatible<ViewPageContext>;
|
package/build/es/utils.js
CHANGED
|
@@ -66,7 +66,7 @@ export async function generateHtmlTag(definition) {
|
|
|
66
66
|
}
|
|
67
67
|
throw new Error(`Invalid external Resource Definition: missing a "src": "${definition.specifier}"`);
|
|
68
68
|
}
|
|
69
|
-
export function normalizeRenderedResult({ renderedView, metadata, options, cache,
|
|
69
|
+
export function normalizeRenderedResult({ renderedView, metadata, options, cache, }) {
|
|
70
70
|
return {
|
|
71
71
|
renderedView,
|
|
72
72
|
metadata: {
|
|
@@ -80,15 +80,15 @@ export function normalizeRenderedResult({ renderedView, metadata, options, cache
|
|
|
80
80
|
skipMetadataCollection: options ? options.skipMetadataCollection : false,
|
|
81
81
|
},
|
|
82
82
|
cache: cache || {},
|
|
83
|
-
status,
|
|
84
83
|
};
|
|
85
84
|
}
|
|
86
85
|
export function reduceSourceAssetReferences(assets) {
|
|
87
|
-
return assets.map(({ url, tagName, override }) => {
|
|
86
|
+
return assets.map(({ url, tagName, override, integrity }) => {
|
|
88
87
|
return {
|
|
89
88
|
url,
|
|
90
89
|
tagName,
|
|
91
90
|
override,
|
|
91
|
+
integrity,
|
|
92
92
|
};
|
|
93
93
|
});
|
|
94
94
|
}
|
|
@@ -300,7 +300,7 @@ export function generateLinkHeaders(assets, patterns) {
|
|
|
300
300
|
for (const filePattern of matchPatterns) {
|
|
301
301
|
const regex = new RegExp(filePattern);
|
|
302
302
|
if (regex.test(path)) {
|
|
303
|
-
matched = pattern.attributes;
|
|
303
|
+
matched = pattern.attributes || {};
|
|
304
304
|
break;
|
|
305
305
|
}
|
|
306
306
|
}
|
|
@@ -309,6 +309,10 @@ export function generateLinkHeaders(assets, patterns) {
|
|
|
309
309
|
}
|
|
310
310
|
if (matched) {
|
|
311
311
|
assetConfig[path] = matched;
|
|
312
|
+
if (assetRef.integrity) {
|
|
313
|
+
// always add the integrity attribute, if it exists
|
|
314
|
+
assetConfig[path].integrity = assetRef.integrity;
|
|
315
|
+
}
|
|
312
316
|
}
|
|
313
317
|
}
|
|
314
318
|
// Use the assetConfig to construct the Link Header
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.17.2-alpha.
|
|
7
|
+
"version": "0.17.2-alpha.20",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -33,20 +33,20 @@
|
|
|
33
33
|
"build": "tsc -b"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@lwrjs/app-service": "0.17.2-alpha.
|
|
37
|
-
"@lwrjs/diagnostics": "0.17.2-alpha.
|
|
38
|
-
"@lwrjs/instrumentation": "0.17.2-alpha.
|
|
39
|
-
"@lwrjs/shared-utils": "0.17.2-alpha.
|
|
36
|
+
"@lwrjs/app-service": "0.17.2-alpha.20",
|
|
37
|
+
"@lwrjs/diagnostics": "0.17.2-alpha.20",
|
|
38
|
+
"@lwrjs/instrumentation": "0.17.2-alpha.20",
|
|
39
|
+
"@lwrjs/shared-utils": "0.17.2-alpha.20",
|
|
40
40
|
"lru-cache": "^10.4.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@lwrjs/types": "0.17.2-alpha.
|
|
43
|
+
"@lwrjs/types": "0.17.2-alpha.20"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
46
|
+
"node": ">=20.0.0"
|
|
47
47
|
},
|
|
48
48
|
"volta": {
|
|
49
49
|
"extends": "../../../package.json"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "871213620dec8ff886be421339f1e90e86dbee96"
|
|
52
52
|
}
|