@lwrjs/view-registry 0.17.2-alpha.8 → 0.17.2

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.
@@ -27,6 +27,7 @@ __export(exports, {
27
27
  LwrViewHandler: () => import_view_handler.LwrViewHandler,
28
28
  LwrViewRegistry: () => LwrViewRegistry
29
29
  });
30
+ var import_config = __toModule(require("@lwrjs/config"));
30
31
  var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
31
32
  var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
32
33
  var import_utils = __toModule(require("./utils.cjs"));
@@ -41,7 +42,6 @@ var LwrViewRegistry = class {
41
42
  this.compiledViews = new Map();
42
43
  this.immutableAssets = new Map();
43
44
  this.pendingViewDefinitions = new import_shared_utils.InflightTasks();
44
- this.metadataCache = new Map();
45
45
  this.name = "lwr-view-registry";
46
46
  this.resourceRegistry = context.resourceRegistry;
47
47
  this.runtimeEnvironment = context.runtimeEnvironment;
@@ -59,6 +59,12 @@ var LwrViewRegistry = class {
59
59
  import_diagnostics.logger.verbose(`View evicted from cache ${key}`);
60
60
  }
61
61
  });
62
+ this.metadataCache = new import_lru_cache.LRUCache({
63
+ max: parseInt(process.env.VIEW_METADATA_CACHE_SIZE ?? "500", 10),
64
+ dispose: (_value, key) => {
65
+ import_diagnostics.logger.verbose(`Metadata evicted from cache ${key}`);
66
+ }
67
+ });
62
68
  observer.onViewSourceChange(({payload}) => this.onViewSourceChange(payload));
63
69
  observer.onModuleDefinitionChange(({payload}) => this.onModuleDefinitionChange(payload));
64
70
  observer.onAssetSourceChange(({payload}) => this.onAssetSourceChange(payload));
@@ -189,13 +195,14 @@ var LwrViewRegistry = class {
189
195
  const updatableViewParams = {...viewParams};
190
196
  (0, import_utils.generateViewNonce)(updatableViewParams);
191
197
  const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
192
- const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => (0, import_instrumentation.getTracer)().trace({
198
+ const pendingViewDefCacheKeyHashed = (0, import_crypto.createHash)("md5").update(pendingViewDefCacheKey).digest("hex");
199
+ const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKeyHashed, () => (0, import_instrumentation.getTracer)().trace({
193
200
  name: import_instrumentation.ViewSpan.RenderView,
194
201
  attributes: {
195
202
  view: view.id,
196
203
  ssr: view.bootstrap?.ssr === true
197
204
  }
198
- }, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKey, renderOptions)));
205
+ }, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKeyHashed, renderOptions)));
199
206
  viewDefinition.nonce = (0, import_utils.getViewNonce)(updatableViewParams);
200
207
  const route = this.globalConfig.routes.find((r) => r.id === view.id);
201
208
  const maxViewCacheTtl = (0, import_shared_utils.getFeatureFlags)().MAX_VIEW_CACHE_TTL;
@@ -219,9 +226,14 @@ var LwrViewRegistry = class {
219
226
  throw new import_diagnostics.LwrServerError(import_diagnostics.descriptions.SERVER.UNEXPECTED_ERROR(message));
220
227
  }
221
228
  }
