@lwrjs/view-registry 0.12.0-alpha.9 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/index.cjs +53 -34
- package/build/cjs/linkers/legacy_view_bootstrap.cjs +28 -7
- package/build/cjs/linkers/utils.cjs +7 -4
- package/build/cjs/linkers/view_bootstrap.cjs +17 -7
- package/build/cjs/view-handler.cjs +13 -1
- package/build/es/index.js +68 -46
- package/build/es/linkers/legacy_view_bootstrap.js +36 -8
- package/build/es/linkers/utils.js +6 -3
- package/build/es/linkers/view_bootstrap.js +19 -8
- package/build/es/view-handler.js +14 -2
- package/package.json +7 -7
package/build/cjs/index.cjs
CHANGED
|
@@ -57,6 +57,10 @@ var LwrViewRegistry = class {
|
|
|
57
57
|
observer.onAssetSourceChange(({payload}) => this.onAssetSourceChange(payload));
|
|
58
58
|
}
|
|
59
59
|
async onModuleDefinitionChange(moduleDefinition) {
|
|
60
|
+
if (process.env.MRT_HMR === "true") {
|
|
61
|
+
this.viewDefinitions.clear();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
60
64
|
const versionedSpecifier = (0, import_shared_utils.getSpecifier)(moduleDefinition);
|
|
61
65
|
for (const [id, viewDefEntry] of this.viewDefinitions.entries()) {
|
|
62
66
|
const {
|
|
@@ -76,6 +80,10 @@ var LwrViewRegistry = class {
|
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
async onViewSourceChange(compiledView) {
|
|
83
|
+
if (process.env.MRT_HMR === "true") {
|
|
84
|
+
this.viewDefinitions.clear();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
79
87
|
const {contentTemplate, rootComponent} = compiledView.viewId;
|
|
80
88
|
const compiledViewCacheKey = (0, import_shared_utils.getCacheKeyFromJson)({contentTemplate, rootComponent});
|
|
81
89
|
this.compiledViews.set(compiledViewCacheKey, compiledView);
|
|
@@ -167,44 +175,54 @@ var LwrViewRegistry = class {
|
|
|
167
175
|
return false;
|
|
168
176
|
}
|
|
169
177
|
async getViewDefinition(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
178
|
+
try {
|
|
179
|
+
const {skipCaching, freezeAssets, viewParamCacheKey} = (0, import_utils.normalizeRenderOptions)(this.runtimeEnvironment, renderOptions);
|
|
180
|
+
const viewDefCacheKey = (0, import_shared_utils.getCacheKeyFromJson)({
|
|
181
|
+
...view,
|
|
182
|
+
freezeAssets,
|
|
183
|
+
locale: runtimeParams?.locale,
|
|
184
|
+
basePath: runtimeParams?.basePath,
|
|
185
|
+
debug: runtimeEnvironment.debug
|
|
186
|
+
});
|
|
187
|
+
import_diagnostics.logger.debug(`[view-registry][getViewDefinition] viewDefCacheKey=${viewDefCacheKey}`);
|
|
188
|
+
const viewParamKey = viewParamCacheKey ? (0, import_shared_utils.getCacheKeyFromJson)(viewParamCacheKey) : (0, import_shared_utils.getCacheKeyFromJson)(viewParams);
|
|
189
|
+
import_diagnostics.logger.debug(`[view-registry][getViewDefinition] viewParamKey=${viewParamKey}`);
|
|
190
|
+
const cacheDisabled = process.env.NOCACHE === "true" || skipCaching;
|
|
191
|
+
if (cacheDisabled === false && this.viewDefinitions.has(viewDefCacheKey)) {
|
|
192
|
+
const viewDefinition2 = this.viewDefinitions.get(viewDefCacheKey);
|
|
193
|
+
if (viewDefinition2 && viewDefinition2.paramKey === viewParamKey && viewDefinition2.viewDefinition.immutable) {
|
|
194
|
+
return viewDefinition2.viewDefinition;
|
|
195
|
+
}
|
|
186
196
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
198
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => (0, import_instrumentation.getTracer)().trace({
|
|
199
|
+
name: import_instrumentation.ViewSpan.RenderView,
|
|
200
|
+
attributes: {
|
|
201
|
+
view: view.id,
|
|
202
|
+
ssr: view.bootstrap?.ssr === true
|
|
203
|
+
}
|
|
204
|
+
}, () => this.renderView(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
205
|
+
if (cacheDisabled === false) {
|
|
206
|
+
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
207
|
+
const ttl = (0, import_shared_utils.shortestTtl)(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
208
|
+
if (ttl !== 0) {
|
|
209
|
+
this.viewDefinitions.set(viewDefCacheKey, {
|
|
210
|
+
view,
|
|
211
|
+
viewDefinition,
|
|
212
|
+
paramKey: viewParamKey
|
|
213
|
+
}, {ttl: ttl ? ttl * 1e3 : void 0});
|
|
214
|
+
}
|
|
194
215
|
}
|
|
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});
|
|
216
|
+
return viewDefinition;
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err instanceof import_diagnostics.DiagnosticsError) {
|
|
219
|
+
throw err;
|
|
205
220
|
}
|
|
221
|
+
import_diagnostics.logger.error(`Failed to get view definition "${view.id}"`);
|
|
222
|
+
import_diagnostics.logger.error(err);
|
|
223
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
224
|
+
throw (0, import_diagnostics.createSingleDiagnosticError)({description: import_diagnostics.descriptions.SERVER.UNEXPECTED_ERROR(message)}, import_diagnostics.LwrServerError);
|
|
206
225
|
}
|
|
207
|
-
return viewDefinition;
|
|
208
226
|
}
|
|
209
227
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams = {}, renderOptions) {
|
|
210
228
|
const {id, contentTemplate, rootComponent, layoutTemplate} = view;
|
|
@@ -305,6 +323,7 @@ var LwrViewRegistry = class {
|
|
|
305
323
|
const linkedMetadata = skipMetadataCollection ? renderedViewMetadata : await (0, import_shared_utils.extractMetadataFromHtml)(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
306
324
|
const mergedViewContext = {
|
|
307
325
|
...viewContext,
|
|
326
|
+
config: this.globalConfig,
|
|
308
327
|
runtimeEnvironment,
|
|
309
328
|
importer: importer || renderedView.compiledView.filePath
|
|
310
329
|
};
|
|
@@ -32,6 +32,14 @@ var import_identity = __toModule(require("@lwrjs/app-service/identity"));
|
|
|
32
32
|
var import_utils = __toModule(require("../utils.cjs"));
|
|
33
33
|
var import_utils2 = __toModule(require("./utils.cjs"));
|
|
34
34
|
var import_preload_utils = __toModule(require("./preload-utils.cjs"));
|
|
35
|
+
function includeIdFactory(bundleConfig) {
|
|
36
|
+
return (moduleRef) => {
|
|
37
|
+
if ((0, import_shared_utils.isExternalSpecifier)(moduleRef.specifier, bundleConfig)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
35
43
|
async function getHtmlResources(view, viewParams, resourceContext) {
|
|
36
44
|
const {
|
|
37
45
|
runtimeEnvironment,
|
|
@@ -46,11 +54,21 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
46
54
|
const version = lwrVersion;
|
|
47
55
|
const isAMD = format === "amd";
|
|
48
56
|
const {bundleConfig} = resourceContext;
|
|
49
|
-
const {external = {}} = bundleConfig;
|
|
57
|
+
const {external = {}, exclude = []} = bundleConfig;
|
|
50
58
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
51
|
-
const
|
|
59
|
+
const getPreloadUri = function(rawSpecifier, uriMap) {
|
|
52
60
|
const {specifier} = (0, import_shared_utils.explodeSpecifier)(rawSpecifier);
|
|
53
|
-
|
|
61
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
62
|
+
return;
|
|
63
|
+
const uri = uriMap[rawSpecifier];
|
|
64
|
+
if (!uri && (exclude.includes(specifier) || (0, import_shared_utils.isGroupie)(specifier, groups))) {
|
|
65
|
+
import_diagnostics.logger.warn({
|
|
66
|
+
label: "view-registry",
|
|
67
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
return uri;
|
|
54
72
|
};
|
|
55
73
|
const {
|
|
56
74
|
id: appName,
|
|
@@ -61,6 +79,9 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
61
79
|
} = view;
|
|
62
80
|
const defRegistry = bundle ? moduleBundler : moduleRegistry;
|
|
63
81
|
const depth = isAMD ? {static: import_shared_utils.GraphDepth.ALL, dynamic: 1} : {static: import_shared_utils.GraphDepth.NONE, dynamic: 0};
|
|
82
|
+
if (isAMD) {
|
|
83
|
+
depth.includeId = includeIdFactory(bundleConfig);
|
|
84
|
+
}
|
|
64
85
|
const appIdentity = {
|
|
65
86
|
appName,
|
|
66
87
|
format: runtimeEnvironment.format,
|
|
@@ -127,8 +148,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
127
148
|
}
|
|
128
149
|
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR}));
|
|
129
150
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
130
|
-
|
|
131
|
-
|
|
151
|
+
const uri2 = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
152
|
+
if (uri2) {
|
|
132
153
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
133
154
|
}
|
|
134
155
|
}
|
|
@@ -169,8 +190,8 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
169
190
|
(0, import_preload_utils.setPreloadModulesMeta)(specifier, uri, groups, viewPreloads);
|
|
170
191
|
if (bundle) {
|
|
171
192
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
172
|
-
|
|
173
|
-
|
|
193
|
+
const uri2 = getPreloadUri(depSpecifier, graph.uriMap);
|
|
194
|
+
if (uri2) {
|
|
174
195
|
(0, import_preload_utils.setPreloadModulesMeta)(depSpecifier, uri2, groups, viewPreloads);
|
|
175
196
|
}
|
|
176
197
|
}
|
|
@@ -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,9 +60,10 @@ 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
|
-
debug && debugMessage && `console.
|
|
66
|
+
debug && debugMessage && `console.error(${JSON.stringify(debugMessage)});`
|
|
64
67
|
].filter(Boolean).join("\n");
|
|
65
68
|
if (viewInfo.configAsSrc) {
|
|
66
69
|
const viewUrl = viewInfo.url || "/";
|
|
@@ -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
|
}
|
|
@@ -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) {
|
|
@@ -36,6 +36,11 @@ export class LwrViewRegistry {
|
|
|
36
36
|
observer.onAssetSourceChange(({ payload }) => this.onAssetSourceChange(payload));
|
|
37
37
|
}
|
|
38
38
|
async onModuleDefinitionChange(moduleDefinition) {
|
|
39
|
+
// TODO we will make this more robust in the future w/ full MRT HMR
|
|
40
|
+
if (process.env.MRT_HMR === 'true') {
|
|
41
|
+
this.viewDefinitions.clear();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
39
44
|
const versionedSpecifier = getSpecifier(moduleDefinition);
|
|
40
45
|
// invalidate viewDefinition cache entries with references to the LinkedModuleDefinition
|
|
41
46
|
for (const [id, viewDefEntry] of this.viewDefinitions.entries()) {
|
|
@@ -57,6 +62,11 @@ export class LwrViewRegistry {
|
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
async onViewSourceChange(compiledView) {
|
|
65
|
+
// TODO we will make this more robust in the future w/ full MRT HMR
|
|
66
|
+
if (process.env.MRT_HMR === 'true') {
|
|
67
|
+
this.viewDefinitions.clear();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
60
70
|
// invalidate compiledViews and viewDefinition cache entries with references to the CompiledView template id.
|
|
61
71
|
const { contentTemplate, rootComponent } = compiledView.viewId;
|
|
62
72
|
const compiledViewCacheKey = getCacheKeyFromJson({ contentTemplate, rootComponent });
|
|
@@ -159,55 +169,66 @@ export class LwrViewRegistry {
|
|
|
159
169
|
return false;
|
|
160
170
|
}
|
|
161
171
|
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
|
-
|
|
172
|
+
try {
|
|
173
|
+
const { skipCaching, freezeAssets, viewParamCacheKey } = normalizeRenderOptions(this.runtimeEnvironment, renderOptions);
|
|
174
|
+
const viewDefCacheKey = getCacheKeyFromJson({
|
|
175
|
+
...view,
|
|
176
|
+
freezeAssets,
|
|
177
|
+
locale: runtimeParams?.locale,
|
|
178
|
+
basePath: runtimeParams?.basePath,
|
|
179
|
+
debug: runtimeEnvironment.debug,
|
|
180
|
+
});
|
|
181
|
+
logger.debug(`[view-registry][getViewDefinition] viewDefCacheKey=${viewDefCacheKey}`);
|
|
182
|
+
// viewParams is an unbounded object and can be very large (17MB/view for developer.salesforce.com). Allowing consumers
|
|
183
|
+
// to provide a simple override avoids the excess memory / performance overhead of serializing & storing the viewParams
|
|
184
|
+
// on every request, while still reusing our caching logic.
|
|
185
|
+
const viewParamKey = viewParamCacheKey
|
|
186
|
+
? getCacheKeyFromJson(viewParamCacheKey)
|
|
187
|
+
: getCacheKeyFromJson(viewParams);
|
|
188
|
+
logger.debug(`[view-registry][getViewDefinition] viewParamKey=${viewParamKey}`);
|
|
189
|
+
const cacheDisabled = process.env.NOCACHE === 'true' || skipCaching;
|
|
190
|
+
// important: cache key does not include the unbounded viewParams
|
|
191
|
+
if (cacheDisabled === false && this.viewDefinitions.has(viewDefCacheKey)) {
|
|
192
|
+
const viewDefinition = this.viewDefinitions.get(viewDefCacheKey);
|
|
193
|
+
if (viewDefinition &&
|
|
194
|
+
viewDefinition.paramKey === viewParamKey &&
|
|
195
|
+
viewDefinition.viewDefinition.immutable) {
|
|
196
|
+
return viewDefinition.viewDefinition;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
200
|
+
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => getTracer().trace({
|
|
201
|
+
name: ViewSpan.RenderView,
|
|
202
|
+
attributes: {
|
|
203
|
+
view: view.id,
|
|
204
|
+
ssr: view.bootstrap?.ssr === true,
|
|
205
|
+
},
|
|
206
|
+
}, () => this.renderView(view, viewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
207
|
+
if (cacheDisabled === false) {
|
|
208
|
+
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
209
|
+
const ttl = shortestTtl(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
210
|
+
if (ttl !== 0) {
|
|
211
|
+
// cache view definition for the shortest ttl or until it is the least recently used when ttl is undefined
|
|
212
|
+
this.viewDefinitions.set(viewDefCacheKey, {
|
|
213
|
+
view,
|
|
214
|
+
viewDefinition,
|
|
215
|
+
paramKey: viewParamKey,
|
|
216
|
+
},
|
|
217
|
+
// s -> ms
|
|
218
|
+
{ ttl: ttl ? ttl * 1000 : undefined });
|
|
219
|
+
}
|
|
186
220
|
}
|
|
221
|
+
return viewDefinition;
|
|
187
222
|
}
|
|
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 });
|
|
223
|
+
catch (err) {
|
|
224
|
+
if (err instanceof DiagnosticsError) {
|
|
225
|
+
throw err;
|
|
208
226
|
}
|
|
227
|
+
logger.error(`Failed to get view definition "${view.id}"`);
|
|
228
|
+
logger.error(err);
|
|
229
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
230
|
+
throw createSingleDiagnosticError({ description: descriptions.SERVER.UNEXPECTED_ERROR(message) }, LwrServerError);
|
|
209
231
|
}
|
|
210
|
-
return viewDefinition;
|
|
211
232
|
}
|
|
212
233
|
async renderView(view, viewParams, runtimeEnvironment, runtimeParams = {}, renderOptions) {
|
|
213
234
|
const { id, contentTemplate, rootComponent, layoutTemplate } = view;
|
|
@@ -319,6 +340,7 @@ export class LwrViewRegistry {
|
|
|
319
340
|
: await extractMetadataFromHtml(renderedViewContent, renderedViewMetadata, this.globalConfig);
|
|
320
341
|
const mergedViewContext = {
|
|
321
342
|
...viewContext,
|
|
343
|
+
config: this.globalConfig,
|
|
322
344
|
runtimeEnvironment,
|
|
323
345
|
importer: importer || renderedView.compiledView.filePath,
|
|
324
346
|
};
|
|
@@ -1,9 +1,20 @@
|
|
|
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, isExternalSpecifier, } 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';
|
|
6
6
|
import { setPreloadModulesMeta, getPreloadModulesMeta } from './preload-utils.js';
|
|
7
|
+
function includeIdFactory(bundleConfig) {
|
|
8
|
+
return (moduleRef) => {
|
|
9
|
+
// Do not bundle externals, including the loader module, which is auto bundled
|
|
10
|
+
// with the shim + loader combo
|
|
11
|
+
if (isExternalSpecifier(moduleRef.specifier, bundleConfig)) {
|
|
12
|
+
// Do not include externals in the required imports but also return false to indicate it should not be in the bundle
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
7
18
|
export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
8
19
|
const { runtimeEnvironment, runtimeParams, moduleRegistry, moduleBundler, resourceRegistry, viewMetadata, } = resourceContext;
|
|
9
20
|
const { lwrVersion, format, hmrEnabled, bundle, debug, minify } = runtimeEnvironment;
|
|
@@ -11,12 +22,26 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
11
22
|
const version = lwrVersion;
|
|
12
23
|
const isAMD = format === 'amd';
|
|
13
24
|
const { bundleConfig } = resourceContext;
|
|
14
|
-
const { external = {} } = bundleConfig;
|
|
25
|
+
const { external = {}, exclude = [] } = bundleConfig;
|
|
15
26
|
// Bundling groups is only supported in AMD for now
|
|
16
27
|
const groups = isAMD ? bundleConfig.groups || {} : {};
|
|
17
|
-
const
|
|
28
|
+
const getPreloadUri = function (rawSpecifier, uriMap) {
|
|
18
29
|
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
19
|
-
|
|
30
|
+
// do not preload externals; this is the app's responsibility
|
|
31
|
+
if (Object.keys(external).some((e) => specifier === e))
|
|
32
|
+
return;
|
|
33
|
+
const uri = uriMap[rawSpecifier];
|
|
34
|
+
// if there is no uri for an exclude or groupie, they've been handled via another specifier
|
|
35
|
+
// eg: if a bundle group has already been added to the URI map, its groups will not also be added
|
|
36
|
+
if (!uri && (exclude.includes(specifier) || isGroupie(specifier, groups))) {
|
|
37
|
+
// warn instead of throwing from setPreloadModulesMeta()
|
|
38
|
+
logger.warn({
|
|
39
|
+
label: 'view-registry',
|
|
40
|
+
message: `Skipping preload of unknown static import: ${rawSpecifier}`,
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
return uri;
|
|
20
45
|
};
|
|
21
46
|
const { id: appName, bootstrap: { services, module: bootstrapModule, preloadModules = [] } = {
|
|
22
47
|
services: [],
|
|
@@ -26,6 +51,9 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
26
51
|
const depth = isAMD
|
|
27
52
|
? { static: GraphDepth.ALL, dynamic: 1 }
|
|
28
53
|
: { static: GraphDepth.NONE, dynamic: 0 };
|
|
54
|
+
if (isAMD) {
|
|
55
|
+
depth.includeId = includeIdFactory(bundleConfig);
|
|
56
|
+
}
|
|
29
57
|
// The Application Bootstrap (ABS) module resource is EITHER
|
|
30
58
|
// - configured as routes[x].bootstrap.module OR
|
|
31
59
|
// - defaulted as "@lwrjs/app-service/{appName}/module/{format}"
|
|
@@ -130,8 +158,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
130
158
|
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
131
159
|
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
132
160
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
133
|
-
|
|
134
|
-
|
|
161
|
+
const uri = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
162
|
+
if (uri) {
|
|
135
163
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
136
164
|
}
|
|
137
165
|
}
|
|
@@ -186,8 +214,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
186
214
|
// PRELOAD custom element static deps as link resources when bundling is ON
|
|
187
215
|
if (bundle) {
|
|
188
216
|
for (const depSpecifier of graph.graphs[0].static) {
|
|
189
|
-
|
|
190
|
-
|
|
217
|
+
const uri = getPreloadUri(depSpecifier, graph.uriMap);
|
|
218
|
+
if (uri) {
|
|
191
219
|
setPreloadModulesMeta(depSpecifier, uri, groups, viewPreloads);
|
|
192
220
|
}
|
|
193
221
|
}
|
|
@@ -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,9 +35,10 @@ 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
|
-
debug && debugMessage && `console.
|
|
41
|
+
debug && debugMessage && `console.error(${JSON.stringify(debugMessage)});`,
|
|
39
42
|
]
|
|
40
43
|
.filter(Boolean)
|
|
41
44
|
.join('\n');
|
|
@@ -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/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
|
|
7
|
+
"version": "0.12.0",
|
|
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
|
|
34
|
-
"@lwrjs/diagnostics": "0.12.0
|
|
35
|
-
"@lwrjs/instrumentation": "0.12.0
|
|
36
|
-
"@lwrjs/shared-utils": "0.12.0
|
|
33
|
+
"@lwrjs/app-service": "0.12.0",
|
|
34
|
+
"@lwrjs/diagnostics": "0.12.0",
|
|
35
|
+
"@lwrjs/instrumentation": "0.12.0",
|
|
36
|
+
"@lwrjs/shared-utils": "0.12.0",
|
|
37
37
|
"lru-cache": "^10.2.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@lwrjs/types": "0.12.0
|
|
40
|
+
"@lwrjs/types": "0.12.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "90f93604b26003e1e1eb85bb0d1f34f4fc9e9ff9"
|
|
46
46
|
}
|