@ecopages/core 0.2.0-beta.5 → 0.2.0-beta.7
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/package.json +2 -2
- package/src/adapters/shared/server-static-builder.d.ts +0 -1
- package/src/adapters/shared/server-static-builder.js +0 -16
- package/src/build/rolldown-adapter-helpers.js +42 -3
- package/src/build/runtime-build-output-normalizer.d.ts +7 -0
- package/src/build/runtime-build-output-normalizer.js +85 -1
- package/src/static-site-generator/static-site-generator.d.ts +1 -13
- package/src/static-site-generator/static-site-generator.js +23 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/core",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.7",
|
|
4
4
|
"description": "Core package for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"directory": "packages/core"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ecopages/file-system": "0.2.0-beta.
|
|
20
|
+
"@ecopages/file-system": "0.2.0-beta.7",
|
|
21
21
|
"@ecopages/logger": "^0.2.3",
|
|
22
22
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
23
23
|
"@oxc-project/runtime": "0.134.0",
|
|
@@ -55,7 +55,6 @@ export declare class ServerStaticBuilder {
|
|
|
55
55
|
private readonly previewServerFactory;
|
|
56
56
|
private readonly entryFile;
|
|
57
57
|
constructor({ appConfig, staticSiteGenerator, serveOptions, apiHandlers, logger, previewServerFactory, entryFile, }: ServerStaticBuilderParams);
|
|
58
|
-
private warnApiHandlersUnavailableInStaticMode;
|
|
59
58
|
private prepareExportDirectory;
|
|
60
59
|
private refreshRuntimeAssets;
|
|
61
60
|
/**
|
|
@@ -30,21 +30,6 @@ class ServerStaticBuilder {
|
|
|
30
30
|
this.previewServerFactory = previewServerFactory ?? StaticContentServer;
|
|
31
31
|
this.entryFile = resolveEntryFile({ entryFile });
|
|
32
32
|
}
|
|
33
|
-
warnApiHandlersUnavailableInStaticMode() {
|
|
34
|
-
if (this.apiHandlers.length === 0) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const uniqueHandlers = Array.from(
|
|
38
|
-
new Set(this.apiHandlers.map((handler) => `${handler.method} ${handler.path}`))
|
|
39
|
-
);
|
|
40
|
-
const visibleHandlers = uniqueHandlers.slice(0, 5).join(", ");
|
|
41
|
-
const remainingCount = uniqueHandlers.length - Math.min(uniqueHandlers.length, 5);
|
|
42
|
-
const summary = remainingCount > 0 ? `${visibleHandlers}, +${remainingCount} more` : visibleHandlers;
|
|
43
|
-
this.logger.warn(
|
|
44
|
-
"Registered API endpoints are not available in static build or preview modes because no server runtime is started. They are excluded from the generated output.\n",
|
|
45
|
-
`\u27A4 ${summary}`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
33
|
prepareExportDirectory() {
|
|
49
34
|
const exportDir = this.appConfig.absolutePaths?.distDir ?? path.join(this.appConfig.rootDir, this.appConfig.distDir);
|
|
50
35
|
fileSystem.ensureDir(exportDir, true);
|
|
@@ -131,7 +116,6 @@ ${errorMessages}`);
|
|
|
131
116
|
async build(options, dependencies) {
|
|
132
117
|
const { preview = false, baseUrl: explicitBaseUrl } = options ?? {};
|
|
133
118
|
const baseUrl = explicitBaseUrl ?? `http://${this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME}:${this.serveOptions.port || DEFAULT_ECOPAGES_PORT}`;
|
|
134
|
-
this.warnApiHandlersUnavailableInStaticMode();
|
|
135
119
|
this.prepareExportDirectory();
|
|
136
120
|
await this.refreshRuntimeAssets();
|
|
137
121
|
await this.bundleServerEntry();
|
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { collectBrowserRuntimeImportRewriteMap, rewriteBrowserRuntimeImports } from "./browser-runtime-plugin.js";
|
|
4
5
|
import { createServerSideCssShimPlugin } from "./server-side-css-shim-plugin.js";
|
|
5
6
|
import { createRolldownPluginBridge } from "./rolldown-plugin-bridge.js";
|
|
6
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
isDeclaredAppPackageImport,
|
|
9
|
+
isWorkspacePackageImport,
|
|
10
|
+
normalizeNodeRuntimeBuildOutputs
|
|
11
|
+
} from "./runtime-build-output-normalizer.js";
|
|
7
12
|
const corePackageRequire = createRequire(new URL("../../package.json", import.meta.url));
|
|
13
|
+
let corePackageNames;
|
|
14
|
+
function getCorePackageNames() {
|
|
15
|
+
if (corePackageNames) {
|
|
16
|
+
return corePackageNames;
|
|
17
|
+
}
|
|
18
|
+
const packageJsonPath = new URL("../../package.json", import.meta.url);
|
|
19
|
+
corePackageNames = /* @__PURE__ */ new Set();
|
|
20
|
+
try {
|
|
21
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
22
|
+
for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
23
|
+
const entries = packageJson[field];
|
|
24
|
+
if (!entries || typeof entries !== "object") {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
for (const name of Object.keys(entries)) {
|
|
28
|
+
corePackageNames.add(name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
return corePackageNames;
|
|
34
|
+
}
|
|
35
|
+
function isCoreDeclaredPackageImport(specifier) {
|
|
36
|
+
const name = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0] ?? specifier;
|
|
37
|
+
return getCorePackageNames().has(name);
|
|
38
|
+
}
|
|
8
39
|
function transpileProfileToOptions(profile) {
|
|
9
40
|
switch (profile) {
|
|
10
41
|
case "browser-script":
|
|
@@ -37,13 +68,21 @@ function getAppRootRequire(cache, contextRoot) {
|
|
|
37
68
|
return req;
|
|
38
69
|
}
|
|
39
70
|
function shouldBundlePackageImport(id, contextRoot, appRootRequireCache) {
|
|
71
|
+
if (isWorkspacePackageImport(id, contextRoot)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
40
74
|
if (isDeclaredAppPackageImport(id, contextRoot)) {
|
|
41
75
|
const appRootRequire = getAppRootRequire(appRootRequireCache, contextRoot);
|
|
42
76
|
const appResolvedPath = tryResolveModule(id, appRootRequire);
|
|
43
77
|
return Boolean(appResolvedPath && /\.(?:[cm]?ts|tsx|jsx)$/u.test(appResolvedPath));
|
|
44
78
|
}
|
|
45
|
-
|
|
46
|
-
|
|
79
|
+
if (isCoreDeclaredPackageImport(id)) {
|
|
80
|
+
const coreResolvedPath = tryResolveModule(id, corePackageRequire);
|
|
81
|
+
if (coreResolvedPath && !/\.(?:[cm]?ts|tsx|jsx)$/u.test(coreResolvedPath)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
47
86
|
}
|
|
48
87
|
function createExternalMatcher(options, appRootRequireCache) {
|
|
49
88
|
const explicitExternals = new Set(options.external ?? []);
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if the given specifier is a workspace package.
|
|
3
|
+
*
|
|
4
|
+
* Workspace packages are declared with the `workspace:` protocol and are
|
|
5
|
+
* typically source-only, requiring bundling rather than externalization.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isWorkspacePackageImport(specifier: string, rootDir: string): boolean;
|
|
1
8
|
export declare function isDeclaredAppPackageImport(specifier: string, rootDir: string): boolean;
|
|
2
9
|
export declare function normalizeNodeRuntimeBuildOutputFile(filePath: string, rootDir: string): void;
|
|
3
10
|
export declare function normalizeNodeRuntimeBuildOutputs(outputPaths: string[], rootDir: string): void;
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
const corePackageRequire = createRequire(new URL("../../package.json", import.meta.url));
|
|
6
6
|
const appDeclaredPackageCache = /* @__PURE__ */ new Map();
|
|
7
|
+
const appWorkspacePackageCache = /* @__PURE__ */ new Map();
|
|
7
8
|
const CORE_RUNTIME_BARE_SPECIFIER_PACKAGES = /* @__PURE__ */ new Set(["ws"]);
|
|
8
9
|
function tryResolveRuntimeImport(specifier, resolver) {
|
|
9
10
|
try {
|
|
@@ -15,6 +16,24 @@ function tryResolveRuntimeImport(specifier, resolver) {
|
|
|
15
16
|
function isBareRuntimeImport(specifier) {
|
|
16
17
|
return !specifier.startsWith(".") && !path.isAbsolute(specifier) && !specifier.startsWith("/") && !specifier.startsWith("node:") && !specifier.startsWith("@/") && !specifier.startsWith("~/") && !specifier.startsWith("#") && !specifier.includes(":");
|
|
17
18
|
}
|
|
19
|
+
function extractPackageNameFromFileUrl(specifier) {
|
|
20
|
+
if (!specifier.startsWith("file://")) {
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
const lastNodeModulesIndex = specifier.lastIndexOf("/node_modules/");
|
|
24
|
+
if (lastNodeModulesIndex === -1) {
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
const afterNodeModules = specifier.slice(lastNodeModulesIndex + "/node_modules/".length);
|
|
28
|
+
const parts = afterNodeModules.split("/");
|
|
29
|
+
if (parts.length === 0) {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
if (parts[0]?.startsWith("@") && parts.length > 1) {
|
|
33
|
+
return `${parts[0]}/${parts[1]}`;
|
|
34
|
+
}
|
|
35
|
+
return parts[0];
|
|
36
|
+
}
|
|
18
37
|
function getPackageNameFromSpecifier(specifier) {
|
|
19
38
|
if (specifier.startsWith("@")) {
|
|
20
39
|
return specifier.split("/").slice(0, 2).join("/");
|
|
@@ -47,6 +66,37 @@ function getDeclaredAppPackages(rootDir) {
|
|
|
47
66
|
appDeclaredPackageCache.set(cacheKey, declaredPackages);
|
|
48
67
|
return declaredPackages;
|
|
49
68
|
}
|
|
69
|
+
function getWorkspacePackages(rootDir) {
|
|
70
|
+
const cacheKey = path.resolve(rootDir);
|
|
71
|
+
const cached = appWorkspacePackageCache.get(cacheKey);
|
|
72
|
+
if (cached) {
|
|
73
|
+
return cached;
|
|
74
|
+
}
|
|
75
|
+
const packageJsonPath = path.resolve(rootDir, "package.json");
|
|
76
|
+
const workspacePackages = /* @__PURE__ */ new Set();
|
|
77
|
+
try {
|
|
78
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
79
|
+
for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
80
|
+
const entries = packageJson[field];
|
|
81
|
+
if (!entries || typeof entries !== "object") {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
for (const [packageName, version] of Object.entries(entries)) {
|
|
85
|
+
if (typeof version === "string" && version.startsWith("workspace:")) {
|
|
86
|
+
workspacePackages.add(packageName);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
appWorkspacePackageCache.set(cacheKey, workspacePackages);
|
|
92
|
+
return workspacePackages;
|
|
93
|
+
}
|
|
94
|
+
appWorkspacePackageCache.set(cacheKey, workspacePackages);
|
|
95
|
+
return workspacePackages;
|
|
96
|
+
}
|
|
97
|
+
function isWorkspacePackageImport(specifier, rootDir) {
|
|
98
|
+
return getWorkspacePackages(rootDir).has(getPackageNameFromSpecifier(specifier));
|
|
99
|
+
}
|
|
50
100
|
function isDeclaredAppPackageImport(specifier, rootDir) {
|
|
51
101
|
return getDeclaredAppPackages(rootDir).has(getPackageNameFromSpecifier(specifier));
|
|
52
102
|
}
|
|
@@ -75,6 +125,23 @@ function rewriteRuntimeBuildOutputImports(code, rootDir) {
|
|
|
75
125
|
const rewrittenSpecifier = rewriteRuntimeImportSpecifier(specifier, quote, rootDir);
|
|
76
126
|
return `${prefix}${rewrittenSpecifier ?? `${quote}${specifier}${quote}`}`;
|
|
77
127
|
};
|
|
128
|
+
const rewriteFileUrl = (prefix, quote, specifier) => {
|
|
129
|
+
const packageName = extractPackageNameFromFileUrl(specifier);
|
|
130
|
+
if (!packageName) {
|
|
131
|
+
return `${prefix}${quote}${specifier}${quote}`;
|
|
132
|
+
}
|
|
133
|
+
if (!isDeclaredInResolutionChain(packageName, rootDir)) {
|
|
134
|
+
return `${prefix}${quote}${specifier}${quote}`;
|
|
135
|
+
}
|
|
136
|
+
const lastNodeModulesIndex = specifier.lastIndexOf("/node_modules/");
|
|
137
|
+
if (lastNodeModulesIndex === -1) {
|
|
138
|
+
return `${prefix}${quote}${specifier}${quote}`;
|
|
139
|
+
}
|
|
140
|
+
const afterNodeModules = specifier.slice(lastNodeModulesIndex + "/node_modules/".length);
|
|
141
|
+
const afterPackage = afterNodeModules.slice(packageName.length);
|
|
142
|
+
const bareSpecifier = packageName + afterPackage;
|
|
143
|
+
return `${prefix}${quote}${bareSpecifier}${quote}`;
|
|
144
|
+
};
|
|
78
145
|
const withResolvedPackages = code.replace(
|
|
79
146
|
/(\bfrom\s+)(['"])([^'"\\]+)\2/g,
|
|
80
147
|
(_match, prefix, quote, specifier) => rewriteSpecifier(prefix, quote, specifier)
|
|
@@ -85,7 +152,17 @@ function rewriteRuntimeBuildOutputImports(code, rootDir) {
|
|
|
85
152
|
/(\bimport\s*\(\s*)(['"])([^'"\\]+)\2/g,
|
|
86
153
|
(_match, prefix, quote, specifier) => rewriteSpecifier(prefix, quote, specifier)
|
|
87
154
|
);
|
|
88
|
-
|
|
155
|
+
const withBareSpecifiers = withResolvedPackages.replace(
|
|
156
|
+
/(\bfrom\s+)(['"])(file:\/\/[^'"\\]+)\2/g,
|
|
157
|
+
(_match, prefix, quote, specifier) => rewriteFileUrl(prefix, quote, specifier)
|
|
158
|
+
).replace(
|
|
159
|
+
/(\bimport\s+)(['"])(file:\/\/[^'"\\]+)\2/g,
|
|
160
|
+
(_match, prefix, quote, specifier) => rewriteFileUrl(prefix, quote, specifier)
|
|
161
|
+
).replace(
|
|
162
|
+
/(\bimport\s*\(\s*)(['"])(file:\/\/[^'"\\]+)\2/g,
|
|
163
|
+
(_match, prefix, quote, specifier) => rewriteFileUrl(prefix, quote, specifier)
|
|
164
|
+
);
|
|
165
|
+
return withBareSpecifiers.replace(
|
|
89
166
|
/(['"])(@oxc-project\/runtime\/(?:helpers(?:\/esm)?\/[^'"\\]+))\1/g,
|
|
90
167
|
(match, quote, specifier) => {
|
|
91
168
|
const resolvedPath = tryResolveRuntimeImport(specifier, corePackageRequire);
|
|
@@ -94,6 +171,9 @@ function rewriteRuntimeBuildOutputImports(code, rootDir) {
|
|
|
94
171
|
);
|
|
95
172
|
}
|
|
96
173
|
function normalizeNodeRuntimeBuildOutputFile(filePath, rootDir) {
|
|
174
|
+
if (process.env.ECOPAGES_LOGGER_DEBUG === "true") {
|
|
175
|
+
console.log(`[normalizeNodeRuntimeBuildOutputFile] Checking ${filePath}`);
|
|
176
|
+
}
|
|
97
177
|
if (!/\.(?:[cm]?js)$/u.test(filePath)) {
|
|
98
178
|
return;
|
|
99
179
|
}
|
|
@@ -104,6 +184,9 @@ function normalizeNodeRuntimeBuildOutputFile(filePath, rootDir) {
|
|
|
104
184
|
const code = fileSystem.readFileSync(filePath, "utf-8");
|
|
105
185
|
const rewritten = rewriteRuntimeBuildOutputImports(code, rootDir);
|
|
106
186
|
if (rewritten !== code) {
|
|
187
|
+
if (process.env.ECOPAGES_LOGGER_DEBUG === "true") {
|
|
188
|
+
console.log(`[normalizeNodeRuntimeBuildOutputFile] Rewriting ${filePath}`);
|
|
189
|
+
}
|
|
107
190
|
fileSystem.writeFileSync(filePath, rewritten);
|
|
108
191
|
}
|
|
109
192
|
}
|
|
@@ -114,6 +197,7 @@ function normalizeNodeRuntimeBuildOutputs(outputPaths, rootDir) {
|
|
|
114
197
|
}
|
|
115
198
|
export {
|
|
116
199
|
isDeclaredAppPackageImport,
|
|
200
|
+
isWorkspacePackageImport,
|
|
117
201
|
normalizeNodeRuntimeBuildOutputFile,
|
|
118
202
|
normalizeNodeRuntimeBuildOutputs
|
|
119
203
|
};
|
|
@@ -34,19 +34,7 @@ export declare class StaticSiteGenerator {
|
|
|
34
34
|
appConfig: EcoPagesAppConfig;
|
|
35
35
|
});
|
|
36
36
|
private getExportDir;
|
|
37
|
-
/**
|
|
38
|
-
* Logs the standardized warning emitted when a dynamic-cache page is skipped.
|
|
39
|
-
*/
|
|
40
|
-
private warnDynamicPageSkipped;
|
|
41
|
-
/**
|
|
42
|
-
* Determines whether one filesystem-discovered page should be excluded from
|
|
43
|
-
* static generation.
|
|
44
|
-
*/
|
|
45
37
|
private shouldSkipStaticPageFile;
|
|
46
|
-
/**
|
|
47
|
-
* Determines whether one explicit static route view should be excluded from
|
|
48
|
-
* static generation.
|
|
49
|
-
*/
|
|
50
38
|
private shouldSkipStaticView;
|
|
51
39
|
/**
|
|
52
40
|
* Writes the robots.txt file declared by the app config.
|
|
@@ -71,7 +59,7 @@ export declare class StaticSiteGenerator {
|
|
|
71
59
|
* issuing a request against the running server origin. Render-strategy routes
|
|
72
60
|
* go through the normal route renderer directly.
|
|
73
61
|
*/
|
|
74
|
-
generateStaticPages(router: StaticGenerationRouteSource, baseUrl: string, routeRendererFactory?: StaticPageRouteRendererFactory): Promise<void>;
|
|
62
|
+
generateStaticPages(router: StaticGenerationRouteSource, baseUrl: string, routeRendererFactory?: StaticPageRouteRendererFactory, skipped?: string[]): Promise<void>;
|
|
75
63
|
private resolveStaticFetchUrl;
|
|
76
64
|
/**
|
|
77
65
|
* Executes the full static-generation workflow for one app run.
|
|
@@ -21,39 +21,14 @@ class StaticSiteGenerator {
|
|
|
21
21
|
getExportDir() {
|
|
22
22
|
return this.appConfig.absolutePaths?.distDir ?? path.join(this.appConfig.rootDir, this.appConfig.distDir);
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Logs the standardized warning emitted when a dynamic-cache page is skipped.
|
|
26
|
-
*/
|
|
27
|
-
warnDynamicPageSkipped(filePath) {
|
|
28
|
-
appLogger.warn(
|
|
29
|
-
"Pages with cache: 'dynamic' are not supported in static generation or preview, so they will be skipped\n",
|
|
30
|
-
`\u27A4 ${filePath}`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Determines whether one filesystem-discovered page should be excluded from
|
|
35
|
-
* static generation.
|
|
36
|
-
*/
|
|
37
24
|
async shouldSkipStaticPageFile(filePath, routeRendererFactory) {
|
|
38
25
|
const module = await routeRendererFactory.getPageRenderer(filePath).loadPageModule(filePath, {
|
|
39
26
|
cacheScope: "static-page-probe"
|
|
40
27
|
});
|
|
41
|
-
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
this.warnDynamicPageSkipped(filePath);
|
|
45
|
-
return true;
|
|
28
|
+
return module.default?.cache === "dynamic";
|
|
46
29
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* static generation.
|
|
50
|
-
*/
|
|
51
|
-
shouldSkipStaticView(routePath, view) {
|
|
52
|
-
if (view.cache !== "dynamic") {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
this.warnDynamicPageSkipped(routePath);
|
|
56
|
-
return true;
|
|
30
|
+
shouldSkipStaticView(_routePath, view) {
|
|
31
|
+
return view.cache === "dynamic";
|
|
57
32
|
}
|
|
58
33
|
/**
|
|
59
34
|
* Writes the robots.txt file declared by the app config.
|
|
@@ -105,7 +80,7 @@ class StaticSiteGenerator {
|
|
|
105
80
|
const integration = this.appConfig.integrations.find((plugin) => plugin.extensions.includes(ext));
|
|
106
81
|
return integration?.staticBuildStep || "render";
|
|
107
82
|
}
|
|
108
|
-
async createFilesystemStaticContents(route, baseUrl, routeRendererFactory) {
|
|
83
|
+
async createFilesystemStaticContents(route, baseUrl, routeRendererFactory, skipped) {
|
|
109
84
|
const {
|
|
110
85
|
templateRoute: { filePath },
|
|
111
86
|
params
|
|
@@ -123,6 +98,7 @@ class StaticSiteGenerator {
|
|
|
123
98
|
throw new Error(STATIC_SITE_GENERATOR_ERRORS.ROUTE_RENDERER_FACTORY_REQUIRED);
|
|
124
99
|
}
|
|
125
100
|
if (await this.shouldSkipStaticPageFile(filePath, routeRendererFactory)) {
|
|
101
|
+
skipped?.push(filePath);
|
|
126
102
|
return null;
|
|
127
103
|
}
|
|
128
104
|
const renderer = routeRendererFactory.getPageRenderer(filePath);
|
|
@@ -147,7 +123,7 @@ class StaticSiteGenerator {
|
|
|
147
123
|
* issuing a request against the running server origin. Render-strategy routes
|
|
148
124
|
* go through the normal route renderer directly.
|
|
149
125
|
*/
|
|
150
|
-
async generateStaticPages(router, baseUrl, routeRendererFactory) {
|
|
126
|
+
async generateStaticPages(router, baseUrl, routeRendererFactory, skipped) {
|
|
151
127
|
const routes = await router.listStaticGenerationRoutes({ runtimeOrigin: baseUrl });
|
|
152
128
|
appLogger.debug(
|
|
153
129
|
"Static Pages",
|
|
@@ -156,7 +132,12 @@ class StaticSiteGenerator {
|
|
|
156
132
|
const directories = this.getDirectories(routes.map((route) => route.requestUrl));
|
|
157
133
|
for (const route of routes) {
|
|
158
134
|
try {
|
|
159
|
-
const contents = await this.createFilesystemStaticContents(
|
|
135
|
+
const contents = await this.createFilesystemStaticContents(
|
|
136
|
+
route,
|
|
137
|
+
baseUrl,
|
|
138
|
+
routeRendererFactory,
|
|
139
|
+
skipped
|
|
140
|
+
);
|
|
160
141
|
if (contents === null) {
|
|
161
142
|
continue;
|
|
162
143
|
}
|
|
@@ -189,17 +170,24 @@ class StaticSiteGenerator {
|
|
|
189
170
|
routeRendererFactory,
|
|
190
171
|
staticRoutes
|
|
191
172
|
}) {
|
|
173
|
+
const skippedDynamicPages = [];
|
|
192
174
|
this.generateRobotsTxt();
|
|
193
|
-
await this.generateStaticPages(router, baseUrl, routeRendererFactory);
|
|
175
|
+
await this.generateStaticPages(router, baseUrl, routeRendererFactory, skippedDynamicPages);
|
|
194
176
|
if (staticRoutes && staticRoutes.length > 0 && routeRendererFactory) {
|
|
195
|
-
await this.generateExplicitStaticPages(staticRoutes, routeRendererFactory);
|
|
177
|
+
await this.generateExplicitStaticPages(staticRoutes, routeRendererFactory, skippedDynamicPages);
|
|
178
|
+
}
|
|
179
|
+
if (skippedDynamicPages.length > 0) {
|
|
180
|
+
appLogger.debug(
|
|
181
|
+
`Skipped ${skippedDynamicPages.length} page(s) with cache: 'dynamic' (not supported in static generation)`,
|
|
182
|
+
skippedDynamicPages
|
|
183
|
+
);
|
|
196
184
|
}
|
|
197
185
|
}
|
|
198
186
|
/**
|
|
199
187
|
* Generates static pages from explicit static routes registered via app.static().
|
|
200
188
|
* These routes use eco.page views via loader functions for HMR support.
|
|
201
189
|
*/
|
|
202
|
-
async generateExplicitStaticPages(staticRoutes, routeRendererFactory) {
|
|
190
|
+
async generateExplicitStaticPages(staticRoutes, routeRendererFactory, skipped) {
|
|
203
191
|
appLogger.debug(
|
|
204
192
|
"Generating explicit static routes",
|
|
205
193
|
staticRoutes.map((r) => r.path)
|
|
@@ -209,6 +197,7 @@ class StaticSiteGenerator {
|
|
|
209
197
|
const mod = await route.loader();
|
|
210
198
|
const view = mod.default;
|
|
211
199
|
if (this.shouldSkipStaticView(route.path, view)) {
|
|
200
|
+
skipped?.push(route.path);
|
|
212
201
|
continue;
|
|
213
202
|
}
|
|
214
203
|
await this.generateExplicitStaticRoute(route.path, view, routeRendererFactory);
|