229
+ getLwrResourcesPlaceHolder(view, runtimeEnvironment, runtimeParams) {
230
+ const resourcesCacheKey = (0, import_utils.getViewDefCacheKey)(view, runtimeEnvironment, true, runtimeParams);
231
+ const resourcesCacheKeyHashed = (0, import_crypto.createHash)("md5").update(resourcesCacheKey).digest("hex");
232
+ return `__LWR_RESOURCES__${view.id}${resourcesCacheKeyHashed}`;
233
+ }
222
234
  async renderView(view, viewParams, runtimeEnvironment, runtimeParams, viewCacheKey, renderOptions) {
223
235
  const {id, contentTemplate, rootComponent, layoutTemplate} = view;
224
- const lwrResourcesId = `__LWR_RESOURCES__${Date.now()}`;
236
+ const lwrResourcesId = this.getLwrResourcesPlaceHolder(view, runtimeEnvironment, runtimeParams);
225
237
  const renderedContent = await this.render({id, contentTemplate, rootComponent}, {...viewParams, lwr_resources: lwrResourcesId}, runtimeParams, runtimeEnvironment);
226
238
  let normalizedRenderOptions = (0, import_utils.normalizeRenderOptions)(this.runtimeEnvironment, renderedContent.options, renderOptions);
227
239
  const layout = layoutTemplate || renderedContent.compiledView.layoutTemplate;
@@ -316,32 +328,59 @@ var LwrViewRegistry = class {
316
328
  const {lwrResourcesId} = contentIds;
317
329
  const {moduleRegistry, resourceRegistry, moduleBundler} = this;
318
330
  const runtimeEnvironment = {...runtimeEnv, immutableAssets: freezeAssets};
331
+ const isSSR = view.bootstrap?.ssr === true;
319
332
  const {
320
333
  renderedView: renderedViewContent,
321
334
  metadata: renderedViewMetadata,
322
335
  compiledView: {immutable = true}
323
336
  } = renderedView;
337
+ let traceId;
324
338
  const {linkedMetadata, stringBuilder} = (0, import_instrumentation.getTracer)().trace({
325
339
  name: import_instrumentation.ViewSpan.ParseView,
326
340
  attributes: {
327
341
  view: view.id,
328
- ssr: view.bootstrap?.ssr === true
329
- }
330
- }, () => {
331
- let linkedMetadata2 = renderedViewMetadata;
332
- if (!skipMetadataCollection) {
333
- const contentHash = (0, import_crypto.createHash)("md5").update(renderedViewContent).digest("hex");
334
- const cacheKey = `${view.id}:${contentHash}`;
335
- if (this.metadataCache.has(cacheKey)) {
336
- linkedMetadata2 = this.metadataCache.get(cacheKey);
337
- } else {
338
- linkedMetadata2 = (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
339
- this.metadataCache.set(cacheKey, linkedMetadata2);
340
- }
342
+ ssr: isSSR
341
343
  }
344
+ }, (span) => {
345
+ traceId = span.traceId;
342
346
  const stringBuilder2 = (0, import_shared_utils.createStringBuilder)(renderedViewContent);
343
- return {linkedMetadata: linkedMetadata2, stringBuilder: stringBuilder2};
347
+ if (skipMetadataCollection) {
348
+ return {linkedMetadata: renderedViewMetadata, stringBuilder: stringBuilder2};
349
+ }
350
+ const contentHash = (0, import_crypto.createHash)("md5").update(renderedViewContent).digest("hex");
351
+ const cacheKey = `${view.id}:${contentHash}`;
352
+ let metadata;
353
+ if (this.metadataCache.has(cacheKey)) {
354
+ metadata = this.metadataCache.get(cacheKey);
355
+ } else {
356
+ metadata = (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
357
+ this.metadataCache.set(cacheKey, metadata);
358
+ }
359
+ return {
360
+ linkedMetadata: {
361
+ ...renderedViewMetadata,
362
+ customElements: metadata.customElements,
363
+ assetReferences: metadata.assetReferences
364
+ },
365
+ stringBuilder: stringBuilder2
366
+ };
344
367
  });
368
+ if (!(0, import_shared_utils.getFeatureFlags)().DISABLE_B3_TRACING && traceId && runtimeParams.viewSpanID) {
369
+ const content = `00-${traceId}-${runtimeParams.viewSpanID}-01`;
370
+ (0, import_shared_utils.addHeadMarkup)([{meta: [{name: "traceparent", content}]}], stringBuilder);
371
+ }
372
+ if (isSSR && (0, import_shared_utils.getFeatureFlags)().SSR_COMPILER_ENABLED) {
373
+ const ssrUtils = await resourceRegistry.getResource({specifier: "register-lwc-style.js", version: import_config.LWC_VERSION}, runtimeEnvironment, runtimeParams);
374
+ if (!ssrUtils?.src) {
375
+ } else {
376
+ (0, import_shared_utils.addToHead)(await (0, import_utils.generateHtmlTag)(ssrUtils), stringBuilder);
377
+ linkedMetadata.assetReferences.push({
378
+ url: ssrUtils.src,
379
+ relative: (0, import_shared_utils.isRelative)(ssrUtils.src),
380
+ integrity: ssrUtils.integrity
381
+ });
382
+ }
383
+ }
345
384
  const mergedViewContext = {
346
385
  ...viewContext,
347
386
  config: this.globalConfig,
@@ -373,23 +412,24 @@ var LwrViewRegistry = class {
373
412
  unsafeEnableViewLinkCaching: this.globalConfig.unsafeEnableViewLinkCaching,
374
413
  viewLinkCacheKey: viewCacheKey
375
414
  });
415
+ const assetReferences = [...linkedMetadata.assetReferences];
376
416
  if (viewRecord.resources?.length) {
377
- linkedMetadata.assetReferences.push(...viewRecord.resources.reduce((res, asset) => {
378
- if (!asset.src)
379
- return res;
380
- res.push({
381
- url: asset.src,
382
- relative: (0, import_shared_utils.isRelative)(asset.src),
383
- integrity: asset.integrity
417
+ for (const resource of viewRecord.resources) {
418
+ if (!resource.src) {
419
+ continue;
420
+ }
421
+ assetReferences.push({
422
+ url: resource.src,
423
+ relative: (0, import_shared_utils.isRelative)(resource.src),
424
+ integrity: resource.integrity
384
425
  });
385
- return res;
386
- }, []));
426
+ }
387
427
  }
388
428
  return {
389
429
  renderedView: linkedView,
390
430
  immutable,
391
431
  viewRecord: {
392
- assetReferences: (0, import_utils.reduceSourceAssetReferences)(linkedMetadata.assetReferences),
432
+ assetReferences: (0, import_utils.reduceSourceAssetReferences)(assetReferences),
393
433
  ...viewRecord,
394
434
  serverBundles: linkedMetadata.serverBundles
395
435
  },
@@ -110,6 +110,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
110
110
  const viewPreloads = {
111
111
  uris: [],
112
112
  specifiers: [],
113
+ includedModules: [],
113
114
  groups: new Map(),
114
115
  integrities: new Map()
115
116
  };
@@ -157,6 +158,10 @@ async function getHtmlResources(view, viewParams, resourceContext) {
157
158
  if (enableModuleGraphsCache && moduleGraphsCache.has(bootstrapModuleGraphCacheKey)) {
158
159
  bootstrapModuleGraph = moduleGraphsCache.get(bootstrapModuleGraphCacheKey);
159
160
  } else {
161
+ import_diagnostics.logger.info({
162
+ label: "view-registry",
163
+ message: `Cache miss for ServerGenerate, cache key: ${bootstrapModuleGraphCacheKey}`
164
+ });
160
165
  bootstrapModuleGraph = await (0, import_shared_utils.getModuleGraphs)(bootstrapSpecifier, {includeUris: true, includeLinkedDefinitions: true, depth}, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
161
166
  enableModuleGraphsCache && moduleGraphsCache.set(bootstrapModuleGraphCacheKey, bootstrapModuleGraph);
162
167
  }
@@ -227,7 +232,9 @@ async function getHtmlResources(view, viewParams, resourceContext) {
227
232
  const specifier = graph.graphs[0].specifier;
228
233
  const uri = graph.uriMap[specifier];
229
234
  const integrity = (0, import_utils2.getBundleIntegrity)(graph, specifier);
230
- (0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, integrity, groups, viewPreloads);
235
+ const bundleDef = graph.linkedDefinitions[specifier];
236
+ const includedModules = bundleDef?.bundleRecord ? bundleDef.bundleRecord.includedModules : [];
237
+ (0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, integrity, groups, viewPreloads, includedModules);
231
238
  if (bundle) {
232
239
  for (const depSpecifier of graph.graphs[0].static) {
233
240
  const depUri = getPreloadUri(depSpecifier, graph.uriMap);
@@ -277,7 +284,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
277
284
  rootComponents,
278
285
  serverData,
279
286
  ...isAMD && {requiredModules: requiredAmdModules},
280
- ...isAMD && {preloadModules: viewPreloads.specifiers}
287
+ ...isAMD && {preloadModules: (0, import_preload_utils.getPreloadModuleList)(viewPreloads)}
281
288
  }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
282
289
  }
283
290
  if (!isAMD && hmrEnabled) {
@@ -24,12 +24,13 @@ var __toModule = (module2) => {
24
24
  // packages/@lwrjs/view-registry/src/linkers/preload-utils.ts
25
25
  __markAsModule(exports);
26
26
  __export(exports, {
27
+ getPreloadModuleList: () => getPreloadModuleList,
27
28
  getPreloadModulesMeta: () => getPreloadModulesMeta,
28
29
  setPreloadModulesMeta: () => setPreloadModulesMeta
29
30
  });
30
31
  var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
31
32
  var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
32
- function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
33
+ function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads, includedModules = []) {
33
34
  if (!uri) {
34
35
  throw new import_diagnostics.LwrInvalidError(import_diagnostics.descriptions.INVALID.PRELOAD_MODULE(specifier));
35
36
  }
@@ -40,6 +41,7 @@ function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
40
41
  const preloadBundleGroupsMap = preloads.groups;
41
42
  const preloadModulesURIs = preloads.uris;
42
43
  const preloadModuleIntegrities = preloads.integrities;
44
+ const preloadModuleIncludedModules = preloads.includedModules;
43
45
  preloadModulesSpecifiers.push(specifier);
44
46
  const {specifier: unversionedSpecifier} = (0, import_shared_utils.explodeSpecifier)(specifier);
45
47
  const groupName = (0, import_shared_utils.getGroupName)(unversionedSpecifier, groups);
@@ -49,6 +51,7 @@ function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
49
51
  preloadModulesURIs.push(uri);
50
52
  groupName && preloadBundleGroupsMap.set(groupName, true);
51
53
  preloadModuleIntegrities.set(uri, integrity);
54
+ preloadModuleIncludedModules.push(...includedModules);
52
55
  }
53
56
  async function getPreloadModulesMeta(specifier, viewPreloads, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, pending) {
54
57
  const {exclude = [], external = {}, groups = {}} = bundleConfig;
@@ -92,3 +95,8 @@ async function getPreloadModulesMeta(specifier, viewPreloads, bundleConfig, modu
92
95
  }
93
96
  }
94
97
  }
98
+ function getPreloadModuleList(viewPreloads) {
99
+ if (process.env.PRELOAD_INCLUDED_MODULES === "true")
100
+ return [...new Set(viewPreloads.specifiers), ...new Set(viewPreloads.includedModules)];
101
+ return [...new Set(viewPreloads.specifiers)];
102
+ }
@@ -52,6 +52,7 @@ function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironm
52
52
  };
53
53
  const lwrEnv = {
54
54
  SSR: false,
55
+ SSREnabled: !!viewInfo.ssr,
55
56
  ...(0, import_shared_utils.buildEnvironmentContext)(runtimeParams)
56
57
  };
57
58
  let warnMessages = `console.group('Server-side rendering warnings:');`;
@@ -100,6 +100,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
100
100
  const viewPreloads = {
101
101
  uris: [],
102
102
  specifiers: [],
103
+ includedModules: [],
103
104
  groups: new Map(),
104
105
  integrities: new Map()
105
106
  };
@@ -209,7 +210,9 @@ async function getHtmlResources(view, viewParams, resourceContext) {
209
210
  const specifier = graph.graphs[0].specifier;
210
211
  const uri = graph.uriMap[specifier];
211
212
  const integrity = (0, import_utils2.getBundleIntegrity)(graph, specifier);
212
- (0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, integrity, groups, viewPreloads);
213
+ const bundleDef = graph.linkedDefinitions[specifier];
214
+ const includedModules = bundleDef?.bundleRecord ? bundleDef.bundleRecord.includedModules : [];
215
+ (0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, integrity, groups, viewPreloads, includedModules);
213
216
  if (bundle) {
214
217
  for (const depSpecifier of graph.graphs[0].static) {
215
218
  const depUri = getPreloadUri(depSpecifier, graph.uriMap);
@@ -251,7 +254,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
251
254
  rootComponents,
252
255
  serverData,
253
256
  ...isAMD && {requiredModules: requiredAmdModules},
254
- ...isAMD && {preloadModules: viewPreloads.specifiers}
257
+ ...isAMD && {preloadModules: (0, import_preload_utils.getPreloadModuleList)(viewPreloads)}
255
258
  }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
256
259
  }
257
260
  if (!isAMD && hmrEnabled) {
@@ -45,6 +45,7 @@ export declare class LwrViewRegistry implements ViewRegistry {
45
45
  getView(viewId: ViewIdentity): Promise<CompiledView>;
46
46
  hasViewDefinition(view: View, viewParams: ViewParams, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams, renderOptions?: RenderOptions): boolean;
47
47
  getViewDefinition(view: View, viewParams: ViewParams, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams, renderOptions?: RenderOptions): Promise<LinkedViewDefinition>;
48
+ private getLwrResourcesPlaceHolder;
48
49
  private renderView;
49
50
  private render;
50
51
  private metadataCache;
package/build/es/index.js CHANGED
@@ -1,6 +1,7 @@
1
- import { InflightTasks, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getFeatureFlags, getSpecifier, isLocalDev, normalizeResourcePath, shortestTtl, isRelative, } from '@lwrjs/shared-utils';
1
+ import { LWC_VERSION } from '@lwrjs/config';
2
+ import { InflightTasks, addHeadMarkup, addToHead, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getFeatureFlags, getSpecifier, isLocalDev, isRelative, normalizeResourcePath, shortestTtl, } from '@lwrjs/shared-utils';
2
3
  import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
3
- import { generateViewNonce, getViewNonce, normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences, getViewDefCacheKey, } from './utils.js';
4
+ import { generateHtmlTag, generateViewNonce, getViewDefCacheKey, getViewNonce, normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences, } from './utils.js';
4
5
  import { linkLwrResources } from './linkers/link-lwr-resources.js';
5
6
  // TODO: investigate perf impact W-16056356
6
7
  import { LRUCache } from 'lru-cache';
@@ -8,19 +9,31 @@ import { createHash } from 'crypto';
8
9
  import { LwrError, LwrServerError, descriptions, logger } from '@lwrjs/diagnostics';
9
10
  export { LwrViewHandler } from './view-handler.js';
10
11
  export class LwrViewRegistry {
12
+ name;
13
+ viewProviders = [];
14
+ // Cache of compiled views retrieved from the viewProviders
15
+ // Cache key: ViewIdentity
16
+ compiledViews = new Map();
17
+ // Cache of linked view definitions, keyed by the View
18
+ // Cache key: View
19
+ viewDefinitions;
20
+ resourceRegistry;
21
+ moduleRegistry;
22
+ moduleBundler;
23
+ assetRegistry;
24
+ globalConfig;
25
+ appEmitter;
26
+ globalData;
27
+ runtimeEnvironment;
28
+ immutableAssets = new Map();
29
+ viewTransformers;
30
+ // Cache of unresolved view definitions
31
+ // Cache key: View + View Params
32
+ //
33
+ // Pending view definitions are tracked to prevent concurrent resolution of the same view.
34
+ // Subsequent requests for the same view will await the original promise.
35
+ pendingViewDefinitions = new InflightTasks();
11
36
  constructor(context, globalConfig) {
12
- this.viewProviders = [];
13
- // Cache of compiled views retrieved from the viewProviders
14
- // Cache key: ViewIdentity
15
- this.compiledViews = new Map();
16
- this.immutableAssets = new Map();
17
- // Cache of unresolved view definitions
18
- // Cache key: View + View Params
19
- //
20
- // Pending view definitions are tracked to prevent concurrent resolution of the same view.
21
- // Subsequent requests for the same view will await the original promise.
22
- this.pendingViewDefinitions = new InflightTasks();
23
- this.metadataCache = new Map();
24
37
  this.name = 'lwr-view-registry';
25
38
  this.resourceRegistry = context.resourceRegistry;
26
39
  this.runtimeEnvironment = context.runtimeEnvironment;
@@ -39,6 +52,12 @@ export class LwrViewRegistry {
39
52
  logger.verbose(`View evicted from cache ${key}`);
40
53
  },
41
54
  });
55
+ this.metadataCache = new LRUCache({
56
+ max: parseInt(process.env.VIEW_METADATA_CACHE_SIZE ?? '500', 10),
57
+ dispose: (_value, key) => {
58
+ logger.verbose(`Metadata evicted from cache ${key}`);
59
+ },
60
+ });
42
61
  // Observers for cached entries external dependencies -- view templates, modules, and assets
43
62
  observer.onViewSourceChange(({ payload }) => this.onViewSourceChange(payload));
44
63
  observer.onModuleDefinitionChange(({ payload }) => this.onModuleDefinitionChange(payload));
@@ -196,13 +215,16 @@ export class LwrViewRegistry {
196
215
  const updatableViewParams = { ...viewParams };
197
216
  generateViewNonce(updatableViewParams);
198
217
  const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
199
- const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => getTracer().trace({
218
+ const pendingViewDefCacheKeyHashed = createHash('md5')
219
+ .update(pendingViewDefCacheKey)
220
+ .digest('hex');
221
+ const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKeyHashed, () => getTracer().trace({
200
222
  name: ViewSpan.RenderView,
201
223
  attributes: {
202
224
  view: view.id,
203
225
  ssr: view.bootstrap?.ssr === true,
204
226
  },
205
- }, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKey, renderOptions)));
227
+ }, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, pendingViewDefCacheKeyHashed, renderOptions)));
206
228
  // Once the view is generated add the nonce to the response so it can be cached and then added to the headers
207
229
  viewDefinition.nonce = getViewNonce(updatableViewParams);
208
230
  const route = this.globalConfig.routes.find((r) => r.id === view.id);
@@ -236,9 +258,17 @@ export class LwrViewRegistry {
236
258
  throw new LwrServerError(descriptions.SERVER.UNEXPECTED_ERROR(message));
237
259
  }
238
260
  }
261
+ getLwrResourcesPlaceHolder(view, runtimeEnvironment, runtimeParams) {
262
+ // Unlike the view definiton cache key which is a lot more open ended, we only
263
+ // need this cache key to vary for critical items like ?debug, locale, basePath, etc
264
+ // Note: hardcoding freeze assets here because it shouldn't matter for this key.
265
+ const resourcesCacheKey = getViewDefCacheKey(view, runtimeEnvironment, true, runtimeParams);
266
+ const resourcesCacheKeyHashed = createHash('md5').update(resourcesCacheKey).digest('hex');
267
+ return `__LWR_RESOURCES__${view.id}${resourcesCacheKeyHashed}`;
268
+ }
239
269
  async renderView(view, viewParams, runtimeEnvironment, runtimeParams, viewCacheKey, renderOptions) {
240
270
  const { id, contentTemplate, rootComponent, layoutTemplate } = view;
241
- const lwrResourcesId = `__LWR_RESOURCES__${Date.now()}`;
271
+ const lwrResourcesId = this.getLwrResourcesPlaceHolder(view, runtimeEnvironment, runtimeParams);
242
272
  const renderedContent = await this.render({ id, contentTemplate, rootComponent }, { ...viewParams, lwr_resources: lwrResourcesId }, runtimeParams, runtimeEnvironment);
243
273
  // normalize the renderOptions provided by the CompiledView content with the request options.
244
274
  let normalizedRenderOptions = normalizeRenderOptions(this.runtimeEnvironment, renderedContent.options, renderOptions);
@@ -339,37 +369,71 @@ export class LwrViewRegistry {
339
369
  ...normalizedResult,
340
370
  };
341
371
  }
372
+ metadataCache;
342
373
  async link(renderedView, viewContext) {
343
374
  const { view, viewParams, runtimeEnvironment: runtimeEnv, runtimeParams, renderOptions, contentIds, importer, viewCacheKey, } = viewContext;
344
375
  const { skipMetadataCollection, freezeAssets } = renderOptions;
345
376
  const { lwrResourcesId } = contentIds;
346
377
  const { moduleRegistry, resourceRegistry, moduleBundler } = this;
347
378
  const runtimeEnvironment = { ...runtimeEnv, immutableAssets: freezeAssets };
379
+ const isSSR = view.bootstrap?.ssr === true;
348
380
  // normalize/extract metadata
349
381
  const { renderedView: renderedViewContent, metadata: renderedViewMetadata, compiledView: { immutable = true }, } = renderedView;
382
+ let traceId;
350
383
  const { linkedMetadata, stringBuilder } = getTracer().trace({
351
384
  name: ViewSpan.ParseView,
352
385
  attributes: {
353
386
  view: view.id,
354
- ssr: view.bootstrap?.ssr === true,
387
+ ssr: isSSR,
355
388
  },
356
- }, () => {
357
- let linkedMetadata = renderedViewMetadata;
358
- if (!skipMetadataCollection) {
359
- // Create a unique key based on view ID and content hash
360
- const contentHash = createHash('md5').update(renderedViewContent).digest('hex');
361
- const cacheKey = `${view.id}:${contentHash}`;
362
- if (this.metadataCache.has(cacheKey)) {
363
- linkedMetadata = this.metadataCache.get(cacheKey);
364
- }
365
- else {
366
- linkedMetadata = extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
367
- this.metadataCache.set(cacheKey, linkedMetadata);
368
- }
369
- }
389
+ }, (span) => {
390
+ traceId = span.traceId;
370
391
  const stringBuilder = createStringBuilder(renderedViewContent);
371
- return { linkedMetadata, stringBuilder };
392
+ if (skipMetadataCollection) {
393
+ return { linkedMetadata: renderedViewMetadata, stringBuilder };
394
+ }
395
+ // Create a unique key based on view ID and content hash
396
+ const contentHash = createHash('md5').update(renderedViewContent).digest('hex');
397
+ const cacheKey = `${view.id}:${contentHash}`;
398
+ let metadata;
399
+ if (this.metadataCache.has(cacheKey)) {
400
+ metadata = this.metadataCache.get(cacheKey);
401
+ }
402
+ else {
403
+ metadata = extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
404
+ this.metadataCache.set(cacheKey, metadata);
405
+ }
406
+ return {
407
+ linkedMetadata: {
408
+ ...renderedViewMetadata,
409
+ customElements: metadata.customElements,
410
+ assetReferences: metadata.assetReferences,
411
+ },
412
+ stringBuilder,
413
+ };
372
414
  });
415
+ // Add distributed tracing meta tag to pass tracing info to the client
416
+ // {version}-{traceId}-{spanId}-{sampleDecision} and version is always 00
417
+ if (!getFeatureFlags().DISABLE_B3_TRACING && traceId && runtimeParams.viewSpanID) {
418
+ const content = `00-${traceId}-${runtimeParams.viewSpanID}-01`;
419
+ addHeadMarkup([{ meta: [{ name: 'traceparent', content }] }], stringBuilder);
420
+ }
421
+ // If the SSR compiler is enabled then inline the @lwc/ssr-client-utils/register-lwc-style script for style de-duplication
422
+ // re-enable logger.error below with W-18004123 after the app has integrated the register-lwc-style resource
423
+ if (isSSR && getFeatureFlags().SSR_COMPILER_ENABLED) {
424
+ const ssrUtils = await resourceRegistry.getResource({ specifier: 'register-lwc-style.js', version: LWC_VERSION }, runtimeEnvironment, runtimeParams);
425
+ if (!ssrUtils?.src) {
426
+ // logger.error('Failed to find script: register-lwc-style.js');
427
+ }
428
+ else {
429
+ addToHead(await generateHtmlTag(ssrUtils), stringBuilder);
430
+ linkedMetadata.assetReferences.push({
431
+ url: ssrUtils.src,
432
+ relative: isRelative(ssrUtils.src),
433
+ integrity: ssrUtils.integrity,
434
+ });
435
+ }
436
+ }
373
437
  const mergedViewContext = {
374
438
  ...viewContext,
375
439
  config: this.globalConfig,
@@ -408,24 +472,25 @@ export class LwrViewRegistry {
408
472
  // Use the same cache key for the link stage
409
473
  viewLinkCacheKey: viewCacheKey,
410
474
  });
475
+ const assetReferences = [...linkedMetadata.assetReferences];
411
476
  if (viewRecord.resources?.length) {
412
- linkedMetadata.assetReferences.push(...viewRecord.resources.reduce((res, asset) => {
413
- if (!asset.src)
414
- return res;
415
- res.push({
416
- url: asset.src,
417
- relative: isRelative(asset.src),
418
- integrity: asset.integrity,
477
+ for (const resource of viewRecord.resources) {
478
+ if (!resource.src) {
479
+ continue;
480
+ }
481
+ assetReferences.push({
482
+ url: resource.src,
483
+ relative: isRelative(resource.src),
484
+ integrity: resource.integrity,
419
485
  });
420
- return res;
421
- }, []));
486
+ }
422
487
  }
423
488
  return {
424
489
  // ...viewDefinition,
425
490
  renderedView: linkedView,
426
491
  immutable,
427
492
  viewRecord: {
428
- assetReferences: reduceSourceAssetReferences(linkedMetadata.assetReferences),
493
+ assetReferences: reduceSourceAssetReferences(assetReferences),
429
494
  ...viewRecord,
430
495
  serverBundles: linkedMetadata.serverBundles,
431
496
  },
@@ -3,7 +3,7 @@ import { kebabCaseToModuleSpecifier, getModuleGraphs, GraphDepth, getModuleUriPr
3
3
  import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
4
4
  import { addExternalScriptNonce, generateHtmlTag, getModuleResource, getModuleResourceByUri, getViewNonce, getModuleGraphCacheKey, } from '../utils.js';
5
5
  import { flattenCustomElements, getBundleIntegrity, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
6
- import { setPreloadModulesMeta, getPreloadModulesMeta } from './preload-utils.js';
6
+ import { setPreloadModulesMeta, getPreloadModulesMeta, getPreloadModuleList, } from './preload-utils.js';
7
7
  import { LRUCache } from 'lru-cache';
8
8
  function includeIdFactory(bundleConfig) {
9
9
  return (moduleRef) => {
@@ -103,6 +103,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
103
103
  const viewPreloads = {
104
104
  uris: [],
105
105
  specifiers: [],
106
+ includedModules: [],
106
107
  groups: new Map(),
107
108
  integrities: new Map(),
108
109
  };
@@ -174,6 +175,10 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
174
175
  bootstrapModuleGraph = moduleGraphsCache.get(bootstrapModuleGraphCacheKey);
175
176
  }
176
177
  else {
178
+ logger.info({
179
+ label: 'view-registry',
180
+ message: `Cache miss for ServerGenerate, cache key: ${bootstrapModuleGraphCacheKey}`,
181
+ });
177
182
  bootstrapModuleGraph = await getModuleGraphs(bootstrapSpecifier, { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
178
183
  enableModuleGraphsCache &&
179
184
  moduleGraphsCache.set(bootstrapModuleGraphCacheKey, bootstrapModuleGraph);
@@ -262,7 +267,9 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
262
267
  const specifier = graph.graphs[0].specifier;
263
268
  const uri = graph.uriMap[specifier];
264
269
  const integrity = getBundleIntegrity(graph, specifier);
265
- setPreloadModulesMeta(specifier, uri, integrity, groups, viewPreloads);
270
+ const bundleDef = graph.linkedDefinitions[specifier];
271
+ const includedModules = bundleDef?.bundleRecord ? bundleDef.bundleRecord.includedModules : [];
272
+ setPreloadModulesMeta(specifier, uri, integrity, groups, viewPreloads, includedModules);
266
273
  // PRELOAD custom element static deps as link resources when bundling is ON
267
274
  if (bundle) {
268
275
  for (const depSpecifier of graph.graphs[0].static) {
@@ -319,7 +326,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
319
326
  serverData,
320
327
  ...(isAMD && { requiredModules: requiredAmdModules }),
321
328
  // in AMD we need to tell the loader what modules we are preloading
322
- ...(isAMD && { preloadModules: viewPreloads.specifiers }),
329
+ ...(isAMD && { preloadModules: getPreloadModuleList(viewPreloads) }),
323
330
  }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
324
331
  }
325
332
  if (!isAMD && hmrEnabled) {
@@ -4,15 +4,17 @@ export type ViewPreloads = {
4
4
  uris: string[];
5
5
  specifiers: string[];
6
6
  integrities: Map<string, string | undefined>;
7
+ includedModules: string[];
7
8
  };
8
9
  /**
9
10
  * keeps track of preloadModules metadata
10
11
  */
11
- export declare function setPreloadModulesMeta(specifier: string, uri: string, integrity: string | undefined, groups: BundleGroups, preloads: ViewPreloads): void;
12
+ export declare function setPreloadModulesMeta(specifier: string, uri: string, integrity: string | undefined, groups: BundleGroups, preloads: ViewPreloads, includedModules?: string[]): void;
12
13
  /**
13
14
  * Recursively gets preloadModules metadata starting with a specifier
14
15
  * Note: don't call me unless you got bundles
15
16
  */
16
17
  export declare function getPreloadModulesMeta(specifier: string, // un-versioned specifier
17
18
  viewPreloads: ViewPreloads, bundleConfig: BundleConfig, moduleRegistry: ModuleRegistry, defRegistry: ModuleBundler, runtimeEnvironment: RuntimeEnvironment, runtimeParams: RuntimeParams, pending?: Map<string, boolean>): Promise<void>;
19
+ export declare function getPreloadModuleList(viewPreloads: ViewPreloads): string[];
18
20
  //# sourceMappingURL=preload-utils.d.ts.map
@@ -3,7 +3,7 @@ import { explodeSpecifier, getGroupName, getVersionedModuleId, normalizeVersionT
3
3
  /**
4
4
  * keeps track of preloadModules metadata
5
5
  */
6
- export function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads) {
6
+ export function setPreloadModulesMeta(specifier, uri, integrity, groups, preloads, includedModules = []) {
7
7
  // Throw a very specific error if we get this back and the uri property is not set
8
8
  if (!uri) {
9
9
  throw new LwrInvalidError(descriptions.INVALID.PRELOAD_MODULE(specifier));
@@ -19,6 +19,7 @@ export function setPreloadModulesMeta(specifier, uri, integrity, groups, preload
19
19
  const preloadBundleGroupsMap = preloads.groups;
20
20
  const preloadModulesURIs = preloads.uris;
21
21
  const preloadModuleIntegrities = preloads.integrities;
22
+ const preloadModuleIncludedModules = preloads.includedModules;
22
23
  preloadModulesSpecifiers.push(specifier);
23
24
  const { specifier: unversionedSpecifier } = explodeSpecifier(specifier);
24
25
  const groupName = getGroupName(unversionedSpecifier, groups);
@@ -29,6 +30,7 @@ export function setPreloadModulesMeta(specifier, uri, integrity, groups, preload
29
30
  preloadModulesURIs.push(uri);
30
31
  groupName && preloadBundleGroupsMap.set(groupName, true);
31
32
  preloadModuleIntegrities.set(uri, integrity);
33
+ preloadModuleIncludedModules.push(...includedModules);
32
34
  }
33
35
  /**
34
36
  * Recursively gets preloadModules metadata starting with a specifier
@@ -85,4 +87,9 @@ viewPreloads, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, run
85
87
  }
86
88
  }
87
89
  }
90
+ export function getPreloadModuleList(viewPreloads) {
91
+ if (process.env.PRELOAD_INCLUDED_MODULES === 'true')
92
+ return [...new Set(viewPreloads.specifiers), ...new Set(viewPreloads.includedModules)];
93
+ return [...new Set(viewPreloads.specifiers)];
94
+ }
88
95
  //# sourceMappingURL=preload-utils.js.map
@@ -25,6 +25,7 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
25
25
  const lwrEnv = {
26
26
  // Note: SSR is always false because this script is executed on the client
27
27
  SSR: false,
28
+ SSREnabled: !!viewInfo.ssr,
28
29
  // Used by `lwr/environment`
29
30
  ...buildEnvironmentContext(runtimeParams),
30
31
  };
@@ -5,7 +5,7 @@ import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
5
5
  import { addExternalScriptNonce, generateHtmlTag, getModuleResourceByUri, getViewNonce } from '../utils.js';
6
6
  import { flattenCustomElements, getBundleIntegrity, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
7
7
  import { getModuleGraphCacheKey } from '../utils.js';
8
- import { setPreloadModulesMeta, getPreloadModulesMeta } from './preload-utils.js';
8
+ import { setPreloadModulesMeta, getPreloadModulesMeta, getPreloadModuleList, } from './preload-utils.js';
9
9
  // `getModuleGraphs` is very expensive and does not need to be recomputed every time.
10
10
  // Note: we use the same cache key passed in from the top level view-registry for consistency
11
11
  const moduleGraphsCache = new LRUCache({
@@ -87,6 +87,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
87
87
  const viewPreloads = {
88
88
  uris: [],
89
89
  specifiers: [],
90
+ includedModules: [],
90
91
  groups: new Map(),
91
92
  integrities: new Map(),
92
93
  };
@@ -232,7 +233,9 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
232
233
  const specifier = graph.graphs[0].specifier;
233
234
  const uri = graph.uriMap[specifier];
234
235
  const integrity = getBundleIntegrity(graph, specifier);
235
- setPreloadModulesMeta(specifier, uri, integrity, groups, viewPreloads);
236
+ const bundleDef = graph.linkedDefinitions[specifier];
237
+ const includedModules = bundleDef?.bundleRecord ? bundleDef.bundleRecord.includedModules : [];
238
+ setPreloadModulesMeta(specifier, uri, integrity, groups, viewPreloads, includedModules);
236
239
  // PRELOAD custom element static deps as link resources when bundling is ON
237
240
  if (bundle) {
238
241
  for (const depSpecifier of graph.graphs[0].static) {
@@ -281,7 +284,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
281
284
  serverData,
282
285
  ...(isAMD && { requiredModules: requiredAmdModules }),
283
286
  // in AMD we need to tell the loader what modules we are preloading
284
- ...(isAMD && { preloadModules: viewPreloads.specifiers }),
287
+ ...(isAMD && { preloadModules: getPreloadModuleList(viewPreloads) }),
285
288
  }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
286
289
  }
287
290
  if (!isAMD && hmrEnabled) {
@@ -4,6 +4,10 @@ import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
4
4
  import { generateHtmlTag, generateLinkHeaders, generatePageContext, isViewResponse, isViewDefinitionResponse, toJsonFormat, } from './utils.js';
5
5
  import { LwrApplicationError, LwrError, descriptions } from '@lwrjs/diagnostics';
6
6
  export class LwrViewHandler {
7
+ globalConfig;
8
+ routeHandlers;
9
+ viewRegistry;
10
+ moduleRegistry;
7
11
  constructor(context, globalConfig) {
8
12
  this.globalConfig = globalConfig;
9
13
  this.routeHandlers = context.routeHandlers;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.17.2-alpha.8",
7
+ "version": "0.17.2",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -33,20 +33,21 @@
33
33
  "build": "tsc -b"
34
34
  },
35
35
  "dependencies": {
36
- "@lwrjs/app-service": "0.17.2-alpha.8",
37
- "@lwrjs/diagnostics": "0.17.2-alpha.8",
38
- "@lwrjs/instrumentation": "0.17.2-alpha.8",
39
- "@lwrjs/shared-utils": "0.17.2-alpha.8",
36
+ "@lwrjs/app-service": "0.17.2",
37
+ "@lwrjs/config": "0.17.2",
38
+ "@lwrjs/diagnostics": "0.17.2",
39
+ "@lwrjs/instrumentation": "0.17.2",
40
+ "@lwrjs/shared-utils": "0.17.2",
40
41
  "lru-cache": "^10.4.3"
41
42
  },
42
43
  "devDependencies": {
43
- "@lwrjs/types": "0.17.2-alpha.8"
44
+ "@lwrjs/types": "0.17.2"
44
45
  },
45
46
  "engines": {
46
- "node": ">=18.0.0"
47
+ "node": ">=20.0.0"
47
48
  },
48
49
  "volta": {
49
50
  "extends": "../../../package.json"
50
51
  },
51
- "gitHead": "ee1182e7d876cf92e579ee88c48b25047486b4f8"
52
+ "gitHead": "d64d8888a28da36c05e3d8d9baf51416551863a9"
52
53
  }