@lwrjs/view-registry 0.9.0-alpha.9 → 0.9.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 +10 -4
- package/build/cjs/linkers/legacy_view_bootstrap.cjs +55 -24
- package/build/cjs/linkers/utils.cjs +39 -0
- package/build/cjs/linkers/view_bootstrap.cjs +43 -21
- package/build/cjs/utils.cjs +8 -25
- package/build/cjs/view-handler.cjs +19 -30
- package/build/es/index.js +9 -2
- package/build/es/linkers/legacy_view_bootstrap.d.ts +2 -1
- package/build/es/linkers/legacy_view_bootstrap.js +74 -39
- package/build/es/linkers/link-lwr-resources.d.ts +2 -1
- package/build/es/linkers/utils.d.ts +7 -1
- package/build/es/linkers/utils.js +52 -1
- package/build/es/linkers/view_bootstrap.d.ts +2 -1
- package/build/es/linkers/view_bootstrap.js +55 -35
- package/build/es/utils.d.ts +2 -14
- package/build/es/utils.js +5 -27
- package/build/es/view-handler.d.ts +5 -5
- package/build/es/view-handler.js +18 -35
- package/package.json +9 -9
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { kebabCaseToModuleSpecifier, getModuleGraphs, GraphDepth, getModuleUriPrefix, logger, explodeSpecifier, isBundler, } from '@lwrjs/shared-utils';
|
|
2
2
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
3
|
-
import { generateHtmlTag,
|
|
4
|
-
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
3
|
+
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
4
|
+
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, getPreloadModulesMeta, } from './utils.js';
|
|
5
5
|
export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
6
6
|
const { runtimeEnvironment, runtimeParams, moduleRegistry, moduleBundler, resourceRegistry, viewMetadata, } = resourceContext;
|
|
7
|
-
const {
|
|
7
|
+
const { bundleConfig } = resourceContext;
|
|
8
|
+
const { external = {} } = bundleConfig;
|
|
9
|
+
const isExternal = function (rawSpecifier) {
|
|
10
|
+
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
11
|
+
return Object.keys(external).some((e) => specifier === e);
|
|
12
|
+
};
|
|
13
|
+
const { id: appName, bootstrap: { services, module: bootstrapModule, preloadModules = [] } = {
|
|
14
|
+
services: [],
|
|
15
|
+
preloadModules: [],
|
|
16
|
+
}, } = view;
|
|
8
17
|
const { lwrVersion, format, hmrEnabled, bundle, debug, minify } = runtimeEnvironment;
|
|
9
18
|
const { customElements } = viewMetadata;
|
|
10
19
|
const version = lwrVersion;
|
|
11
20
|
const isAMD = format === 'amd';
|
|
12
|
-
// Application Bootstrap (ABS) module resource
|
|
21
|
+
// The Application Bootstrap (ABS) module resource is EITHER
|
|
22
|
+
// - configured as routes[x].bootstrap.module OR
|
|
23
|
+
// - defaulted as "@lwrjs/app-service/{appName}/module/{format}"
|
|
13
24
|
const appIdentity = {
|
|
14
25
|
appName,
|
|
15
26
|
format: runtimeEnvironment.format,
|
|
16
27
|
resourceType: AppResourceEnum.MODULE,
|
|
17
28
|
};
|
|
18
|
-
const bootstrapSpecifier = getAppSpecifier(appIdentity);
|
|
29
|
+
const bootstrapSpecifier = bootstrapModule || getAppSpecifier(appIdentity);
|
|
19
30
|
/*
|
|
20
31
|
Internal module and module dependency related resources used by the view to render view related components.
|
|
21
32
|
*/
|
|
@@ -37,25 +48,34 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
37
48
|
const rootComponents = [];
|
|
38
49
|
// Collection of modules specifiers that MUST be loaded in the view
|
|
39
50
|
const requiredAmdModules = [];
|
|
40
|
-
// Collection of modules that will be
|
|
41
|
-
|
|
51
|
+
// Collection of modules that will be preloaded. For AMD, it will be part of
|
|
52
|
+
// the preloadModules client bootstrap config
|
|
53
|
+
const preloadModulesMeta = new Map();
|
|
42
54
|
// Determine if server side rendering view modules
|
|
43
55
|
const isSSR = view.bootstrap?.ssr;
|
|
44
56
|
// ------ AMD Required module resources
|
|
45
57
|
if (isAMD) {
|
|
46
58
|
// Keep shim format in sync with view_bootstrap.ts
|
|
47
|
-
const shimBundle =
|
|
48
|
-
? 'lwr-loader-shim-legacy.js'
|
|
49
|
-
:
|
|
50
|
-
|
|
51
|
-
: 'lwr-loader-shim-legacy.bundle.min.js';
|
|
52
|
-
const def = (await resourceRegistry.getResource({ specifier: shimBundle, version }, runtimeEnvironment, runtimeParams));
|
|
59
|
+
const shimBundle = debug || minify === false
|
|
60
|
+
? 'lwr-loader-shim-legacy.bundle.js'
|
|
61
|
+
: 'lwr-loader-shim-legacy.bundle.min.js';
|
|
62
|
+
let def = (await resourceRegistry.getResource({ specifier: shimBundle, version }, runtimeEnvironment, runtimeParams));
|
|
53
63
|
if (!def) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
// HACK: fallback to looking for the other shim.
|
|
65
|
+
// TODO: remove this once we solve debug mode in MRT
|
|
66
|
+
let fallbackShimBundle;
|
|
67
|
+
if (shimBundle === 'lwr-loader-shim-legacy.bundle.js') {
|
|
68
|
+
fallbackShimBundle = 'lwr-loader-shim-legacy.bundle.min.js';
|
|
69
|
+
def = (await resourceRegistry.getResource({ specifier: fallbackShimBundle, version }, runtimeEnvironment, runtimeParams));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
fallbackShimBundle = 'lwr-loader-shim-legacy.bundle.js';
|
|
73
|
+
def = (await resourceRegistry.getResource({ specifier: fallbackShimBundle, version }, runtimeEnvironment, runtimeParams));
|
|
74
|
+
}
|
|
75
|
+
// throw if we still can't find it
|
|
76
|
+
if (!def) {
|
|
77
|
+
throw Error('Failed to find definition of resource: ' + shimBundle);
|
|
78
|
+
}
|
|
59
79
|
}
|
|
60
80
|
requiredResources.push(def);
|
|
61
81
|
// Always inline the error shim script after the shim
|
|
@@ -64,30 +84,34 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
64
84
|
throw Error('Failed to find definition of resource: lwr-error-shim.js');
|
|
65
85
|
}
|
|
66
86
|
requiredResources.push(errorShimDef);
|
|
67
|
-
// Add loader, if not already bundled with the shim
|
|
68
|
-
if (!bundle) {
|
|
69
|
-
// needed because we're resolving against fully-linked modules
|
|
70
|
-
requiredResources.push(await getModuleResource({
|
|
71
|
-
specifier: 'lwr/loaderLegacy',
|
|
72
|
-
version,
|
|
73
|
-
}, runtimeEnvironment, {
|
|
74
|
-
isPreload: false,
|
|
75
|
-
isSSR,
|
|
76
|
-
}, moduleRegistry, runtimeParams));
|
|
77
|
-
}
|
|
78
87
|
}
|
|
79
88
|
// ------- Application Bootstrap module
|
|
80
89
|
// Traversal of the Bootstrap Module Graph is done to get all the URLS for discoverable static dependencies.
|
|
81
|
-
// Reasoning: This is to avoid
|
|
90
|
+
// Reasoning: This is to avoid unnecessary HTTP 302's during initial application module fetching.
|
|
82
91
|
// Scope: ESM currently only exposes immutable URI references, optimize for AMD formats
|
|
83
92
|
const depth = isAMD
|
|
84
93
|
? { static: GraphDepth.ALL, dynamic: 1 }
|
|
85
94
|
: { static: GraphDepth.NONE, dynamic: 0 };
|
|
86
|
-
const
|
|
95
|
+
const defRegistry = bundle ? moduleBundler : moduleRegistry;
|
|
96
|
+
const bootstrapModuleGraph = await getModuleGraphs(bootstrapSpecifier, { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
|
|
87
97
|
// ADD bootstrap module uri as a script resource
|
|
88
98
|
const versionedSpecifier = bootstrapModuleGraph.graphs[0].specifier;
|
|
89
99
|
const uri = bootstrapModuleGraph.uriMap[versionedSpecifier];
|
|
90
100
|
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
101
|
+
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
102
|
+
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
103
|
+
if (!isExternal(depSpecifier)) {
|
|
104
|
+
const uri = bootstrapModuleGraph.uriMap[depSpecifier];
|
|
105
|
+
preloadModulesMeta.set(depSpecifier, uri);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// PRELOAD configured preloadModules as preloaded script resources
|
|
109
|
+
if (isBundler(defRegistry)) {
|
|
110
|
+
for (const specifier of preloadModules) {
|
|
111
|
+
// eslint-disable-next-line no-await-in-loop
|
|
112
|
+
await getPreloadModulesMeta(specifier, preloadModulesMeta, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
91
115
|
if (isAMD) {
|
|
92
116
|
// ADD bootstrap module as required
|
|
93
117
|
requiredAmdModules.push(versionedSpecifier);
|
|
@@ -100,8 +124,6 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
100
124
|
imports[staticDep] = uri;
|
|
101
125
|
// ADD bootstrap module static deps to requiredAmdModules if services, otherwise preloadModules
|
|
102
126
|
if (services && services.length) {
|
|
103
|
-
// get the graphs for the bs static deps
|
|
104
|
-
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
105
127
|
requiredAmdModules.push(staticDep);
|
|
106
128
|
}
|
|
107
129
|
}
|
|
@@ -120,18 +142,26 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
120
142
|
const customElementsRecords = [];
|
|
121
143
|
const flattenedElements = flattenCustomElements(customElements, isSSR);
|
|
122
144
|
await Promise.all(flattenedElements.map(async ({ tagName: element, props }) => {
|
|
123
|
-
const graph = await getModuleGraphs(
|
|
145
|
+
const graph = await getModuleGraphs(kebabCaseToModuleSpecifier(element), { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams ? runtimeParams : {}, visitedCache);
|
|
124
146
|
// add to the viewRecord
|
|
125
147
|
customElementsRecords.push({ elementName: element, flatGraph: graph });
|
|
126
|
-
// PRELOAD custom element
|
|
148
|
+
// PRELOAD the custom element module as a link resource
|
|
127
149
|
const specifier = graph.graphs[0].specifier;
|
|
128
150
|
const uri = graph.uriMap[specifier];
|
|
129
|
-
|
|
151
|
+
preloadModulesMeta.set(specifier, uri);
|
|
152
|
+
// PRELOAD custom element static deps as link resources when bundling is ON
|
|
153
|
+
if (bundle) {
|
|
154
|
+
for (const depSpecifier of graph.graphs[0].static) {
|
|
155
|
+
if (!isExternal(depSpecifier)) {
|
|
156
|
+
const uri = graph.uriMap[depSpecifier];
|
|
157
|
+
preloadModulesMeta.set(depSpecifier, uri);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
130
161
|
// ADD register custom elements as a uri addressable rootComponents
|
|
131
162
|
rootComponents.push(specifier);
|
|
132
163
|
imports[specifier] = uri;
|
|
133
164
|
if (isAMD) {
|
|
134
|
-
preloadAmdModules.push(specifier);
|
|
135
165
|
for (const staticDep of graph.graphs[0].static) {
|
|
136
166
|
const uri = graph.uriMap[staticDep];
|
|
137
167
|
// AMD ADD static module dep uri addressability
|
|
@@ -159,11 +189,16 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
159
189
|
},
|
|
160
190
|
rootComponents,
|
|
161
191
|
...(isAMD && { requiredModules: requiredAmdModules }),
|
|
162
|
-
|
|
192
|
+
// in AMD we need to tell the loader what modules we are preloading
|
|
193
|
+
...(isAMD && { preloadModules: Array.from(preloadModulesMeta.keys()) }),
|
|
163
194
|
}, runtimeEnvironment, runtimeParams));
|
|
164
195
|
if (!isAMD && hmrEnabled) {
|
|
165
196
|
configResources.unshift(await getViewHmrConfigurationResource(view, viewMetadata));
|
|
166
197
|
}
|
|
198
|
+
// PRELOAD script resources for preload module URIs after the bootstrap module
|
|
199
|
+
for (const [, preloadUri] of preloadModulesMeta) {
|
|
200
|
+
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
201
|
+
}
|
|
167
202
|
// generate html partial
|
|
168
203
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(generateHtmlTag));
|
|
169
204
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModuleRegistry, LinkedViewDefinition, RenderedViewMetadata, ResourceRegistry, RuntimeEnvironment, RuntimeParams, View, ModuleBundler, ViewParams } from '@lwrjs/types';
|
|
1
|
+
import { ModuleRegistry, LinkedViewDefinition, RenderedViewMetadata, ResourceRegistry, RuntimeEnvironment, RuntimeParams, View, ModuleBundler, ViewParams, BundleConfig } from '@lwrjs/types';
|
|
2
2
|
export interface LwrResourcesLinkedContext extends ResourceContext {
|
|
3
3
|
lwrResourcesId: string;
|
|
4
4
|
}
|
|
@@ -9,6 +9,7 @@ interface ResourceContext {
|
|
|
9
9
|
moduleRegistry: ModuleRegistry;
|
|
10
10
|
moduleBundler: ModuleBundler;
|
|
11
11
|
resourceRegistry: ResourceRegistry;
|
|
12
|
+
bundleConfig: BundleConfig;
|
|
12
13
|
}
|
|
13
14
|
declare type LinkedResourcesViewDefinition = Pick<LinkedViewDefinition, 'renderedView' | 'viewRecord'>;
|
|
14
15
|
export declare function linkLwrResources(source: string, view: View, viewParams: ViewParams, cxt: LwrResourcesLinkedContext): Promise<LinkedResourcesViewDefinition>;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { ClientBootstrapConfig, RuntimeEnvironment, RuntimeParams, ResourceDefinition, RenderedViewMetadata, CustomElementReference } from '@lwrjs/types';
|
|
1
|
+
import { ClientBootstrapConfig, RuntimeEnvironment, RuntimeParams, ResourceDefinition, RenderedViewMetadata, CustomElementReference, BundleConfig, ModuleBundler, ModuleRegistry } from '@lwrjs/types';
|
|
2
2
|
import { View, ViewInfo } from '@lwrjs/types';
|
|
3
3
|
export declare function getViewBootstrapConfigurationResource(viewInfo: ViewInfo, config: ClientBootstrapConfig, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams): ResourceDefinition;
|
|
4
4
|
export declare function getViewHmrConfigurationResource(view: View, viewMetadata: RenderedViewMetadata): ResourceDefinition;
|
|
5
5
|
export declare function flattenCustomElements(arr: CustomElementReference[], isSSR?: boolean): CustomElementReference[];
|
|
6
|
+
/**
|
|
7
|
+
* Recursively gets preloadModules metadata starting with a specifer
|
|
8
|
+
* Note: don't call me unless you got bundles
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPreloadModulesMeta(specifier: string, // unversioned specifier
|
|
11
|
+
preloadModulesMeta: Map<string, string>, bundleConfig: BundleConfig, moduleRegistry: ModuleRegistry, defRegistry: ModuleBundler, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams, pending?: Map<string, boolean>): Promise<void>;
|
|
6
12
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getMappingUriPrefix, getModuleUriPrefix, getClientBootstrapConfigurationUri, hashContent, } from '@lwrjs/shared-utils';
|
|
1
|
+
import { getMappingUriPrefix, getModuleUriPrefix, getClientBootstrapConfigurationUri, hashContent, getVersionedModuleId, normalizeVersionToUri, logger, VERSION_NOT_PROVIDED, explodeSpecifier, getSpecifier, } from '@lwrjs/shared-utils';
|
|
2
2
|
const CONTENT_TYPE = 'application/javascript';
|
|
3
3
|
export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeEnvironment, runtimeParams) {
|
|
4
4
|
const { compat, debug, hmrEnabled, apiVersion, format } = runtimeEnvironment;
|
|
@@ -25,6 +25,7 @@ export function getViewBootstrapConfigurationResource(viewInfo, config, runtimeE
|
|
|
25
25
|
...config,
|
|
26
26
|
endpoints,
|
|
27
27
|
})});`,
|
|
28
|
+
// TODO: W-12639529 change after addressing downstream customers
|
|
28
29
|
`globalThis.process = { env: { NODE_ENV: "${runtimeEnvironment.serverMode}" } };`,
|
|
29
30
|
]
|
|
30
31
|
.filter(Boolean)
|
|
@@ -99,4 +100,54 @@ export function flattenCustomElements(arr, isSSR = false) {
|
|
|
99
100
|
flatten(arr);
|
|
100
101
|
return ret;
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Recursively gets preloadModules metadata starting with a specifer
|
|
105
|
+
* Note: don't call me unless you got bundles
|
|
106
|
+
*/
|
|
107
|
+
export async function getPreloadModulesMeta(specifier, // unversioned specifier
|
|
108
|
+
preloadModulesMeta, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, pending) {
|
|
109
|
+
const { exclude = [], external = {} } = bundleConfig;
|
|
110
|
+
const isExternal = function (rawSpecifier) {
|
|
111
|
+
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
112
|
+
return Object.keys(external).includes(specifier);
|
|
113
|
+
};
|
|
114
|
+
const isExclude = function (specifier) {
|
|
115
|
+
return exclude.includes(specifier);
|
|
116
|
+
};
|
|
117
|
+
if (isExternal(specifier)) {
|
|
118
|
+
logger.warn(`"${specifier}" is configured in both bundleConfig.externals and bootstrap.preloadModules. We are treating it as external.`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// eslint-disable-next-line no-await-in-loop
|
|
122
|
+
const versionedModuleId = await getVersionedModuleId(specifier, moduleRegistry); // TODO replace moduleRegistry with defRegistry
|
|
123
|
+
const versionedModuleSpecifier = getSpecifier({
|
|
124
|
+
specifier,
|
|
125
|
+
version: normalizeVersionToUri(versionedModuleId.version),
|
|
126
|
+
});
|
|
127
|
+
const uri =
|
|
128
|
+
// eslint-disable-next-line no-await-in-loop
|
|
129
|
+
await defRegistry.resolveModuleUri(versionedModuleId, runtimeEnvironment, runtimeParams);
|
|
130
|
+
// fallback to unversioned specifier if needed
|
|
131
|
+
const normalizedSpecifier = versionedModuleId.version === VERSION_NOT_PROVIDED ? specifier : versionedModuleSpecifier;
|
|
132
|
+
preloadModulesMeta.set(normalizedSpecifier, uri);
|
|
133
|
+
if (exclude.length) {
|
|
134
|
+
// check if we need to also preload any excluded dependencies of this preload module
|
|
135
|
+
const preloadModuleRecord = await defRegistry.getModuleBundle(versionedModuleId, runtimeEnvironment, runtimeParams);
|
|
136
|
+
const { imports } = preloadModuleRecord.bundleRecord;
|
|
137
|
+
if (imports) {
|
|
138
|
+
if (!pending) {
|
|
139
|
+
pending = new Map();
|
|
140
|
+
}
|
|
141
|
+
for (let i = 0; i < imports.length; i++) {
|
|
142
|
+
const imp = imports[i];
|
|
143
|
+
if (!pending.has(imp.specifier) && isExclude(imp.specifier)) {
|
|
144
|
+
pending.set(imp.specifier, true); // prevent dupe calls
|
|
145
|
+
// eslint-disable-next-line no-await-in-loop
|
|
146
|
+
await getPreloadModulesMeta(imp.specifier, preloadModulesMeta, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, pending);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
102
153
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModuleRegistry, RenderedViewMetadata, RenderedViewRecord, ResourceRegistry, RuntimeEnvironment, RuntimeParams, View, ModuleBundler, ViewParams } from '@lwrjs/types';
|
|
1
|
+
import { BundleConfig, ModuleRegistry, RenderedViewMetadata, RenderedViewRecord, ResourceRegistry, RuntimeEnvironment, RuntimeParams, View, ModuleBundler, ViewParams } from '@lwrjs/types';
|
|
2
2
|
export interface LwrResourcesLinkedContext extends ResourceContext {
|
|
3
3
|
lwrResourcesId: string;
|
|
4
4
|
}
|
|
@@ -9,6 +9,7 @@ interface ResourceContext {
|
|
|
9
9
|
moduleRegistry: ModuleRegistry;
|
|
10
10
|
moduleBundler: ModuleBundler;
|
|
11
11
|
resourceRegistry: ResourceRegistry;
|
|
12
|
+
bundleConfig: BundleConfig;
|
|
12
13
|
}
|
|
13
14
|
export declare function getHtmlResources(view: View, viewParams: ViewParams, resourceContext: ResourceContext): Promise<{
|
|
14
15
|
partial: string;
|
|
@@ -1,21 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { kebabCaseToModuleSpecifier, toImportMetadata, getModuleGraphs, getMappingUriPrefix, GraphDepth, logger, explodeSpecifier, isBundler, } from '@lwrjs/shared-utils';
|
|
2
2
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
3
|
-
import { generateHtmlTag,
|
|
4
|
-
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
3
|
+
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
4
|
+
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, getPreloadModulesMeta, } from './utils.js';
|
|
5
5
|
export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
6
6
|
const { runtimeEnvironment, runtimeParams, moduleRegistry, moduleBundler, resourceRegistry, viewMetadata, } = resourceContext;
|
|
7
|
-
const {
|
|
7
|
+
const { bundleConfig } = resourceContext;
|
|
8
|
+
const { external = {} } = bundleConfig;
|
|
9
|
+
const isExternal = function (rawSpecifier) {
|
|
10
|
+
const { specifier } = explodeSpecifier(rawSpecifier);
|
|
11
|
+
return Object.keys(external).some((e) => specifier === e);
|
|
12
|
+
};
|
|
13
|
+
const { id: appName, bootstrap: { services, module: bootstrapModule, preloadModules = [] } = {
|
|
14
|
+
services: [],
|
|
15
|
+
preloadModules: [],
|
|
16
|
+
}, } = view;
|
|
8
17
|
const { lwrVersion, format, hmrEnabled, bundle, debug, minify } = runtimeEnvironment;
|
|
9
18
|
const { customElements } = viewMetadata;
|
|
19
|
+
const defRegistry = bundle ? moduleBundler : moduleRegistry;
|
|
10
20
|
const version = lwrVersion;
|
|
11
21
|
const isAMD = format === 'amd';
|
|
12
|
-
// Application Bootstrap (ABS) module resource
|
|
22
|
+
// The Application Bootstrap (ABS) module resource is EITHER
|
|
23
|
+
// - configured as routes[x].bootstrap.module OR
|
|
24
|
+
// - defaulted as "@lwrjs/app-service/{appName}/module/{format}"
|
|
13
25
|
const appIdentity = {
|
|
14
26
|
appName,
|
|
15
27
|
format: runtimeEnvironment.format,
|
|
16
28
|
resourceType: AppResourceEnum.MODULE,
|
|
17
29
|
};
|
|
18
|
-
const bootstrapSpecifier = getAppSpecifier(appIdentity);
|
|
30
|
+
const bootstrapSpecifier = bootstrapModule || getAppSpecifier(appIdentity);
|
|
19
31
|
/*
|
|
20
32
|
Internal module and module dependency related resources used by the view to render view related components.
|
|
21
33
|
*/
|
|
@@ -37,26 +49,19 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
37
49
|
const rootComponents = [];
|
|
38
50
|
// Collection of modules specifiers that MUST be loaded in the view
|
|
39
51
|
const requiredAmdModules = [];
|
|
40
|
-
// Collection of modules that will be
|
|
41
|
-
|
|
52
|
+
// Collection of modules that will be preloaded. For AMD, it will be part of
|
|
53
|
+
// the preloadModules client bootstrap config
|
|
54
|
+
const preloadModulesMeta = new Map();
|
|
42
55
|
// Determine if server side rendering view modules
|
|
43
56
|
const isSSR = view.bootstrap?.ssr;
|
|
44
57
|
// ------ AMD Required module resources
|
|
45
58
|
if (isAMD) {
|
|
46
59
|
// Keep shim format in sync with legacy_view_bootstrap.ts
|
|
47
|
-
const shimBundle =
|
|
48
|
-
? 'lwr-loader-shim.js'
|
|
49
|
-
: debug || minify === false
|
|
50
|
-
? 'lwr-loader-shim.bundle.js'
|
|
51
|
-
: 'lwr-loader-shim.bundle.min.js';
|
|
60
|
+
const shimBundle = debug || minify === false ? 'lwr-loader-shim.bundle.js' : 'lwr-loader-shim.bundle.min.js';
|
|
52
61
|
const def = (await resourceRegistry.getResource({ specifier: shimBundle, version }, runtimeEnvironment, runtimeParams));
|
|
53
62
|
if (!def) {
|
|
54
63
|
throw Error('Failed to find definition of resource: ' + shimBundle);
|
|
55
64
|
}
|
|
56
|
-
// HACK: preemptively closing the stream because it is never read
|
|
57
|
-
if (def.stream) {
|
|
58
|
-
def.stream.destroy();
|
|
59
|
-
}
|
|
60
65
|
requiredResources.push(def);
|
|
61
66
|
// Always inline the error shim script after the shim
|
|
62
67
|
const errorShimDef = (await resourceRegistry.getResource({ specifier: 'lwr-error-shim.js', version }, runtimeEnvironment, runtimeParams));
|
|
@@ -64,16 +69,6 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
64
69
|
throw Error('Failed to find definition of resource: lwr-error-shim.js');
|
|
65
70
|
}
|
|
66
71
|
requiredResources.push(errorShimDef);
|
|
67
|
-
// Add loader, if not already bundled with the shim
|
|
68
|
-
if (!bundle) {
|
|
69
|
-
// needed because we're resolving against fully-linked modules
|
|
70
|
-
requiredResources.push(await getModuleResource({
|
|
71
|
-
specifier: 'lwr/loader',
|
|
72
|
-
version,
|
|
73
|
-
}, runtimeEnvironment, {
|
|
74
|
-
isSSR,
|
|
75
|
-
}, moduleRegistry, runtimeParams));
|
|
76
|
-
}
|
|
77
72
|
}
|
|
78
73
|
// ------- Application Bootstrap module
|
|
79
74
|
// Traversal of the Bootstrap Module Graph is done to get all the URLS for discoverable static dependencies.
|
|
@@ -81,11 +76,25 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
81
76
|
const depth = isAMD
|
|
82
77
|
? { static: GraphDepth.ALL, dynamic: 1 }
|
|
83
78
|
: { static: GraphDepth.NONE, dynamic: 1 };
|
|
84
|
-
const bootstrapModuleGraph = await getModuleGraphs(bootstrapSpecifier, { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry,
|
|
79
|
+
const bootstrapModuleGraph = await getModuleGraphs(bootstrapSpecifier, { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
|
|
85
80
|
// ADD bootstrap module uri as a script resource
|
|
86
81
|
const versionedSpecifier = bootstrapModuleGraph.graphs[0].specifier;
|
|
87
82
|
const uri = bootstrapModuleGraph.uriMap[versionedSpecifier];
|
|
88
83
|
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
84
|
+
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
85
|
+
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
86
|
+
if (!isExternal(depSpecifier)) {
|
|
87
|
+
const uri = bootstrapModuleGraph.uriMap[depSpecifier];
|
|
88
|
+
preloadModulesMeta.set(depSpecifier, uri);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// PRELOAD configured preloadModules as preloaded script resources
|
|
92
|
+
if (isBundler(defRegistry)) {
|
|
93
|
+
for (const specifier of preloadModules) {
|
|
94
|
+
// eslint-disable-next-line no-await-in-loop
|
|
95
|
+
await getPreloadModulesMeta(specifier, preloadModulesMeta, bundleConfig, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
89
98
|
if (isAMD) {
|
|
90
99
|
// ADD bootstrap module as required
|
|
91
100
|
requiredAmdModules.push(versionedSpecifier);
|
|
@@ -98,8 +107,6 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
98
107
|
imports[staticDep] = uri;
|
|
99
108
|
// ADD bootstrap module static deps to requiredAmdModules if services, otherwise preloadModules
|
|
100
109
|
if (services && services.length) {
|
|
101
|
-
// get the graphs for the bs static deps
|
|
102
|
-
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
103
110
|
requiredAmdModules.push(staticDep);
|
|
104
111
|
}
|
|
105
112
|
}
|
|
@@ -120,18 +127,26 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
120
127
|
const flattenedElements = flattenCustomElements(customElements, isSSR);
|
|
121
128
|
for (const { tagName: element } of flattenedElements) {
|
|
122
129
|
// eslint-disable-next-line no-await-in-loop
|
|
123
|
-
const graph = await getModuleGraphs(
|
|
130
|
+
const graph = await getModuleGraphs(kebabCaseToModuleSpecifier(element), { includeUris: true, includeLinkedDefinitions: true, depth }, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams ? runtimeParams : {}, visitedCache);
|
|
124
131
|
// add to the viewRecord
|
|
125
132
|
customElementsRecords.push({ elementName: element, flatGraph: graph });
|
|
126
|
-
// PRELOAD custom element
|
|
133
|
+
// PRELOAD the custom element module as a link resource
|
|
127
134
|
const specifier = graph.graphs[0].specifier;
|
|
128
135
|
const uri = graph.uriMap[specifier];
|
|
129
|
-
|
|
136
|
+
preloadModulesMeta.set(specifier, uri);
|
|
137
|
+
// PRELOAD custom element static deps as link resources when bundling is ON
|
|
138
|
+
if (bundle) {
|
|
139
|
+
for (const depSpecifier of graph.graphs[0].static) {
|
|
140
|
+
if (!isExternal(depSpecifier)) {
|
|
141
|
+
const uri = graph.uriMap[depSpecifier];
|
|
142
|
+
preloadModulesMeta.set(depSpecifier, uri);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
130
146
|
// ADD register custom elements as a uri addressable rootComponents
|
|
131
147
|
rootComponents.push(specifier);
|
|
132
148
|
imports[specifier] = uri;
|
|
133
149
|
if (isAMD) {
|
|
134
|
-
preloadAmdModules.push(specifier);
|
|
135
150
|
for (const staticDep of graph.graphs[0].static) {
|
|
136
151
|
const uri = graph.uriMap[staticDep];
|
|
137
152
|
// AMD ADD static module dep uri addressability
|
|
@@ -159,11 +174,16 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
159
174
|
index: importMetadata?.index,
|
|
160
175
|
rootComponents,
|
|
161
176
|
...(isAMD && { requiredModules: requiredAmdModules }),
|
|
162
|
-
|
|
177
|
+
// in AMD we need to tell the loader what modules we are preloading
|
|
178
|
+
...(isAMD && { preloadModules: Array.from(preloadModulesMeta.keys()) }),
|
|
163
179
|
}, runtimeEnvironment, runtimeParams));
|
|
164
180
|
if (!isAMD && hmrEnabled) {
|
|
165
181
|
configResources.unshift(await getViewHmrConfigurationResource(view, viewMetadata));
|
|
166
182
|
}
|
|
183
|
+
// PRELOAD script resources for preload module URIs after the bootstrap module
|
|
184
|
+
for (const [, preloadUri] of preloadModulesMeta) {
|
|
185
|
+
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
186
|
+
}
|
|
167
187
|
// generate html partial
|
|
168
188
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(generateHtmlTag));
|
|
169
189
|
const mapping = getMappingUriPrefix(runtimeEnvironment, runtimeParams);
|
package/build/es/utils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { NormalizedRenderingResult, RenderingResult, ResourceDefinition,
|
|
2
|
-
import { PublicModuleRegistry, RuntimeEnvironment, RuntimeParams, ModuleJson, RouteHandlerViewResponse, ViewResponse, RouteHandlerFunction, LwrRoute, LwrErrorRoute, ViewRequest, LinkedViewDefinition, ModuleRegistry } from 'packages/@lwrjs/types/src';
|
|
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';
|
|
3
2
|
export declare type HTMLResource = Partial<ResourceDefinition>;
|
|
4
3
|
export declare function generateHtmlTag(definition: HTMLResource): Promise<string>;
|
|
5
4
|
export declare function normalizeRenderedResult({ renderedView, metadata, options, }: RenderingResult): NormalizedRenderingResult;
|
|
@@ -7,19 +6,8 @@ export declare function reduceSourceAssetReferences(assets: AssetReference[]): R
|
|
|
7
6
|
export declare function normalizeRenderOptions(runtimeEnvironment: RuntimeEnvironment, overrideRenderOptions?: RenderOptions, baseRenderOptions?: RenderOptions): Required<RenderOptions>;
|
|
8
7
|
export declare function generatePageContext({ requestPath: url }: ViewRequest, { id, contentTemplate, properties }: LwrRoute | LwrErrorRoute): JsonCompatible<ViewPageContext>;
|
|
9
8
|
export declare function isViewResponse(response: RouteHandlerViewResponse): response is ViewResponse;
|
|
10
|
-
interface RouteHandlerContext {
|
|
11
|
-
cacheDir: string;
|
|
12
|
-
rootDir: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Load and cache a route handler function (for a view) from the fs
|
|
16
|
-
* @param path - path to the route handle code on the fs
|
|
17
|
-
* @param param1 - directories
|
|
18
|
-
*/
|
|
19
|
-
export declare function getRouteHandler(path: string, { cacheDir, rootDir }: RouteHandlerContext): Promise<RouteHandlerFunction>;
|
|
20
9
|
export declare function toJsonFormat(viewRequest: ViewRequest, viewDefinition: LinkedViewDefinition, route: LwrRoute | LwrErrorRoute, runtimeEnvironment: RuntimeEnvironment, runtimeParams: RuntimeParams, moduleRegistry: ModuleRegistry): Promise<ViewResponse>;
|
|
21
|
-
export declare function getModuleResource(moduleId: Pick<ModuleId, 'specifier' | 'version'>, runtimeEnvironment: RuntimeEnvironment, moduleResouceMeta: ViewModuleResourceContext,
|
|
10
|
+
export declare function getModuleResource(moduleId: Pick<ModuleId, 'specifier' | 'version'>, runtimeEnvironment: RuntimeEnvironment, moduleResouceMeta: ViewModuleResourceContext, defRegistry: ModuleRegistry | ModuleBundler, runtimeParams?: RuntimeParams): Promise<ResourceDefinition>;
|
|
22
11
|
export declare function getModuleResourceByUri(uri: string, runtimeEnvironment: RuntimeEnvironment, moduleResouceMeta: ViewModuleResourceContext): ResourceDefinition;
|
|
23
12
|
export declare function createJsonModule(specifier: string, moduleRegistry: PublicModuleRegistry, environment: RuntimeEnvironment, params?: RuntimeParams): Promise<ModuleJson>;
|
|
24
|
-
export {};
|
|
25
13
|
//# sourceMappingURL=utils.d.ts.map
|
package/build/es/utils.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { explodeSpecifier, getMappingUriPrefix, getSpecifier, resolveFileExtension, transpileTs, DEFAULT_TITLE, } from '@lwrjs/shared-utils';
|
|
2
|
-
import libPath from 'path';
|
|
3
1
|
import { basename, extname } from 'path';
|
|
4
|
-
import { mimeLookup } from '@lwrjs/shared-utils';
|
|
2
|
+
import { explodeSpecifier, getMappingUriPrefix, getSpecifier, getClientBootstrapConfigurationUri, mimeLookup, DEFAULT_TITLE, } from '@lwrjs/shared-utils';
|
|
5
3
|
import { AppResourceEnum, getAppSpecifier, ResourceIdentityTypes, } from '@lwrjs/app-service/identity';
|
|
6
|
-
import { getClientBootstrapConfigurationUri } from '@lwrjs/shared-utils';
|
|
7
4
|
function streamToString(stream) {
|
|
8
5
|
const chunks = [];
|
|
9
6
|
return new Promise((resolve, reject) => {
|
|
@@ -51,7 +48,7 @@ async function generateInlineTag({ specifier, type, content, stream, nonce }) {
|
|
|
51
48
|
if (!content && !stream) {
|
|
52
49
|
throw new Error(`Invalid inline Resource Definition: must have either "content" or "stream": "${specifier}"`);
|
|
53
50
|
}
|
|
54
|
-
const code =
|
|
51
|
+
const code = stream ? await streamToString(stream()) : content;
|
|
55
52
|
return `<${tag}${typeStr}${nonceStr}>${code}</${tag}>`;
|
|
56
53
|
}
|
|
57
54
|
export async function generateHtmlTag(definition) {
|
|
@@ -110,25 +107,6 @@ export function generatePageContext({ requestPath: url }, { id, contentTemplate,
|
|
|
110
107
|
export function isViewResponse(response) {
|
|
111
108
|
return response.body !== undefined;
|
|
112
109
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Load and cache a route handler function (for a view) from the fs
|
|
115
|
-
* @param path - path to the route handle code on the fs
|
|
116
|
-
* @param param1 - directories
|
|
117
|
-
*/
|
|
118
|
-
export async function getRouteHandler(path, { cacheDir, rootDir }) {
|
|
119
|
-
try {
|
|
120
|
-
const fullPath = resolveFileExtension(path);
|
|
121
|
-
if (fullPath.endsWith('.ts')) {
|
|
122
|
-
path = await transpileTs(path, { rootDir, cacheDir: libPath.join(cacheDir, 'routeHandlers') });
|
|
123
|
-
}
|
|
124
|
-
const moduleEntry = await import(path);
|
|
125
|
-
return moduleEntry.default || moduleEntry;
|
|
126
|
-
}
|
|
127
|
-
catch (err) {
|
|
128
|
-
console.log(err);
|
|
129
|
-
throw new Error(`Unable to get routeHandler: ${path}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
110
|
export async function toJsonFormat(viewRequest, viewDefinition, route, runtimeEnvironment, runtimeParams, moduleRegistry) {
|
|
133
111
|
const { viewRecord } = viewDefinition;
|
|
134
112
|
const { bootstrap, id: appName } = route;
|
|
@@ -213,10 +191,10 @@ export async function toJsonFormat(viewRequest, viewDefinition, route, runtimeEn
|
|
|
213
191
|
},
|
|
214
192
|
};
|
|
215
193
|
}
|
|
216
|
-
export async function getModuleResource(moduleId, runtimeEnvironment, moduleResouceMeta,
|
|
194
|
+
export async function getModuleResource(moduleId, runtimeEnvironment, moduleResouceMeta, defRegistry, runtimeParams) {
|
|
217
195
|
const { format } = runtimeEnvironment;
|
|
218
196
|
const { isSSR = false, isPreload = false } = moduleResouceMeta;
|
|
219
|
-
const moduleUri = await
|
|
197
|
+
const moduleUri = await defRegistry.resolveModuleUri(moduleId, runtimeEnvironment, runtimeParams);
|
|
220
198
|
return {
|
|
221
199
|
src: moduleUri,
|
|
222
200
|
type: format === 'amd' ? 'application/javascript' : 'module',
|
|
@@ -257,7 +235,7 @@ export async function createJsonModule(specifier, moduleRegistry, environment, p
|
|
|
257
235
|
version,
|
|
258
236
|
ownHash,
|
|
259
237
|
links: {
|
|
260
|
-
self: moduleRegistry.resolveModuleUri(moduleIdentifier, environment, params, ownHash),
|
|
238
|
+
self: await moduleRegistry.resolveModuleUri(moduleIdentifier, environment, params, ownHash),
|
|
261
239
|
},
|
|
262
240
|
};
|
|
263
241
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ViewRegistry, RuntimeEnvironment, NormalizedLwrGlobalConfig, ViewRequest, RuntimeParams, ViewResponse,
|
|
1
|
+
import { ViewRegistry, RuntimeEnvironment, NormalizedLwrGlobalConfig, ViewRequest, RuntimeParams, ViewResponse, LwrRoute, LwrErrorRoute, ModuleRegistry, ViewHandler, RouteHandlers } from '@lwrjs/types';
|
|
2
2
|
export interface ViewHandlerContext {
|
|
3
3
|
viewRegistry: ViewRegistry;
|
|
4
4
|
moduleRegistry: ModuleRegistry;
|
|
5
|
+
routeHandlers: RouteHandlers;
|
|
5
6
|
}
|
|
6
|
-
export declare class LwrViewHandler {
|
|
7
|
+
export declare class LwrViewHandler implements ViewHandler {
|
|
8
|
+
globalConfig: NormalizedLwrGlobalConfig;
|
|
9
|
+
routeHandlers: RouteHandlers;
|
|
7
10
|
viewRegistry: ViewRegistry;
|
|
8
11
|
moduleRegistry: ModuleRegistry;
|
|
9
|
-
globalConfig: NormalizedLwrGlobalConfig;
|
|
10
|
-
inflightRouteHandlerEvalMap: Map<string, Promise<RouteHandlerFunction>>;
|
|
11
|
-
routeHandlerFunctionMap: Map<string, RouteHandlerFunction>;
|
|
12
12
|
constructor(context: ViewHandlerContext, globalConfig: NormalizedLwrGlobalConfig);
|
|
13
13
|
getViewContent(viewRequest: ViewRequest, route: LwrRoute | LwrErrorRoute, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams): Promise<ViewResponse>;
|
|
14
14
|
getViewJson(viewRequest: ViewRequest, route: LwrRoute | LwrErrorRoute, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams): Promise<ViewResponse>;
|