@lwrjs/core 0.11.0-alpha.8 → 0.11.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/context/server.cjs +1 -1
- package/build/cjs/index.cjs +3 -1
- package/build/cjs/middleware/asset-middleware.cjs +10 -2
- package/build/cjs/middleware/bundle-middleware.cjs +20 -7
- package/build/cjs/middleware/hmr-middleware.cjs +6 -5
- package/build/cjs/middleware/locale-middleware.cjs +3 -1
- package/build/cjs/middleware/mapping-middleware.cjs +14 -4
- package/build/cjs/middleware/module-middleware.cjs +12 -4
- package/build/cjs/middleware/request-processor-middleware.cjs +64 -0
- package/build/cjs/middleware/resource-middleware.cjs +3 -3
- package/build/cjs/middleware/utils/error-handling.cjs +5 -4
- package/build/cjs/middleware/view-middleware.cjs +37 -8
- package/build/cjs/middleware.cjs +2 -0
- package/build/cjs/tools/server-warmup.cjs +6 -6
- package/build/cjs/tools/static-generation.cjs +72 -66
- package/build/cjs/tools/utils/network-dispatcher.cjs +12 -11
- package/build/es/context/server.js +1 -2
- package/build/es/index.js +5 -2
- package/build/es/middleware/asset-middleware.js +10 -2
- package/build/es/middleware/bundle-middleware.js +17 -9
- package/build/es/middleware/hmr-middleware.js +6 -5
- package/build/es/middleware/locale-middleware.js +1 -1
- package/build/es/middleware/mapping-middleware.js +9 -4
- package/build/es/middleware/module-middleware.js +14 -6
- package/build/es/middleware/request-processor-middleware.d.ts +3 -0
- package/build/es/middleware/request-processor-middleware.js +53 -0
- package/build/es/middleware/resource-middleware.js +3 -3
- package/build/es/middleware/utils/error-handling.js +5 -4
- package/build/es/middleware/view-middleware.js +48 -8
- package/build/es/middleware.d.ts +1 -0
- package/build/es/middleware.js +1 -0
- package/build/es/tools/server-warmup.js +2 -2
- package/build/es/tools/static-generation.d.ts +4 -0
- package/build/es/tools/static-generation.js +66 -52
- package/build/es/tools/types.d.ts +2 -1
- package/build/es/tools/utils/network-dispatcher.js +2 -1
- package/package.json +31 -29
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ServerContext, InternalAppServer, ServerTypes } from '@lwrjs/types';
|
|
2
|
+
export declare function requestProcessorMiddleware<T extends ServerTypes>(app: InternalAppServer<T>, context: ServerContext): void;
|
|
3
|
+
//# sourceMappingURL=request-processor-middleware.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse passed to us via the X-Mobify-Request-Class.
|
|
3
|
+
*
|
|
4
|
+
* basePath: The dynamic base path
|
|
5
|
+
* '' or undefined -> LWR basePath ''
|
|
6
|
+
* token or /token -> LWR basePath '/token'
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
import { logger } from '@lwrjs/diagnostics';
|
|
10
|
+
const MRT_REQUEST_CLASS = 'X-Mobify-Request-Class';
|
|
11
|
+
const MRT_REQUEST_CLASS_KEY = MRT_REQUEST_CLASS.toLowerCase();
|
|
12
|
+
export function requestProcessorMiddleware(app, context) {
|
|
13
|
+
const { basePath } = context.runtimeEnvironment;
|
|
14
|
+
app.use(async (req, _res, next) => {
|
|
15
|
+
let requestClass;
|
|
16
|
+
if (req.headers) {
|
|
17
|
+
// If debug print log all the headers
|
|
18
|
+
if (logger.currentLevel === 'debug' || logger.currentLevel == 'verbose') {
|
|
19
|
+
// Loop through and print each header
|
|
20
|
+
for (const headerName in req.headers) {
|
|
21
|
+
logger.debug(`[request-processor-middleware] Header ${headerName}: ${req.headers[headerName]}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
requestClass = req.headers[MRT_REQUEST_CLASS_KEY];
|
|
25
|
+
}
|
|
26
|
+
if (req.headers && typeof requestClass === 'string') {
|
|
27
|
+
const parsedRequestClass = parseRequestClass(requestClass);
|
|
28
|
+
logger.debug(`[request-processor-middleware] parsedRequestClass?.basePath: ${parsedRequestClass?.basePath}`);
|
|
29
|
+
const pathValue = parsedRequestClass?.basePath || basePath || '';
|
|
30
|
+
// If base path is '' or starts with / leave it alone
|
|
31
|
+
req.basePath = pathValue === '' || pathValue.indexOf('/') === 0 ? pathValue : `/${pathValue}`;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
logger.debug(`[request-processor-middleware] ${MRT_REQUEST_CLASS_KEY} ignored ${req.headers ? req.headers[MRT_REQUEST_CLASS_KEY] : 'no-headers'}`);
|
|
35
|
+
req.basePath = basePath;
|
|
36
|
+
}
|
|
37
|
+
// await is required when calling next to support koa
|
|
38
|
+
await next();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function parseRequestClass(requestClass) {
|
|
42
|
+
// Split the Forwarded header into individual key-value pairs
|
|
43
|
+
const keyValuePairs = requestClass.split(';');
|
|
44
|
+
// Create an object to store the parsed values
|
|
45
|
+
const parsed = {};
|
|
46
|
+
// Iterate through the key-value pairs and populate the parsed object
|
|
47
|
+
for (const pair of keyValuePairs) {
|
|
48
|
+
const [key, value] = pair.split('=');
|
|
49
|
+
parsed[key] = value;
|
|
50
|
+
}
|
|
51
|
+
return parsed;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=request-processor-middleware.js.map
|
|
@@ -2,13 +2,13 @@ import { descriptions } from '@lwrjs/diagnostics';
|
|
|
2
2
|
import { getResourceIdentity } from './utils/identity.js';
|
|
3
3
|
import { handleErrors } from './utils/error-handling.js';
|
|
4
4
|
function createResourceMiddleware(context) {
|
|
5
|
-
const { resourceRegistry } = context;
|
|
5
|
+
const { appConfig, resourceRegistry, runtimeEnvironment: defaultRuntimeEnvironment } = context;
|
|
6
6
|
return async (req, res) => {
|
|
7
|
-
if (!req.validateEnvironmentRequest(
|
|
7
|
+
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
8
8
|
res.status(400).send(descriptions.UNRESOLVABLE.INVALID_ENVIRONMENT(req.params.environment).message);
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
-
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(
|
|
11
|
+
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(defaultRuntimeEnvironment);
|
|
12
12
|
const { resourceId } = getResourceIdentity(req);
|
|
13
13
|
const resource = await resourceRegistry.getResource(resourceId, runtimeEnvironment, runtimeParams);
|
|
14
14
|
if (req.isSiteGeneration()) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { descriptions, DiagnosticsError, LwrUnresolvableError } from '@lwrjs/diagnostics';
|
|
2
|
+
import { logger } from '@lwrjs/diagnostics';
|
|
2
3
|
function createReturnStatus(error, url) {
|
|
3
4
|
if (error instanceof LwrUnresolvableError &&
|
|
4
5
|
error.diagnostics[0].description.category === 'lwrUnresolvable/invalid') {
|
|
@@ -16,12 +17,12 @@ export function handleErrors(middleware) {
|
|
|
16
17
|
}
|
|
17
18
|
catch (err) {
|
|
18
19
|
if (err instanceof DiagnosticsError) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
logger.error('LWR Diagnostic Error: ' + err.message);
|
|
21
|
+
logger.error(err.diagnostics);
|
|
22
|
+
logger.error(err.stack);
|
|
22
23
|
}
|
|
23
24
|
else {
|
|
24
|
-
|
|
25
|
+
logger.error(err);
|
|
25
26
|
}
|
|
26
27
|
const { status, message } = createReturnStatus(err, req.originalUrl);
|
|
27
28
|
res.status(status);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { descriptions } from '@lwrjs/diagnostics';
|
|
1
|
+
import { descriptions, logger } from '@lwrjs/diagnostics';
|
|
2
2
|
import { getClientRoutes } from '@lwrjs/router';
|
|
3
|
-
import { decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes,
|
|
3
|
+
import { decodeViewPath, extractRequestParams, getClientBootstrapConfigurationRoutes, shortestTtl, } from '@lwrjs/shared-utils';
|
|
4
|
+
import { RequestHandlerSpan, getTracer } from '@lwrjs/instrumentation';
|
|
4
5
|
import { handleErrors } from './utils/error-handling.js';
|
|
5
6
|
import { LwrViewHandler } from '@lwrjs/view-registry';
|
|
6
7
|
function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
7
8
|
const errorRoute = errorRoutes.find((route) => route.status === 500);
|
|
9
|
+
const appConfig = context.appConfig;
|
|
10
|
+
const { environment: environmentConfig } = appConfig;
|
|
8
11
|
return async (req, res) => {
|
|
9
|
-
if (!req.validateEnvironmentRequest(
|
|
12
|
+
if (!req.validateEnvironmentRequest(appConfig)) {
|
|
10
13
|
res.status(400);
|
|
11
14
|
res.send(descriptions.UNRESOLVABLE.INVALID_ENVIRONMENT(req.params.environment).message);
|
|
12
15
|
return;
|
|
@@ -18,7 +21,6 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
18
21
|
}
|
|
19
22
|
const { runtimeEnvironment, runtimeParams } = req.getRuntimeContext(context.runtimeEnvironment);
|
|
20
23
|
// set the default environment if an environment is configured in the app config
|
|
21
|
-
const { environment: environmentConfig } = context.appConfig;
|
|
22
24
|
if (!runtimeParams.environment && environmentConfig?.default) {
|
|
23
25
|
runtimeParams.environment = environmentConfig.default;
|
|
24
26
|
}
|
|
@@ -32,7 +34,14 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
32
34
|
let viewResponse;
|
|
33
35
|
let resolvedRoute;
|
|
34
36
|
try {
|
|
35
|
-
viewResponse = await
|
|
37
|
+
viewResponse = await getTracer().trace({
|
|
38
|
+
name: RequestHandlerSpan.GetView,
|
|
39
|
+
attributes: {
|
|
40
|
+
view: route.id,
|
|
41
|
+
},
|
|
42
|
+
}, () => {
|
|
43
|
+
return resolve.call(viewHandler, viewRequest, route, runtimeEnvironment, runtimeParams);
|
|
44
|
+
});
|
|
36
45
|
resolvedRoute = route;
|
|
37
46
|
}
|
|
38
47
|
catch (err) {
|
|
@@ -42,7 +51,14 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
|
|
|
42
51
|
// Log Unexpected Routing Errors
|
|
43
52
|
logger.error(`[view-middleware] Route Error ${req.originalUrl}`);
|
|
44
53
|
logger.error(err);
|
|
45
|
-
viewResponse = await
|
|
54
|
+
viewResponse = await getTracer().trace({
|
|
55
|
+
name: RequestHandlerSpan.GetView,
|
|
56
|
+
attributes: {
|
|
57
|
+
view: errorRoute.id,
|
|
58
|
+
},
|
|
59
|
+
}, () => {
|
|
60
|
+
return resolve.call(viewHandler, viewRequest, errorRoute, runtimeEnvironment, runtimeParams);
|
|
61
|
+
});
|
|
46
62
|
resolvedRoute = errorRoute;
|
|
47
63
|
}
|
|
48
64
|
if (req.isSiteGeneration()) {
|
|
@@ -125,13 +141,20 @@ export function viewMiddleware(app, context) {
|
|
|
125
141
|
}
|
|
126
142
|
// Add localized routes
|
|
127
143
|
if (i18n.uriPattern === 'path-prefix') {
|
|
128
|
-
|
|
144
|
+
// Add a redirect handler for the default locale for each route /en-US/home -> 301 /home
|
|
145
|
+
const defaultLocalePaths = paths.map((routePath) => `/${i18n.defaultLocale}${routePath}`);
|
|
146
|
+
// Map all supported locale ids into an array. Filter out the default one. It will be handled separately
|
|
147
|
+
const supportedStr = i18n.locales
|
|
148
|
+
.map((l) => l.id)
|
|
149
|
+
.filter((id) => id !== i18n.defaultLocale)
|
|
150
|
+
.join('|');
|
|
129
151
|
paths.forEach((routePath) => {
|
|
130
152
|
const localizedPath = `/:locale(${supportedStr})${routePath}`;
|
|
131
|
-
logger.debug(`[view-middleware] Add localized path ${localizedPath}`);
|
|
132
153
|
paths.push(localizedPath);
|
|
133
154
|
});
|
|
155
|
+
addDefaultLocaleRedirects(i18n.defaultLocale, defaultLocalePaths, app);
|
|
134
156
|
}
|
|
157
|
+
logger.debug(`[view-middleware] Add view paths ${paths}`);
|
|
135
158
|
app.get(paths, handleErrors(createViewMiddleware(route, errorRoutes, context, viewHandler)));
|
|
136
159
|
}
|
|
137
160
|
// create and attach middleware for bootstrap configurations
|
|
@@ -140,4 +163,21 @@ export function viewMiddleware(app, context) {
|
|
|
140
163
|
// NOTE: a greedy `all` is used over `use` due to the way middleware is mounted in the server abstraction
|
|
141
164
|
app.get('/' + app.getRegexWildcard(), handleErrors(createNotFoundMiddleware(errorRoutes, context, viewHandler)));
|
|
142
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Adds a 301 redirect if attempting to route with default locale as the path prefix
|
|
168
|
+
*/
|
|
169
|
+
function addDefaultLocaleRedirects(defaultLocale, defaultLocalePaths, app) {
|
|
170
|
+
logger.debug(`[view-middleware] Add default localized paths ${defaultLocalePaths}`);
|
|
171
|
+
app.get(defaultLocalePaths, (req, res) => {
|
|
172
|
+
// Get the original URL path and split it into segments
|
|
173
|
+
let modifiedPath = req.originalUrl.replace(`/${defaultLocale}`, '');
|
|
174
|
+
// Make sure there is a leading slash. Redirect to '' causes an infinite loop.
|
|
175
|
+
if (modifiedPath.indexOf('/') !== 0) {
|
|
176
|
+
modifiedPath = `/${modifiedPath}`;
|
|
177
|
+
}
|
|
178
|
+
// Perform a 301 redirect to the modified URL
|
|
179
|
+
res.setHeader('Location', modifiedPath);
|
|
180
|
+
return res.sendStatus(301);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
143
183
|
//# sourceMappingURL=view-middleware.js.map
|
package/build/es/middleware.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { requestProcessorMiddleware } from './middleware/request-processor-middleware.js';
|
|
1
2
|
export { localeMiddleware } from './middleware/locale-middleware.js';
|
|
2
3
|
export { hmrMiddleware } from './middleware/hmr-middleware.js';
|
|
3
4
|
export { moduleMiddleware } from './middleware/module-middleware.js';
|
package/build/es/middleware.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// handler bundle size. For example, importing `@lwrjs/core` will pull in ALL `@lwrjs/server` dependencies
|
|
3
3
|
// which includes both `koa` and `express`. Importing `@lwrjs/core/middleware` will only pull in the
|
|
4
4
|
// middleware dependencies.
|
|
5
|
+
export { requestProcessorMiddleware } from './middleware/request-processor-middleware.js';
|
|
5
6
|
export { localeMiddleware } from './middleware/locale-middleware.js';
|
|
6
7
|
export { hmrMiddleware } from './middleware/hmr-middleware.js';
|
|
7
8
|
export { moduleMiddleware } from './middleware/module-middleware.js';
|
|
@@ -2,14 +2,14 @@ import SiteGenerator from './static-generation.js';
|
|
|
2
2
|
import { skipDirCreation } from './utils/dir.js';
|
|
3
3
|
import NetworkDispatcher from './utils/network-dispatcher.js';
|
|
4
4
|
import { getRuntimeEnvironment } from '@lwrjs/config';
|
|
5
|
-
import { logger, WARN, INFO } from '@lwrjs/
|
|
5
|
+
import { logger, WARN, INFO } from '@lwrjs/diagnostics';
|
|
6
6
|
export async function warmupServer(config, internalRequestKey) {
|
|
7
7
|
// De-duplicate warming messages if log level is warn or info
|
|
8
8
|
if (!logger.currentLevel || logger.currentLevel == WARN || logger.currentLevel == INFO) {
|
|
9
9
|
logger.setOptions({ dedupe: new Set([WARN]) });
|
|
10
10
|
}
|
|
11
11
|
logger.info('[Server Warmup] starting');
|
|
12
|
-
const {
|
|
12
|
+
const { basePath, port, routes, staticSiteGenerator } = config;
|
|
13
13
|
staticSiteGenerator.outputDir = skipDirCreation;
|
|
14
14
|
const urlRewriteMap = new Map();
|
|
15
15
|
const runtimeEnvironment = getRuntimeEnvironment(config);
|
|
@@ -15,6 +15,10 @@ export default class SiteGenerator {
|
|
|
15
15
|
* Crawl all view routes for a site
|
|
16
16
|
*/
|
|
17
17
|
generateRoutes(runtimeEnvironment: RuntimeEnvironment, staticSiteGenerator: StaticSiteGenerator, routes: LwrRoute[], basePath: string, dispatcher: LwrDispatcher, outputDir: string, urlRewriteMap?: Map<string, string>): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Generate all routes for a given locale
|
|
20
|
+
*/
|
|
21
|
+
private generateRoutesForLocale;
|
|
18
22
|
/**
|
|
19
23
|
* Creates a function to dispatch the root requests for a given view url
|
|
20
24
|
*/
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { performance } from 'perf_hooks';
|
|
2
|
-
import {
|
|
2
|
+
import { logger, WARN, INFO } from '@lwrjs/diagnostics';
|
|
3
|
+
import { getSpecifier, getFeatureFlags, hashContent, isSelfUrl, getModuleUriPrefix, getMappingUriPrefix, isExternalUrl, mimeLookup, getViewUri, sortLocalesByFallback, } from '@lwrjs/shared-utils';
|
|
3
4
|
import { SiteMetadataImpl } from '@lwrjs/static/site-metadata';
|
|
4
5
|
import { join, dirname, extname, normalize } from 'path';
|
|
5
6
|
import fs from 'fs-extra';
|
|
6
7
|
import { writeResponse } from './utils/stream.js';
|
|
7
|
-
import {
|
|
8
|
+
import { createResourceDir } from './utils/dir.js';
|
|
8
9
|
import { getRuntimeEnvironment } from '@lwrjs/config';
|
|
9
10
|
export default class SiteGenerator {
|
|
10
11
|
/**
|
|
@@ -23,7 +24,7 @@ export default class SiteGenerator {
|
|
|
23
24
|
if (!logger.currentLevel || logger.currentLevel == WARN || logger.currentLevel == INFO) {
|
|
24
25
|
logger.setOptions({ dedupe: new Set([WARN]) });
|
|
25
26
|
}
|
|
26
|
-
const {
|
|
27
|
+
const { assets, basePath, rootDir, routes, staticSiteGenerator } = config;
|
|
27
28
|
if (!staticSiteGenerator.outputDir) {
|
|
28
29
|
staticSiteGenerator.outputDir = 'site';
|
|
29
30
|
}
|
|
@@ -36,7 +37,6 @@ export default class SiteGenerator {
|
|
|
36
37
|
logger.info(`[SSG] Reusing existing output directory: ${outputDir}`);
|
|
37
38
|
}
|
|
38
39
|
const urlRewriteMap = new Map();
|
|
39
|
-
const { basePath } = config;
|
|
40
40
|
const runtimeEnvironment = getRuntimeEnvironment(config);
|
|
41
41
|
// For each locale, generate all the modules
|
|
42
42
|
logger.info(`[SSG] Building routes (this may take some time to complete)`);
|
|
@@ -53,43 +53,60 @@ export default class SiteGenerator {
|
|
|
53
53
|
* Crawl all view routes for a site
|
|
54
54
|
*/
|
|
55
55
|
async generateRoutes(runtimeEnvironment, staticSiteGenerator, routes, basePath, dispatcher, outputDir, urlRewriteMap = new Map()) {
|
|
56
|
-
if (!staticSiteGenerator.locales) {
|
|
57
|
-
staticSiteGenerator.locales = ['en-US'];
|
|
58
|
-
}
|
|
59
56
|
const generateUrl = this.createGenerateURLFunction(dispatcher);
|
|
60
57
|
// Note: generateUrl can consume a lot of memory so we need to do this sequentially
|
|
61
58
|
const { skipBaseDocumentGeneration = false } = staticSiteGenerator;
|
|
62
|
-
|
|
59
|
+
const i18n = runtimeEnvironment.i18n;
|
|
60
|
+
// If there is not a know URL pattern it is expected the app is accounting with the locale in the routes
|
|
61
|
+
if (!i18n.uriPattern) {
|
|
62
|
+
// eslint-disable-next-line no-await-in-loop
|
|
63
|
+
await this.generateRoutesForLocale(routes, outputDir, { id: i18n.defaultLocale }, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, basePath, generateUrl, staticSiteGenerator, dispatcher);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Run through locales in fallback sorted order
|
|
67
|
+
const sortedLocales = sortLocalesByFallback(i18n);
|
|
63
68
|
// Generate all the routes
|
|
64
|
-
for (const
|
|
65
|
-
|
|
69
|
+
for (const locale of sortedLocales) {
|
|
70
|
+
logger.debug(`[SSG] Generate routes of locale: ${locale.id}`);
|
|
66
71
|
// eslint-disable-next-line no-await-in-loop
|
|
67
|
-
await
|
|
68
|
-
}
|
|
69
|
-
// Generate any additional urls
|
|
70
|
-
if (staticSiteGenerator._additionalRoutePaths) {
|
|
71
|
-
for (const uri of staticSiteGenerator._additionalRoutePaths) {
|
|
72
|
-
const siteConfig = this.createSiteConfig(outputDir, locale, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment);
|
|
73
|
-
// eslint-disable-next-line no-await-in-loop
|
|
74
|
-
await generateUrl(uri, siteConfig);
|
|
75
|
-
}
|
|
72
|
+
await this.generateRoutesForLocale(routes, outputDir, locale, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, basePath, generateUrl, staticSiteGenerator, dispatcher);
|
|
76
73
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Generate all routes for a given locale
|
|
78
|
+
*/
|
|
79
|
+
async generateRoutesForLocale(routes, outputDir, locale, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, basePath, generateUrl, staticSiteGenerator, dispatcher) {
|
|
80
|
+
const i18n = runtimeEnvironment.i18n;
|
|
81
|
+
for (const route of routes) {
|
|
82
|
+
const siteConfig = this.createSiteConfig(outputDir, locale.id, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, i18n);
|
|
83
|
+
const localizedPath = getViewUri(route.path, basePath, locale.id, i18n);
|
|
84
|
+
// eslint-disable-next-line no-await-in-loop
|
|
85
|
+
await generateUrl(localizedPath, siteConfig);
|
|
86
|
+
}
|
|
87
|
+
// Generate any additional urls
|
|
88
|
+
if (staticSiteGenerator._additionalRoutePaths) {
|
|
89
|
+
for (const uri of staticSiteGenerator._additionalRoutePaths) {
|
|
90
|
+
const siteConfig = this.createSiteConfig(outputDir, locale.id, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, i18n);
|
|
91
|
+
// eslint-disable-next-line no-await-in-loop
|
|
92
|
+
await generateUrl(uri, siteConfig);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Handle _additionalModules specifiers
|
|
96
|
+
const { _additionalModules } = staticSiteGenerator;
|
|
97
|
+
if (_additionalModules) {
|
|
98
|
+
for (const specifier of _additionalModules) {
|
|
99
|
+
logger.debug(`[SSG] Additional Module: ${locale.id} ${specifier}`);
|
|
100
|
+
const startTime = performance.now();
|
|
101
|
+
const siteConfig = this.createSiteConfig(outputDir, locale.id, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, i18n);
|
|
102
|
+
// eslint-disable-next-line no-await-in-loop
|
|
103
|
+
await this.dispatchJSResourceRecursive(specifier, dispatcher, siteConfig, true);
|
|
104
|
+
// Capture any additional collected metadata
|
|
105
|
+
// eslint-disable-next-line no-await-in-loop
|
|
106
|
+
await this.captureAdditionalRouteMetadata(siteConfig);
|
|
107
|
+
const endTime = performance.now();
|
|
108
|
+
const timeDiff = endTime - startTime;
|
|
109
|
+
logger.info(`[SSG] Additional Module ${locale.id} ${specifier} in ${Math.round(timeDiff)} ms`);
|
|
93
110
|
}
|
|
94
111
|
}
|
|
95
112
|
}
|
|
@@ -233,13 +250,18 @@ export default class SiteGenerator {
|
|
|
233
250
|
}
|
|
234
251
|
addBundleToSiteMetadata(bundleDefinition, url, siteConfig) {
|
|
235
252
|
if (siteConfig.siteMetadata) {
|
|
236
|
-
const
|
|
253
|
+
const locale = siteConfig.locale;
|
|
254
|
+
const specifier = siteConfig.i18n.defaultLocale === locale
|
|
255
|
+
? bundleDefinition.specifier
|
|
256
|
+
: `${bundleDefinition.specifier}|l/${locale}`;
|
|
237
257
|
const imports = bundleDefinition.bundleRecord.imports?.map((moduleRef) => getSpecifier(moduleRef)) || [];
|
|
258
|
+
const dynamicImports = bundleDefinition.bundleRecord.dynamicImports?.map((moduleRef) => getSpecifier(moduleRef));
|
|
238
259
|
const bundleMetadata = {
|
|
239
260
|
version: bundleDefinition.version,
|
|
240
261
|
path: decodeURIComponent(url),
|
|
241
262
|
includedModules: bundleDefinition.bundleRecord.includedModules || [],
|
|
242
263
|
imports,
|
|
264
|
+
dynamicImports,
|
|
243
265
|
};
|
|
244
266
|
const siteBundles = siteConfig.siteMetadata.getSiteBundles().bundles;
|
|
245
267
|
siteBundles[specifier] = bundleMetadata;
|
|
@@ -343,24 +365,15 @@ export default class SiteGenerator {
|
|
|
343
365
|
directoryPath = url.substring(0, lastPathIndex);
|
|
344
366
|
}
|
|
345
367
|
const dir = createResourceDir(directoryPath, outputDir);
|
|
346
|
-
const localeDir = createResourceDir(directoryPath, join(outputDir, siteConfig.locale));
|
|
347
368
|
// TODO: Should we handle routes with non-html extensions differently?
|
|
348
369
|
// Example Route: "path": "/mixed_templates.md" (not sure why you would do this)
|
|
349
370
|
// "contentTemplate": "$contentDir/composed_markdown.md"
|
|
350
371
|
// Today this will get written to /mixed_templates.md/index.html
|
|
351
372
|
// Which we workaround by setting "renderSingle": true in serve.json
|
|
352
373
|
const filePath = join(dir, fileName);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (siteConfig.locale.toLowerCase().startsWith('en')) {
|
|
357
|
-
siteConfig.viewPaths.add(filePath);
|
|
358
|
-
await writeResponse(context, filePath);
|
|
359
|
-
}
|
|
360
|
-
// Language path (always write out)
|
|
361
|
-
createDir(localeDir);
|
|
362
|
-
siteConfig.viewPaths.add(fileLocalePath);
|
|
363
|
-
await writeResponse(context, fileLocalePath);
|
|
374
|
+
// Write out response
|
|
375
|
+
siteConfig.viewPaths.add(filePath);
|
|
376
|
+
await writeResponse(context, filePath);
|
|
364
377
|
}
|
|
365
378
|
// Get the metadata
|
|
366
379
|
const viewDefinition = context.fs?.metadata?.viewDefinition;
|
|
@@ -549,7 +562,7 @@ export default class SiteGenerator {
|
|
|
549
562
|
const { basePath } = config;
|
|
550
563
|
const runtimeEnvironment = getRuntimeEnvironment(config);
|
|
551
564
|
const siteConfig = this.createSiteConfig(outputDir, 'en-US', // Copy Assets should not use the locale
|
|
552
|
-
new Map(), true, runtimeEnvironment);
|
|
565
|
+
new Map(), true, runtimeEnvironment, config.i18n);
|
|
553
566
|
for (const asset of assets) {
|
|
554
567
|
try {
|
|
555
568
|
const assetSrcFile = asset.file;
|
|
@@ -614,14 +627,14 @@ export default class SiteGenerator {
|
|
|
614
627
|
this.addAssetToSiteMetadata({
|
|
615
628
|
uri,
|
|
616
629
|
type: 'asset',
|
|
617
|
-
stream: function (
|
|
630
|
+
stream: function (_encoding) {
|
|
618
631
|
throw new Error('Function not implemented.');
|
|
619
632
|
},
|
|
620
633
|
entry: filePath,
|
|
621
634
|
ext: extname(filePath),
|
|
622
635
|
mime: mimeLookup(filePath),
|
|
623
636
|
ownHash: 'not-provided',
|
|
624
|
-
content: function (
|
|
637
|
+
content: function (_encoding) {
|
|
625
638
|
throw new Error('Function not implemented.');
|
|
626
639
|
},
|
|
627
640
|
}, uri, siteConfig);
|
|
@@ -633,7 +646,7 @@ export default class SiteGenerator {
|
|
|
633
646
|
/**
|
|
634
647
|
* Create a new site config for the current view
|
|
635
648
|
*/
|
|
636
|
-
createSiteConfig(outputDir, locale, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment) {
|
|
649
|
+
createSiteConfig(outputDir, locale, urlRewriteMap, skipBaseDocumentGeneration, runtimeEnvironment, i18n) {
|
|
637
650
|
const featureFlags = this.filterFeatureFlags();
|
|
638
651
|
const endpoints = {
|
|
639
652
|
uris: {
|
|
@@ -653,6 +666,7 @@ export default class SiteGenerator {
|
|
|
653
666
|
// Only include LEGACY_LOADER if true
|
|
654
667
|
...featureFlags,
|
|
655
668
|
siteMetadata: new SiteMetadataImpl({ rootDir: outputDir }),
|
|
669
|
+
i18n,
|
|
656
670
|
};
|
|
657
671
|
}
|
|
658
672
|
filterFeatureFlags() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Endpoints, FeatureFlags, ImportMetadata, RenderedAssetReference, SiteMetadata } from '@lwrjs/types';
|
|
1
|
+
import type { Endpoints, FeatureFlags, I18NConfig, ImportMetadata, RenderedAssetReference, SiteMetadata } from '@lwrjs/types';
|
|
2
2
|
export interface BaseResourceContextOpts {
|
|
3
3
|
resourceType: 'route' | 'asset' | 'js' | 'resource' | 'mapping';
|
|
4
4
|
}
|
|
@@ -36,6 +36,7 @@ export interface SiteConfig {
|
|
|
36
36
|
viewPaths: Set<string>;
|
|
37
37
|
visitedUrls: Set<string>;
|
|
38
38
|
locale: string;
|
|
39
|
+
i18n: I18NConfig;
|
|
39
40
|
urlRewriteMap: Map<string, string>;
|
|
40
41
|
endpoints?: Endpoints;
|
|
41
42
|
importMetadata?: ViewImportMetadata;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
import https from 'https';
|
|
3
|
-
import {
|
|
3
|
+
import { logger, DEBUG, VERBOSE } from '@lwrjs/diagnostics';
|
|
4
|
+
import { isModuleOrBundleUrl } from '@lwrjs/shared-utils';
|
|
4
5
|
export default class NetworkDispatcher {
|
|
5
6
|
constructor(port, internalRequestKey) {
|
|
6
7
|
this.port = port || 3000;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.11.0
|
|
7
|
+
"version": "0.11.0",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -39,31 +39,33 @@
|
|
|
39
39
|
"build": "tsc -b"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@lwrjs/app-service": "0.11.0
|
|
43
|
-
"@lwrjs/asset-registry": "0.11.0
|
|
44
|
-
"@lwrjs/asset-transformer": "0.11.0
|
|
45
|
-
"@lwrjs/base-view-provider": "0.11.0
|
|
46
|
-
"@lwrjs/base-view-transformer": "0.11.0
|
|
47
|
-
"@lwrjs/client-modules": "0.11.0
|
|
48
|
-
"@lwrjs/config": "0.11.0
|
|
49
|
-
"@lwrjs/diagnostics": "0.11.0
|
|
50
|
-
"@lwrjs/
|
|
51
|
-
"@lwrjs/
|
|
52
|
-
"@lwrjs/
|
|
53
|
-
"@lwrjs/
|
|
54
|
-
"@lwrjs/
|
|
55
|
-
"@lwrjs/
|
|
56
|
-
"@lwrjs/module-
|
|
57
|
-
"@lwrjs/
|
|
58
|
-
"@lwrjs/
|
|
59
|
-
"@lwrjs/
|
|
60
|
-
"@lwrjs/
|
|
61
|
-
"@lwrjs/
|
|
62
|
-
"@lwrjs/
|
|
63
|
-
"@lwrjs/
|
|
64
|
-
"@lwrjs/
|
|
65
|
-
"@lwrjs/
|
|
66
|
-
"@lwrjs/
|
|
42
|
+
"@lwrjs/app-service": "0.11.0",
|
|
43
|
+
"@lwrjs/asset-registry": "0.11.0",
|
|
44
|
+
"@lwrjs/asset-transformer": "0.11.0",
|
|
45
|
+
"@lwrjs/base-view-provider": "0.11.0",
|
|
46
|
+
"@lwrjs/base-view-transformer": "0.11.0",
|
|
47
|
+
"@lwrjs/client-modules": "0.11.0",
|
|
48
|
+
"@lwrjs/config": "0.11.0",
|
|
49
|
+
"@lwrjs/diagnostics": "0.11.0",
|
|
50
|
+
"@lwrjs/esbuild": "0.11.0",
|
|
51
|
+
"@lwrjs/fs-asset-provider": "0.11.0",
|
|
52
|
+
"@lwrjs/fs-watch": "0.11.0",
|
|
53
|
+
"@lwrjs/html-view-provider": "0.11.0",
|
|
54
|
+
"@lwrjs/instrumentation": "0.11.0",
|
|
55
|
+
"@lwrjs/loader": "0.11.0",
|
|
56
|
+
"@lwrjs/lwc-module-provider": "0.11.0",
|
|
57
|
+
"@lwrjs/markdown-view-provider": "0.11.0",
|
|
58
|
+
"@lwrjs/module-bundler": "0.11.0",
|
|
59
|
+
"@lwrjs/module-registry": "0.11.0",
|
|
60
|
+
"@lwrjs/npm-module-provider": "0.11.0",
|
|
61
|
+
"@lwrjs/nunjucks-view-provider": "0.11.0",
|
|
62
|
+
"@lwrjs/o11y": "0.11.0",
|
|
63
|
+
"@lwrjs/resource-registry": "0.11.0",
|
|
64
|
+
"@lwrjs/router": "0.11.0",
|
|
65
|
+
"@lwrjs/server": "0.11.0",
|
|
66
|
+
"@lwrjs/shared-utils": "0.11.0",
|
|
67
|
+
"@lwrjs/static": "0.11.0",
|
|
68
|
+
"@lwrjs/view-registry": "0.11.0",
|
|
67
69
|
"chokidar": "^3.5.3",
|
|
68
70
|
"esbuild": "^0.9.7",
|
|
69
71
|
"fs-extra": "^11.1.1",
|
|
@@ -73,11 +75,11 @@
|
|
|
73
75
|
"ws": "^8.8.1"
|
|
74
76
|
},
|
|
75
77
|
"devDependencies": {
|
|
76
|
-
"@lwrjs/types": "0.11.0
|
|
78
|
+
"@lwrjs/types": "0.11.0",
|
|
77
79
|
"@types/ws": "^8.5.3"
|
|
78
80
|
},
|
|
79
81
|
"peerDependencies": {
|
|
80
|
-
"lwc": "2.x || 3.x"
|
|
82
|
+
"lwc": "2.x || 3.x || 4.x"
|
|
81
83
|
},
|
|
82
84
|
"engines": {
|
|
83
85
|
"node": ">=16.0.0"
|
|
@@ -85,5 +87,5 @@
|
|
|
85
87
|
"volta": {
|
|
86
88
|
"extends": "../../../package.json"
|
|
87
89
|
},
|
|
88
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "fbc883ea90a12672ce6f1adc2201144fda8762bd"
|
|
89
91
|
}
|