@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.
@@ -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 viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => (0, import_instrumentation.getTracer)().trace({
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, pendingViewDefCacheKey, renderOptions)));
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__${Date.now()}`;
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
- const linkedMetadata2 = skipMetadataCollection ? renderedViewMetadata : (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
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?.message) {
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?.message));
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.LwrApplicationError(import_diagnostics.descriptions.APPLICATION.PRELOAD_MODULE(specifier));
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, debugMessage) {
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
- debug && debugMessage && `console.error(${JSON.stringify(debugMessage)});`
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?.message) {
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?.message));
255
+ }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
256
256
  }
257
257
  if (!isAMD && hmrEnabled) {
258
258
  configResources.unshift((0, import_utils2.getViewHmrConfigurationResource)(view, viewMetadata));
@@ -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) => {
@@ -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, isRelative, } from '@lwrjs/shared-utils';
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 viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => getTracer().trace({
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, pendingViewDefCacheKey, renderOptions)));
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__${Date.now()}`;
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
- const linkedMetadata = skipMetadataCollection
354
- ? renderedViewMetadata
355
- : extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
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?.message) {
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?.message));
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 { LwrApplicationError, descriptions, logger } from '@lwrjs/diagnostics';
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 LwrApplicationError(descriptions.APPLICATION.PRELOAD_MODULE(specifier));
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, debugMessage?: string): ResourceDefinition;
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, debugMessage) {
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
- debug && debugMessage && `console.error(${JSON.stringify(debugMessage)});`,
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?.message) {
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?.message));
285
+ }, runtimeEnvironment, runtimeParams, serverDebug?.warnings));
286
286
  }
287
287
  if (!isAMD && hmrEnabled) {
288
288
  configResources.unshift(getViewHmrConfigurationResource(view, viewMetadata));
@@ -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, status, }: RenderingResult): NormalizedRenderingResult;
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, status, }) {
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.2",
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.2",
37
- "@lwrjs/diagnostics": "0.17.2-alpha.2",
38
- "@lwrjs/instrumentation": "0.17.2-alpha.2",
39
- "@lwrjs/shared-utils": "0.17.2-alpha.2",
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.2"
43
+ "@lwrjs/types": "0.17.2-alpha.20"
44
44
  },
45
45
  "engines": {
46
- "node": ">=18.0.0"
46
+ "node": ">=20.0.0"
47
47
  },
48
48
  "volta": {
49
49
  "extends": "../../../package.json"
50
50
  },
51
- "gitHead": "739b237f5d7f2c1989142cb505a56cc763f21976"
51
+ "gitHead": "871213620dec8ff886be421339f1e90e86dbee96"
52
52
  }