@lwrjs/view-registry 0.12.0-alpha.2 → 0.12.0-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 +47 -36
- package/build/cjs/linkers/legacy_view_bootstrap.cjs +17 -7
- package/build/cjs/linkers/preload-utils.cjs +3 -1
- package/build/cjs/linkers/utils.cjs +6 -3
- package/build/cjs/linkers/view_bootstrap.cjs +17 -7
- package/build/cjs/utils.cjs +4 -2
- package/build/cjs/view-handler.cjs +13 -1
- package/build/es/index.js +59 -47
- package/build/es/linkers/legacy_view_bootstrap.js +22 -8
- package/build/es/linkers/preload-utils.js +4 -2
- package/build/es/linkers/utils.js +5 -2
- package/build/es/linkers/view_bootstrap.js +19 -8
- package/build/es/utils.d.ts +1 -1
- package/build/es/utils.js +2 -1
- package/build/es/view-handler.js +14 -2
- package/package.json +8 -8
package/build/cjs/index.cjs
CHANGED
|
@@ -167,44 +167,53 @@ var LwrViewRegistry = class {
|
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
169
|
async getViewDefinition(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
170
|
+
try {
|
|
171
|
+
const {skipCaching, freezeAssets, viewParamCacheKey} = (0, import_utils.normalizeRenderOptions)(this.runtimeEnvironment, renderOptions);
|
|
172
|
+
const viewDefCacheKey = (0, import_shared_utils.getCacheKeyFromJson)({
|
|
173
|
+
...view,
|
|
174
|
+
freezeAssets,
|
|
175
|
+
locale: runtimeParams?.locale,
|
|
176
|
+
basePath: runtimeParams?.basePath,
|
|
177
|
+
debug: runtimeEnvironment.debug
|
|
178
|
+
});
|
|
179
|
+
import_diagnostics.logger.debug(`[view-registry][getViewDefinition] viewDefCacheKey=${viewDefCacheKey}`);
|
|
180
|
+
const viewParamKey = viewParamCacheKey ? (0, import_shared_utils.getCacheKeyFromJson)(viewParamCacheKey) : (0, import_shared_utils.getCacheKeyFromJson)(viewParams);
|
|
181
|
+
import_diagnostics.logger.debug(`[view-registry][getViewDefinition] viewParamKey=${viewParamKey}`);
|
|
182
|
+
const cacheDisabled = process.env.NOCACHE === "true" || skipCaching;
|
|
183
|
+
if (cacheDisabled === false && this.viewDefinitions.has(viewDefCacheKey)) {
|
|
184
|
+
const viewDefinition2 = this.viewDefinitions.get(viewDefCacheKey);
|
|
185
|
+
if (viewDefinition2 && viewDefinition2.paramKey === viewParamKey && viewDefinition2.viewDefinition.immutable) {
|
|
186
|
+
return viewDefinition2.viewDefinition;
|
|
187
|
+
}
|
|
186
188
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
189
|
+
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
190
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => (0, import_instrumentation.getTracer)().trace({
|
|
191
|
+
name: import_instrumentation.ViewSpan.RenderView,
|
|
192
|
+
attributes: {
|
|
193
|
+
view: view.id,
|
|
194
|
+
ssr: view.bootstrap?.ssr === true
|
|
195
|
+
}
|
|
196
|
+
}, () => this.renderView(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
197
|
+
if (cacheDisabled === false) {
|
|
198
|
+
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
199
|
+
const ttl = (0, import_shared_utils.shortestTtl)(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
200
|
+
if (ttl !== 0) {
|
|
201
|
+
this.viewDefinitions.set(viewDefCacheKey, {
|
|
202
|
+
view,
|
|
203
|
+
viewDefinition,
|
|
204
|
+
paramKey: viewParamKey
|
|
205
|
+
}, {ttl: ttl ? ttl * 1e3 : void 0});
|
|
206
|
+
}
|
|
194
207
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (ttl !== 0) {
|
|
200
|
-
this.viewDefinitions.set(viewDefCacheKey, {
|
|
201
|
-
view,
|
|
202
|
-
viewDefinition,
|
|
203
|
-
paramKey: viewParamKey
|
|
204
|
-
}, {ttl: ttl ? ttl * 1e3 : void 0});
|
|
208
|
+
return viewDefinition;
|
|
209
|
+
} catch (err) {
|
|
210
|
+
if (err instanceof import_diagnostics.DiagnosticsError) {
|
|
211
|
+
throw err;
|
|
205
212
|
}
|
|
213
|
+
import_diagnostics.logger.error(`Failed to get view definition "${view.id}": ${err}`);
|
|
214
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
215
|
+
throw (0, import_diagnostics.createSingleDiagnosticError)({description: import_diagnostics.descriptions.SERVER.UNEXPECTED_ERROR(message)}, import_diagnostics.LwrServerError);
|
|
206
216
|
}
|
|
207
|
-
return viewDefinition;
|
|
208
217
|
}
|
|
209
218
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams = {}, renderOptions) {
|
|
210
219
|
const {id, contentTemplate, rootComponent, layoutTemplate} = view;
|
|
@@ -254,7 +263,8 @@ var LwrViewRegistry = class {
|
|
|
254
263
|
...renderedContent.metadata.serverDebug,
|
|
255
264
|
...renderedLayout.metadata.serverDebug
|
|
256
265
|
}
|
|
257
|
-
}
|
|
266
|
+
},
|
|
267
|
+
cache: renderedContent.cache
|
|
258
268
|
}, {
|
|
259
269
|
view: {...view, layoutTemplate: layoutTemplatePath},
|
|
260
270
|
viewParams,
|
|
@@ -304,11 +314,12 @@ var LwrViewRegistry = class {
|
|
|
304
314
|
const linkedMetadata = skipMetadataCollection ? renderedViewMetadata : await (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
305
315
|
const mergedViewContext = {
|
|
306
316
|
...viewContext,
|
|
317
|
+
config: this.globalConfig,
|
|
307
318
|
runtimeEnvironment,
|
|
308
319
|
importer: importer || renderedView.compiledView.filePath
|
|
309
320
|
};
|
|
310
321
|
const stringBuilder = (0, import_shared_utils.createStringBuilder)(renderedViewContent);
|
|
311
|
-
let pageTtl;
|
|
322
|
+
let pageTtl = renderedView.cache.ttl;
|
|
312
323
|
for (const viewTransformer of this.viewTransformers) {
|
|
313
324
|
const linkResults = await viewTransformer.link?.(stringBuilder, mergedViewContext, linkedMetadata);
|
|
314
325
|
const ttl = linkResults && linkResults.cache?.ttl;
|
|
@@ -46,11 +46,21 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
46
46
|
const version = lwrVersion;
|
|
47
47
|
const isAMD = format === "amd";
|
|
48
48
|
const {bundleConfig} = resourceContext;
|
|
49
|
-
const {external = {}} = bundleConfig;
|
|
49
|
+
const {external = {}, exclude = []} = bundleConfig;
|
|
50
50
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
51
|
-
const
|
|
51
|
+
const getPreloadUri = function(rawSpecifier, uriMap) {
|
|
52
52
|
const {specifier} = (0, import_shared_utils.explodeSpecifier)(rawSpecifier);
|
|
53
|
-
|
|
53
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
54
|
+
return;
|
|
55
|
+
const uri = uriMap[rawSpecifier];
|
|
56
|
+
if (!uri && (exclude.includes(specifier) || (0, import_shared_utils.isGroupie)(specifier, groups))) {
|
|
57
|
+
import_diagnostics.logger.warn({
|
|
58
|
+
label: "view-registry",
|
|
59
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
return uri;
|
|
54
64
|
};
|
|
55
65
|
const {
|
|
56
66
|
id: appName,
|
|
@@ -127,8 +137,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
127
137
|
}
|
|
128
138
|
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR}));
|
|
129
139
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
const uri2 = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
141
|
+
if (uri2) {
|
|
132
142
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
133
143
|
}
|
|
134
144
|
}
|
|
@@ -169,8 +179,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
169
179
|
(0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, groups, viewPreloads);
|
|
170
180
|
if (bundle) {
|
|
171
181
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
const uri2 = getPreloadUri(depSpecifier, graph.uriMap);
|
|
183
|
+
if (uri2) {
|
|
174
184
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
175
185
|
}
|
|
176
186
|
}
|
|
@@ -31,7 +31,9 @@ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
|
31
31
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
32
32
|
function setPreloadModulesMeta(specifier, uri, groups, preloads) {
|
|
33
33
|
if (!uri) {
|
|
34
|
-
throw
|
|
34
|
+
throw (0, import_diagnostics.createSingleDiagnosticError)({
|
|
35
|
+
description: import_diagnostics.descriptions.UNRESOLVABLE.PRELOAD_MODULE(specifier)
|
|
36
|
+
}, import_diagnostics.LwrUnresolvableError);
|
|
35
37
|
}
|
|
36
38
|
const [removedVersion, version] = specifier.split("/v/");
|
|
37
39
|
const normalizedSpecifier = version === import_shared_utils.VERSION_NOT_PROVIDED ? removedVersion : specifier;
|
|
@@ -45,8 +45,10 @@ function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironm
|
|
|
45
45
|
},
|
|
46
46
|
...debug && {modifiers: {debug: "true"}}
|
|
47
47
|
};
|
|
48
|
-
const
|
|
49
|
-
NODE_ENV: runtimeEnvironment.serverMode
|
|
48
|
+
const nodeEnv = {
|
|
49
|
+
NODE_ENV: runtimeEnvironment.serverMode
|
|
50
|
+
};
|
|
51
|
+
const lwrEnv = {
|
|
50
52
|
SSR: false,
|
|
51
53
|
...(0, import_shared_utils.buildEnvironmentContext)(runtimeParams)
|
|
52
54
|
};
|
|
@@ -58,7 +60,8 @@ function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironm
|
|
|
58
60
|
...config,
|
|
59
61
|
endpoints
|
|
60
62
|
})});`,
|
|
61
|
-
`globalThis.
|
|
63
|
+
`globalThis.LWR = {...globalThis.LWR, env: ${JSON.stringify(lwrEnv)}};`,
|
|
64
|
+
`globalThis.process={...globalThis.process,env:{...globalThis.process?.env,...${JSON.stringify(nodeEnv)}}};`,
|
|
62
65
|
`globalThis.lwcRuntimeFlags = { ENABLE_MIXED_SHADOW_MODE: ${viewInfo.mixedMode} };`,
|
|
63
66
|
debug && debugMessage && `console.warn(${JSON.stringify(debugMessage)});`
|
|
64
67
|
].filter(Boolean).join("\n");
|
|
@@ -48,11 +48,21 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
48
48
|
const isAMD = format === "amd";
|
|
49
49
|
const depth = isAMD ? {static: import_shared_utils.GraphDepth.ALL, dynamic: 1} : {static: import_shared_utils.GraphDepth.NONE, dynamic: 1};
|
|
50
50
|
const {bundleConfig} = resourceContext;
|
|
51
|
-
const {external = {}} = bundleConfig;
|
|
51
|
+
const {external = {}, exclude = []} = bundleConfig;
|
|
52
52
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
53
|
-
const
|
|
53
|
+
const getPreloadUri = function(rawSpecifier, uriMap) {
|
|
54
54
|
const {specifier} = (0, import_shared_utils.explodeSpecifier)(rawSpecifier);
|
|
55
|
-
|
|
55
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
56
|
+
return;
|
|
57
|
+
const uri = uriMap[rawSpecifier];
|
|
58
|
+
if (!uri && (exclude.includes(specifier) || (0, import_shared_utils.isGroupie)(specifier, groups))) {
|
|
59
|
+
import_diagnostics.logger.warn({
|
|
60
|
+
label: "view-registry",
|
|
61
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
return uri;
|
|
56
66
|
};
|
|
57
67
|
const {
|
|
58
68
|
id: appName,
|
|
@@ -118,8 +128,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
118
128
|
}
|
|
119
129
|
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR}));
|
|
120
130
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
const uri2 = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
132
|
+
if (uri2) {
|
|
123
133
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
124
134
|
}
|
|
125
135
|
}
|
|
@@ -161,8 +171,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
161
171
|
(0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, groups, viewPreloads);
|
|
162
172
|
if (bundle) {
|
|
163
173
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
164
|
-
|
|
165
|
-
|
|
174
|
+
const uri2 = getPreloadUri(depSpecifier, graph.uriMap);
|
|
175
|
+
if (uri2) {
|
|
166
176
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
167
177
|
}
|
|
168
178
|
}
|
package/build/cjs/utils.cjs
CHANGED
|
@@ -87,7 +87,8 @@ async function generateHtmlTag(definition) {
|
|
|
87
87
|
function normalizeRenderedResult({
|
|
88
88
|
renderedView,
|
|
89
89
|
metadata,
|
|
90
|
-
options
|
|
90
|
+
options,
|
|
91
|
+
cache
|
|
91
92
|
}) {
|
|
92
93
|
return {
|
|
93
94
|
renderedView,
|
|
@@ -99,7 +100,8 @@ function normalizeRenderedResult({
|
|
|
99
100
|
},
|
|
100
101
|
options: {
|
|
101
102
|
skipMetadataCollection: options ? options.skipMetadataCollection : false
|
|
102
|
-
}
|
|
103
|
+
},
|
|
104
|
+
cache: cache || {}
|
|
103
105
|
};
|
|
104
106
|
}
|
|
105
107
|
function reduceSourceAssetReferences(assets) {
|
|
@@ -30,6 +30,7 @@ var import_path = __toModule(require("path"));
|
|
|
30
30
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
31
31
|
var import_instrumentation = __toModule(require("@lwrjs/instrumentation"));
|
|
32
32
|
var import_utils = __toModule(require("./utils.cjs"));
|
|
33
|
+
var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
|
|
33
34
|
var LwrViewHandler = class {
|
|
34
35
|
constructor(context, globalConfig) {
|
|
35
36
|
this.globalConfig = globalConfig;
|
|
@@ -128,6 +129,7 @@ var LwrViewHandler = class {
|
|
|
128
129
|
const {rootDir, assets, contentDir, layoutsDir} = this.globalConfig;
|
|
129
130
|
const paths = {rootDir, assets, contentDir, layoutsDir};
|
|
130
131
|
const locale = runtimeParams.locale;
|
|
132
|
+
const basePath = runtimeParams.basePath;
|
|
131
133
|
const viewApi = this.getBoundApi(viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
132
134
|
const response = await (0, import_instrumentation.getTracer)().trace({
|
|
133
135
|
name: import_instrumentation.ViewSpan.ExecuteRouteHandler,
|
|
@@ -135,7 +137,17 @@ var LwrViewHandler = class {
|
|
|
135
137
|
view: route.id,
|
|
136
138
|
route: viewRequest.requestPath
|
|
137
139
|
}
|
|
138
|
-
}, async () =>
|
|
140
|
+
}, async () => {
|
|
141
|
+
try {
|
|
142
|
+
return await routeHandlerFn({...viewRequest, locale, basePath}, {route, viewApi, ...paths}, routeHandlerOptions);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (err instanceof import_diagnostics.DiagnosticsError) {
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
148
|
+
throw (0, import_diagnostics.createSingleDiagnosticError)({description: import_diagnostics.descriptions.APPLICATION.ROUTE_HANDLER_ERROR(route.id, message)}, import_diagnostics.LwrApplicationError);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
139
151
|
return response;
|
|
140
152
|
}
|
|
141
153
|
getBoundApi(viewRequest, route, runtimeEnvironment, runtimeParams) {
|
package/build/es/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
|
|
|
3
3
|
import { normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences } from './utils.js';
|
|
4
4
|
import { linkLwrResources } from './linkers/link-lwr-resources.js';
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
6
|
-
import { logger } from '@lwrjs/diagnostics';
|
|
6
|
+
import { DiagnosticsError, LwrServerError, createSingleDiagnosticError, descriptions, logger, } from '@lwrjs/diagnostics';
|
|
7
7
|
export { LwrViewHandler } from './view-handler.js';
|
|
8
8
|
export class LwrViewRegistry {
|
|
9
9
|
constructor(context, globalConfig) {
|
|
@@ -159,55 +159,65 @@ export class LwrViewRegistry {
|
|
|
159
159
|
return false;
|
|
160
160
|
}
|
|
161
161
|
async getViewDefinition(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
viewDefinition
|
|
184
|
-
|
|
185
|
-
|
|
162
|
+
try {
|
|
163
|
+
const { skipCaching, freezeAssets, viewParamCacheKey } = normalizeRenderOptions(this.runtimeEnvironment, renderOptions);
|
|
164
|
+
const viewDefCacheKey = getCacheKeyFromJson({
|
|
165
|
+
...view,
|
|
166
|
+
freezeAssets,
|
|
167
|
+
locale: runtimeParams?.locale,
|
|
168
|
+
basePath: runtimeParams?.basePath,
|
|
169
|
+
debug: runtimeEnvironment.debug,
|
|
170
|
+
});
|
|
171
|
+
logger.debug(`[view-registry][getViewDefinition] viewDefCacheKey=${viewDefCacheKey}`);
|
|
172
|
+
// viewParams is an unbounded object and can be very large (17MB/view for developer.salesforce.com). Allowing consumers
|
|
173
|
+
// to provide a simple override avoids the excess memory / performance overhead of serializing & storing the viewParams
|
|
174
|
+
// on every request, while still reusing our caching logic.
|
|
175
|
+
const viewParamKey = viewParamCacheKey
|
|
176
|
+
? getCacheKeyFromJson(viewParamCacheKey)
|
|
177
|
+
: getCacheKeyFromJson(viewParams);
|
|
178
|
+
logger.debug(`[view-registry][getViewDefinition] viewParamKey=${viewParamKey}`);
|
|
179
|
+
const cacheDisabled = process.env.NOCACHE === 'true' || skipCaching;
|
|
180
|
+
// important: cache key does not include the unbounded viewParams
|
|
181
|
+
if (cacheDisabled === false && this.viewDefinitions.has(viewDefCacheKey)) {
|
|
182
|
+
const viewDefinition = this.viewDefinitions.get(viewDefCacheKey);
|
|
183
|
+
if (viewDefinition &&
|
|
184
|
+
viewDefinition.paramKey === viewParamKey &&
|
|
185
|
+
viewDefinition.viewDefinition.immutable) {
|
|
186
|
+
return viewDefinition.viewDefinition;
|
|
187
|
+
}
|
|
186
188
|
}
|
|
189
|
+
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
190
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => getTracer().trace({
|
|
191
|
+
name: ViewSpan.RenderView,
|
|
192
|
+
attributes: {
|
|
193
|
+
view: view.id,
|
|
194
|
+
ssr: view.bootstrap?.ssr === true,
|
|
195
|
+
},
|
|
196
|
+
}, () => this.renderView(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
197
|
+
if (cacheDisabled === false) {
|
|
198
|
+
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
199
|
+
const ttl = shortestTtl(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
200
|
+
if (ttl !== 0) {
|
|
201
|
+
// cache view definition for the shortest ttl or until it is the least recently used when ttl is undefined
|
|
202
|
+
this.viewDefinitions.set(viewDefCacheKey, {
|
|
203
|
+
view,
|
|
204
|
+
viewDefinition,
|
|
205
|
+
paramKey: viewParamKey,
|
|
206
|
+
},
|
|
207
|
+
// s -> ms
|
|
208
|
+
{ ttl: ttl ? ttl * 1000 : undefined });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return viewDefinition;
|
|
187
212
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
attributes: {
|
|
192
|
-
view: view.id,
|
|
193
|
-
ssr: view.bootstrap?.ssr === true,
|
|
194
|
-
},
|
|
195
|
-
}, () => this.renderView(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
196
|
-
if (cacheDisabled === false) {
|
|
197
|
-
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
198
|
-
const ttl = shortestTtl(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
199
|
-
if (ttl !== 0) {
|
|
200
|
-
// cache view definition for the shortest ttl or until it is the least recently used when ttl is undefined
|
|
201
|
-
this.viewDefinitions.set(viewDefCacheKey, {
|
|
202
|
-
view,
|
|
203
|
-
viewDefinition,
|
|
204
|
-
paramKey: viewParamKey,
|
|
205
|
-
},
|
|
206
|
-
// s -> ms
|
|
207
|
-
{ ttl: ttl ? ttl * 1000 : undefined });
|
|
213
|
+
catch (err) {
|
|
214
|
+
if (err instanceof DiagnosticsError) {
|
|
215
|
+
throw err;
|
|
208
216
|
}
|
|
217
|
+
logger.error(`Failed to get view definition "${view.id}": ${err}`);
|
|
218
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
219
|
+
throw createSingleDiagnosticError({ description: descriptions.SERVER.UNEXPECTED_ERROR(message) }, LwrServerError);
|
|
209
220
|
}
|
|
210
|
-
return viewDefinition;
|
|
211
221
|
}
|
|
212
222
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams = {}, renderOptions) {
|
|
213
223
|
const { id, contentTemplate, rootComponent, layoutTemplate } = view;
|
|
@@ -264,6 +274,7 @@ export class LwrViewRegistry {
|
|
|
264
274
|
...renderedLayout.metadata.serverDebug,
|
|
265
275
|
},
|
|
266
276
|
},
|
|
277
|
+
cache: renderedContent.cache,
|
|
267
278
|
},
|
|
268
279
|
// Render Content now contains a layout
|
|
269
280
|
{
|
|
@@ -318,11 +329,12 @@ export class LwrViewRegistry {
|
|
|
318
329
|
: await extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
319
330
|
const mergedViewContext = {
|
|
320
331
|
...viewContext,
|
|
332
|
+
config: this.globalConfig,
|
|
321
333
|
runtimeEnvironment,
|
|
322
334
|
importer: importer || renderedView.compiledView.filePath,
|
|
323
335
|
};
|
|
324
336
|
const stringBuilder = createStringBuilder(renderedViewContent);
|
|
325
|
-
let pageTtl;
|
|
337
|
+
let pageTtl = renderedView.cache.ttl;
|
|
326
338
|
for (const viewTransformer of this.viewTransformers) {
|
|
327
339
|
// eslint-disable-next-line no-await-in-loop
|
|
328
340
|
const linkResults = await viewTransformer.link?.(stringBuilder, mergedViewContext, linkedMetadata);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logger } from '@lwrjs/diagnostics';
|
|
2
|
-
import { kebabCaseToModuleSpecifier, getModuleGraphs, GraphDepth, getModuleUriPrefix, explodeSpecifier, isBundler, getHydrateDirective, } from '@lwrjs/shared-utils';
|
|
2
|
+
import { kebabCaseToModuleSpecifier, getModuleGraphs, GraphDepth, getModuleUriPrefix, explodeSpecifier, isBundler, getHydrateDirective, isGroupie, } from '@lwrjs/shared-utils';
|
|
3
3
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
4
4
|
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
5
5
|
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
@@ -11,12 +11,26 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
11
11
|
const version = lwrVersion;
|
|
12
12
|
const isAMD = format === 'amd';
|
|
13
13
|
const { bundleConfig } = resourceContext;
|
|
14
|
-
const { external = {} } = bundleConfig;
|
|
14
|
+
const { external = {}, exclude = [] } = bundleConfig;
|
|
15
15
|
// Bundling groups is only supported in AMD for now
|
|
16
16
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
17
|
-
const
|
|
17
|
+
const getPreloadUri = function (rawSpecifier, uriMap) {
|
|
18
18
|
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
19
|
-
|
|
19
|
+
// do not preload externals; this is the app's responsibility
|
|
20
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
21
|
+
return;
|
|
22
|
+
const uri = uriMap[rawSpecifier];
|
|
23
|
+
// if there is no uri for an exclude or groupie, they've been handled via another specifier
|
|
24
|
+
// eg: if a bundle group has already been added to the URI map, its groups will not also be added
|
|
25
|
+
if (!uri && (exclude.includes(specifier) || isGroupie(specifier, groups))) {
|
|
26
|
+
// warn instead of throwing from setPreloadModulesMeta()
|
|
27
|
+
logger.warn({
|
|
28
|
+
label: 'view-registry',
|
|
29
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`,
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
return uri;
|
|
20
34
|
};
|
|
21
35
|
const { id: appName, bootstrap: { services, module: bootstrapModule, preloadModules = [] } = {
|
|
22
36
|
services: [],
|
|
@@ -130,8 +144,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
130
144
|
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
131
145
|
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
132
146
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
const uri = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
148
|
+
if (uri) {
|
|
135
149
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
136
150
|
}
|
|
137
151
|
}
|
|
@@ -186,8 +200,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
186
200
|
// PRELOAD custom element static deps as link resources when bundling is ON
|
|
187
201
|
if (bundle) {
|
|
188
202
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
const uri = getPreloadUri(depSpecifier, graph.uriMap);
|
|
204
|
+
if (uri) {
|
|
191
205
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
192
206
|
}
|
|
193
207
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger } from '@lwrjs/diagnostics';
|
|
1
|
+
import { LwrUnresolvableError, createSingleDiagnosticError, 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,9 @@ import { explodeSpecifier, getGroupName, getVersionedModuleId, normalizeVersionT
|
|
|
6
6
|
export function setPreloadModulesMeta(specifier, uri, 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
|
|
9
|
+
throw createSingleDiagnosticError({
|
|
10
|
+
description: descriptions.UNRESOLVABLE.PRELOAD_MODULE(specifier),
|
|
11
|
+
}, LwrUnresolvableError);
|
|
10
12
|
}
|
|
11
13
|
// We need to support version-less preloadModules, including version-less rootComponents.
|
|
12
14
|
// Removing the "/v/version_not_provided" hack from the preloadModules specifier
|
|
@@ -17,9 +17,11 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
|
|
|
17
17
|
},
|
|
18
18
|
...(debug && { modifiers: { debug: 'true' } }),
|
|
19
19
|
};
|
|
20
|
-
const
|
|
20
|
+
const nodeEnv = {
|
|
21
21
|
// TODO: W-12639529 change NODE_ENV after addressing downstream customers
|
|
22
22
|
NODE_ENV: runtimeEnvironment.serverMode,
|
|
23
|
+
};
|
|
24
|
+
const lwrEnv = {
|
|
23
25
|
// Note: SSR is always false because this script is executed on the client
|
|
24
26
|
SSR: false,
|
|
25
27
|
// Used by `lwr/environment`
|
|
@@ -33,7 +35,8 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
|
|
|
33
35
|
...config,
|
|
34
36
|
endpoints,
|
|
35
37
|
})});`,
|
|
36
|
-
`globalThis.
|
|
38
|
+
`globalThis.LWR = {...globalThis.LWR, env: ${JSON.stringify(lwrEnv)}};`,
|
|
39
|
+
`globalThis.process={...globalThis.process,env:{...globalThis.process?.env,...${JSON.stringify(nodeEnv)}}};`,
|
|
37
40
|
`globalThis.lwcRuntimeFlags = { ENABLE_MIXED_SHADOW_MODE: ${viewInfo.mixedMode} };`,
|
|
38
41
|
debug && debugMessage && `console.warn(${JSON.stringify(debugMessage)});`,
|
|
39
42
|
]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logger } from '@lwrjs/diagnostics';
|
|
2
|
-
import { kebabCaseToModuleSpecifier, toImportMetadata, getModuleGraphs, getMappingUriPrefix, GraphDepth, explodeSpecifier, isBundler, getHydrateDirective, } from '@lwrjs/shared-utils';
|
|
2
|
+
import { kebabCaseToModuleSpecifier, toImportMetadata, getModuleGraphs, getMappingUriPrefix, GraphDepth, explodeSpecifier, isBundler, getHydrateDirective, isGroupie, } from '@lwrjs/shared-utils';
|
|
3
3
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
4
4
|
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
5
5
|
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
@@ -15,12 +15,23 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
15
15
|
? { static: GraphDepth.ALL, dynamic: 1 }
|
|
16
16
|
: { static: GraphDepth.NONE, dynamic: 1 };
|
|
17
17
|
const { bundleConfig } = resourceContext;
|
|
18
|
-
const { external = {} } = bundleConfig;
|
|
18
|
+
const { external = {}, exclude = [] } = bundleConfig;
|
|
19
19
|
// Bundling groups is only supported in AMD for now
|
|
20
20
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
21
|
-
const
|
|
21
|
+
const getPreloadUri = function (rawSpecifier, uriMap) {
|
|
22
22
|
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
23
|
-
|
|
23
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
24
|
+
return;
|
|
25
|
+
const uri = uriMap[rawSpecifier];
|
|
26
|
+
if (!uri && (exclude.includes(specifier) || isGroupie(specifier, groups))) {
|
|
27
|
+
// warn instead of throwing from setPreloadModulesMeta()
|
|
28
|
+
logger.warn({
|
|
29
|
+
label: 'view-registry',
|
|
30
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`,
|
|
31
|
+
});
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return uri;
|
|
24
35
|
};
|
|
25
36
|
const { id: appName, bootstrap: { services, module: bootstrapModule, preloadModules = [] } = {
|
|
26
37
|
services: [],
|
|
@@ -114,8 +125,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
114
125
|
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
115
126
|
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
116
127
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
const uri = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
129
|
+
if (uri) {
|
|
119
130
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
120
131
|
}
|
|
121
132
|
}
|
|
@@ -172,8 +183,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
172
183
|
// PRELOAD custom element static deps as link resources when bundling is ON
|
|
173
184
|
if (bundle) {
|
|
174
185
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
175
|
-
|
|
176
|
-
|
|
186
|
+
const uri = getPreloadUri(depSpecifier, graph.uriMap);
|
|
187
|
+
if (uri) {
|
|
177
188
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
178
189
|
}
|
|
179
190
|
}
|
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, ViewRequest, ViewResponse } 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, }: 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
|
@@ -52,7 +52,7 @@ export async function generateHtmlTag(definition) {
|
|
|
52
52
|
}
|
|
53
53
|
throw new Error(`Invalid external Resource Definition: missing a "src": "${definition.specifier}"`);
|
|
54
54
|
}
|
|
55
|
-
export function normalizeRenderedResult({ renderedView, metadata, options, }) {
|
|
55
|
+
export function normalizeRenderedResult({ renderedView, metadata, options, cache, }) {
|
|
56
56
|
return {
|
|
57
57
|
renderedView,
|
|
58
58
|
metadata: {
|
|
@@ -64,6 +64,7 @@ export function normalizeRenderedResult({ renderedView, metadata, options, }) {
|
|
|
64
64
|
options: {
|
|
65
65
|
skipMetadataCollection: options ? options.skipMetadataCollection : false,
|
|
66
66
|
},
|
|
67
|
+
cache: cache || {},
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
export function reduceSourceAssetReferences(assets) {
|
package/build/es/view-handler.js
CHANGED
|
@@ -2,6 +2,7 @@ import { resolve } from 'path';
|
|
|
2
2
|
import { normalizeResourcePath, shortestTtl } from '@lwrjs/shared-utils';
|
|
3
3
|
import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
|
|
4
4
|
import { generateHtmlTag, generatePageContext, isViewResponse, toJsonFormat } from './utils.js';
|
|
5
|
+
import { DiagnosticsError, LwrApplicationError, createSingleDiagnosticError, descriptions, } from '@lwrjs/diagnostics';
|
|
5
6
|
export class LwrViewHandler {
|
|
6
7
|
constructor(context, globalConfig) {
|
|
7
8
|
this.globalConfig = globalConfig;
|
|
@@ -144,15 +145,26 @@ export class LwrViewHandler {
|
|
|
144
145
|
const { rootDir, assets, contentDir, layoutsDir } = this.globalConfig;
|
|
145
146
|
const paths = { rootDir, assets, contentDir, layoutsDir };
|
|
146
147
|
const locale = runtimeParams.locale;
|
|
148
|
+
const basePath = runtimeParams.basePath;
|
|
147
149
|
const viewApi = this.getBoundApi(viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
148
|
-
// TODO: add trace attributes
|
|
149
150
|
const response = await getTracer().trace({
|
|
150
151
|
name: ViewSpan.ExecuteRouteHandler,
|
|
151
152
|
attributes: {
|
|
152
153
|
view: route.id,
|
|
153
154
|
route: viewRequest.requestPath,
|
|
154
155
|
},
|
|
155
|
-
}, async () =>
|
|
156
|
+
}, async () => {
|
|
157
|
+
try {
|
|
158
|
+
return await routeHandlerFn({ ...viewRequest, locale, basePath }, { route: route, viewApi, ...paths }, routeHandlerOptions);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
if (err instanceof DiagnosticsError) {
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
164
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
165
|
+
throw createSingleDiagnosticError({ description: descriptions.APPLICATION.ROUTE_HANDLER_ERROR(route.id, message) }, LwrApplicationError);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
156
168
|
return response;
|
|
157
169
|
}
|
|
158
170
|
/*
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.12.0-alpha.
|
|
7
|
+
"version": "0.12.0-alpha.20",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
"build/**/*.d.ts"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@lwrjs/app-service": "0.12.0-alpha.
|
|
34
|
-
"@lwrjs/diagnostics": "0.12.0-alpha.
|
|
35
|
-
"@lwrjs/instrumentation": "0.12.0-alpha.
|
|
36
|
-
"@lwrjs/shared-utils": "0.12.0-alpha.
|
|
37
|
-
"lru-cache": "^10.
|
|
33
|
+
"@lwrjs/app-service": "0.12.0-alpha.20",
|
|
34
|
+
"@lwrjs/diagnostics": "0.12.0-alpha.20",
|
|
35
|
+
"@lwrjs/instrumentation": "0.12.0-alpha.20",
|
|
36
|
+
"@lwrjs/shared-utils": "0.12.0-alpha.20",
|
|
37
|
+
"lru-cache": "^10.2.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@lwrjs/types": "0.12.0-alpha.
|
|
40
|
+
"@lwrjs/types": "0.12.0-alpha.20"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "ae1793e34eaf4e9b97996d7aea9031908b23a13a"
|
|
46
46
|
}
|