astro 7.1.6 → 7.2.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/dist/assets/build/generate.d.ts +8 -1
- package/dist/assets/build/generate.js +21 -1
- package/dist/assets/fonts/providers/index.js +12 -2
- package/dist/assets/types.d.ts +13 -0
- package/dist/assets/vite-plugin-assets.js +8 -0
- package/dist/cli/add/index.js +1 -1
- package/dist/cli/agent.d.ts +1 -0
- package/dist/cli/agent.js +11 -0
- package/dist/cli/dev/background.d.ts +3 -16
- package/dist/cli/dev/background.js +7 -93
- package/dist/cli/dev/index.d.ts +12 -0
- package/dist/cli/dev/index.js +30 -23
- package/dist/cli/dev/logs.js +2 -64
- package/dist/cli/dev/status.d.ts +2 -9
- package/dist/cli/dev/status.js +6 -24
- package/dist/cli/dev/stop.d.ts +2 -6
- package/dist/cli/dev/stop.js +6 -14
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/cli/install-package.js +1 -1
- package/dist/cli/preview/index.js +77 -3
- package/dist/cli/server.d.ts +60 -0
- package/dist/cli/server.js +274 -0
- package/dist/content/content-layer.js +3 -3
- package/dist/content/runtime.d.ts +2 -0
- package/dist/content/runtime.js +2 -0
- package/dist/content/types-generator.js +1 -0
- package/dist/content/vite-plugin-content-assets.js +6 -1
- package/dist/content/vite-plugin-content-imports.js +12 -3
- package/dist/content/vite-plugin-content-virtual-mod.js +28 -16
- package/dist/core/app/entrypoints/index.d.ts +2 -0
- package/dist/core/app/entrypoints/index.js +14 -0
- package/dist/core/build/config-hash/index.d.ts +8 -0
- package/dist/core/build/config-hash/index.js +23 -0
- package/dist/core/build/config-hash/input.d.ts +199 -0
- package/dist/core/build/config-hash/input.js +43 -0
- package/dist/core/build/generate.d.ts +3 -1
- package/dist/core/build/generate.js +149 -14
- package/dist/core/build/incremental-content-collector.d.ts +10 -0
- package/dist/core/build/incremental-content-collector.js +33 -0
- package/dist/core/build/incremental-image-collector.d.ts +11 -0
- package/dist/core/build/incremental-image-collector.js +32 -0
- package/dist/core/build/incremental-metadata.d.ts +9 -0
- package/dist/core/build/incremental-metadata.js +17 -0
- package/dist/core/build/incremental.d.ts +123 -0
- package/dist/core/build/incremental.js +178 -0
- package/dist/core/build/index.d.ts +3 -0
- package/dist/core/build/index.js +6 -2
- package/dist/core/build/internal.d.ts +19 -0
- package/dist/core/build/lockfile/finder.d.ts +22 -0
- package/dist/core/build/lockfile/finder.js +45 -0
- package/dist/core/build/lockfile/hasher.d.ts +16 -0
- package/dist/core/build/lockfile/hasher.js +46 -0
- package/dist/core/build/lockfile/index.d.ts +9 -0
- package/dist/core/build/lockfile/index.js +16 -0
- package/dist/core/build/plugins/index.js +3 -1
- package/dist/core/build/plugins/plugin-incremental.d.ts +14 -0
- package/dist/core/build/plugins/plugin-incremental.js +134 -0
- package/dist/core/build/types.d.ts +2 -0
- package/dist/core/config/schemas/base.d.ts +3 -2
- package/dist/core/config/schemas/base.js +1 -0
- package/dist/core/config/schemas/defaults.d.ts +1 -0
- package/dist/core/config/schemas/defaults.js +1 -0
- package/dist/core/config/schemas/relative.d.ts +7 -4
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +2 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/lockfile.d.ts +8 -7
- package/dist/core/dev/lockfile.js +13 -13
- package/dist/core/encryption.d.ts +6 -0
- package/dist/core/encryption.js +14 -2
- package/dist/core/errors/default-handler.js +4 -5
- package/dist/core/fetch/index.js +1 -1
- package/dist/core/logger/config.d.ts +1 -1
- package/dist/core/logger/load.d.ts +3 -1
- package/dist/core/logger/load.js +3 -3
- package/dist/core/logger/utils.d.ts +6 -4
- package/dist/core/logger/utils.js +13 -5
- package/dist/core/logger/vite-plugin.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/preview/static-preview-server.d.ts +2 -0
- package/dist/core/preview/static-preview-server.js +1 -0
- package/dist/core/routing/handler.js +1 -1
- package/dist/core/session/config.d.ts +2 -2
- package/dist/core/session/config.js +2 -1
- package/dist/core/session/provider-disabled.d.ts +2 -0
- package/dist/core/session/provider-disabled.js +7 -0
- package/dist/core/session/provider.d.ts +1 -0
- package/dist/core/session/provider.js +4 -0
- package/dist/core/session/utils.js +3 -0
- package/dist/core/session/vite-plugin.d.ts +3 -0
- package/dist/core/session/vite-plugin.js +41 -6
- package/dist/integrations/hooks.js +3 -1
- package/dist/runtime/prerender/static-paths.js +5 -1
- package/dist/runtime/server/render/util.js +3 -0
- package/dist/types/public/common.d.ts +1 -0
- package/dist/types/public/config.d.ts +59 -2
- package/dist/types/public/integrations.d.ts +29 -2
- package/dist/types/public/preview.d.ts +2 -0
- package/dist/vite-plugin-config-alias/index.js +1 -0
- package/dist/vite-plugin-environment/index.js +4 -1
- package/package.json +1 -2
|
@@ -12,15 +12,29 @@ import {
|
|
|
12
12
|
serializeRouteInfo
|
|
13
13
|
} from "../manifest.js";
|
|
14
14
|
import { AppPipeline } from "../pipeline.js";
|
|
15
|
+
import {
|
|
16
|
+
beginContentEntryCollection,
|
|
17
|
+
endContentEntryCollection
|
|
18
|
+
} from "../../build/incremental-content-collector.js";
|
|
19
|
+
import {
|
|
20
|
+
beginImageCollection,
|
|
21
|
+
endImageCollection,
|
|
22
|
+
recordStaticImage
|
|
23
|
+
} from "../../build/incremental-image-collector.js";
|
|
15
24
|
export {
|
|
16
25
|
App,
|
|
17
26
|
AppPipeline,
|
|
18
27
|
BaseApp,
|
|
28
|
+
beginContentEntryCollection,
|
|
29
|
+
beginImageCollection,
|
|
19
30
|
createConsoleLogger,
|
|
20
31
|
deserializeManifest,
|
|
21
32
|
deserializeRouteData,
|
|
22
33
|
deserializeRouteInfo,
|
|
34
|
+
endContentEntryCollection,
|
|
35
|
+
endImageCollection,
|
|
23
36
|
fromRoutingStrategy,
|
|
37
|
+
recordStaticImage,
|
|
24
38
|
serializeRouteData,
|
|
25
39
|
serializeRouteInfo,
|
|
26
40
|
toRoutingStrategy
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AstroConfig } from '../../../types/public/config.js';
|
|
2
|
+
export { getConfigHashInput } from './input.js';
|
|
3
|
+
/**
|
|
4
|
+
* Produce a sha256 over the output-affecting subset of the resolved config (see
|
|
5
|
+
* {@link getConfigHashInput}). A mismatch invalidates the whole incremental
|
|
6
|
+
* build cache.
|
|
7
|
+
*/
|
|
8
|
+
export declare function computeConfigHash(config: AstroConfig): Promise<string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { encodeHexLowerCase } from "@oslojs/encoding";
|
|
2
|
+
import { getConfigHashInput } from "./input.js";
|
|
3
|
+
import { getConfigHashInput as getConfigHashInput2 } from "./input.js";
|
|
4
|
+
function stableStringify(value) {
|
|
5
|
+
return JSON.stringify(value, (_key, val) => {
|
|
6
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
7
|
+
return Object.keys(val).sort().reduce((acc, key) => {
|
|
8
|
+
acc[key] = val[key];
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
12
|
+
return val;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function computeConfigHash(config) {
|
|
16
|
+
const input = stableStringify(getConfigHashInput(config));
|
|
17
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
|
|
18
|
+
return encodeHexLowerCase(new Uint8Array(digest));
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
computeConfigHash,
|
|
22
|
+
getConfigHashInput2 as getConfigHashInput
|
|
23
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { AstroConfig } from '../../../types/public/config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Projection of {@link AstroConfig} limited to values that can change the bytes
|
|
4
|
+
* or paths of a prerendered page. A change to any of these must invalidate the
|
|
5
|
+
* incremental build cache: the per-route dependency hash only sees module
|
|
6
|
+
* *source*, so it misses config baked into compiled output by the compiler
|
|
7
|
+
* (`compressHTML`, `site`, `scopedStyleStrategy`), inlined via Vite `define`
|
|
8
|
+
* (`base`, `build.assetsPrefix`), or serialized into virtual modules (`image`,
|
|
9
|
+
* `env.schema`, `i18n`).
|
|
10
|
+
*
|
|
11
|
+
* Only serializable values are included. Function-valued config (integrations,
|
|
12
|
+
* vite/remark/rehype plugins, image services) is omitted because it cannot be
|
|
13
|
+
* serialized. `outDir`/`publicDir` are omitted too, since they move where files
|
|
14
|
+
* are written without changing a page's bytes.
|
|
15
|
+
*
|
|
16
|
+
* The whole `vite` config cannot be hashed: it carries plugins and other
|
|
17
|
+
* function-valued, per-run state that churns between builds and would sink the
|
|
18
|
+
* cache hit rate. Instead a curated allowlist of serializable Vite options that
|
|
19
|
+
* change emitted bytes or asset paths is included (e.g. `build.assetsInlineLimit`
|
|
20
|
+
* flips an asset between an inlined data URI and a separate hashed file). This
|
|
21
|
+
* allowlist is best-effort, so an obscure output-affecting Vite option outside
|
|
22
|
+
* it will not invalidate the cache; `--force` is the escape hatch.
|
|
23
|
+
*
|
|
24
|
+
* The set of fields is asserted against the full config schema in
|
|
25
|
+
* `test/units/build/config-hash.test.ts`, which fails when a new top-level
|
|
26
|
+
* config key appears so it gets classified here or explicitly excluded.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getConfigHashInput(config: AstroConfig): {
|
|
29
|
+
site: string | undefined;
|
|
30
|
+
base: string;
|
|
31
|
+
trailingSlash: "never" | "ignore" | "always";
|
|
32
|
+
output: "server" | "static";
|
|
33
|
+
compressHTML: boolean | "jsx";
|
|
34
|
+
scopedStyleStrategy: "where" | "class" | "attribute";
|
|
35
|
+
build: {
|
|
36
|
+
format: "file" | "directory" | "preserve";
|
|
37
|
+
assets: string;
|
|
38
|
+
assetsPrefix: string | ({
|
|
39
|
+
fallback: string;
|
|
40
|
+
} & Record<string, string>) | undefined;
|
|
41
|
+
inlineStylesheets: "never" | "always" | "auto";
|
|
42
|
+
redirects: boolean;
|
|
43
|
+
};
|
|
44
|
+
redirects: Record<string, string | {
|
|
45
|
+
status: 301 | 302 | 303 | 307 | 308 | 300 | 304;
|
|
46
|
+
destination: string;
|
|
47
|
+
}>;
|
|
48
|
+
i18n: {
|
|
49
|
+
defaultLocale: string;
|
|
50
|
+
locales: (string | {
|
|
51
|
+
path: string;
|
|
52
|
+
codes: [string, ...string[]];
|
|
53
|
+
})[];
|
|
54
|
+
routing: "manual" | {
|
|
55
|
+
prefixDefaultLocale: boolean;
|
|
56
|
+
redirectToDefaultLocale: boolean;
|
|
57
|
+
fallbackType: "redirect" | "rewrite";
|
|
58
|
+
};
|
|
59
|
+
domains?: Record<string, string> | undefined;
|
|
60
|
+
fallback?: Record<string, string> | undefined;
|
|
61
|
+
} | undefined;
|
|
62
|
+
image: {
|
|
63
|
+
endpoint: {
|
|
64
|
+
route: string;
|
|
65
|
+
entrypoint?: string | undefined;
|
|
66
|
+
};
|
|
67
|
+
service: {
|
|
68
|
+
entrypoint: string;
|
|
69
|
+
config: Record<string, any>;
|
|
70
|
+
};
|
|
71
|
+
dangerouslyProcessSVG: boolean;
|
|
72
|
+
domains: string[];
|
|
73
|
+
remotePatterns: {
|
|
74
|
+
protocol?: string | undefined;
|
|
75
|
+
hostname?: string | undefined;
|
|
76
|
+
port?: string | undefined;
|
|
77
|
+
pathname?: string | undefined;
|
|
78
|
+
}[];
|
|
79
|
+
responsiveStyles: boolean;
|
|
80
|
+
layout?: "fixed" | "constrained" | "full-width" | "none" | undefined;
|
|
81
|
+
objectFit?: string | undefined;
|
|
82
|
+
objectPosition?: string | undefined;
|
|
83
|
+
breakpoints?: number[] | undefined;
|
|
84
|
+
};
|
|
85
|
+
markdown: {
|
|
86
|
+
syntaxHighlight: false | "shiki" | "prism" | {
|
|
87
|
+
type: "shiki" | "prism";
|
|
88
|
+
excludeLangs?: string[] | undefined;
|
|
89
|
+
};
|
|
90
|
+
shikiConfig: {
|
|
91
|
+
langs: (import("shiki").LanguageRegistration & import("../../config/schemas/base.js").ComplexifyUnionObj)[];
|
|
92
|
+
langAlias: Record<string, string>;
|
|
93
|
+
theme: "andromeeda" | "aurora-x" | "ayu-dark" | "ayu-light" | "ayu-mirage" | "catppuccin-frappe" | "catppuccin-latte" | "catppuccin-macchiato" | "catppuccin-mocha" | "dark-plus" | "dracula" | "dracula-soft" | "everforest-dark" | "everforest-light" | "github-dark" | "github-dark-default" | "github-dark-dimmed" | "github-dark-high-contrast" | "github-light" | "github-light-default" | "github-light-high-contrast" | "gruvbox-dark-hard" | "gruvbox-dark-medium" | "gruvbox-dark-soft" | "gruvbox-light-hard" | "gruvbox-light-medium" | "gruvbox-light-soft" | "horizon" | "horizon-bright" | "houston" | "kanagawa-dragon" | "kanagawa-lotus" | "kanagawa-wave" | "laserwave" | "light-plus" | "material-theme" | "material-theme-darker" | "material-theme-lighter" | "material-theme-ocean" | "material-theme-palenight" | "min-dark" | "min-light" | "monokai" | "night-owl" | "night-owl-light" | "nord" | "one-dark-pro" | "one-light" | "plastic" | "poimandres" | "red" | "rose-pine" | "rose-pine-dawn" | "rose-pine-moon" | "slack-dark" | "slack-ochin" | "snazzy-light" | "solarized-dark" | "solarized-light" | "synthwave-84" | "tokyo-night" | "vesper" | "vitesse-black" | "vitesse-dark" | "vitesse-light" | (NonNullable<(import("shiki").BundledTheme | "css-variables") | import("shiki").ThemeRegistration | import("shiki").ThemeRegistrationRaw | undefined> & import("../../config/schemas/base.js").ComplexifyUnionObj);
|
|
94
|
+
themes: Record<string, "andromeeda" | "aurora-x" | "ayu-dark" | "ayu-light" | "ayu-mirage" | "catppuccin-frappe" | "catppuccin-latte" | "catppuccin-macchiato" | "catppuccin-mocha" | "dark-plus" | "dracula" | "dracula-soft" | "everforest-dark" | "everforest-light" | "github-dark" | "github-dark-default" | "github-dark-dimmed" | "github-dark-high-contrast" | "github-light" | "github-light-default" | "github-light-high-contrast" | "gruvbox-dark-hard" | "gruvbox-dark-medium" | "gruvbox-dark-soft" | "gruvbox-light-hard" | "gruvbox-light-medium" | "gruvbox-light-soft" | "horizon" | "horizon-bright" | "houston" | "kanagawa-dragon" | "kanagawa-lotus" | "kanagawa-wave" | "laserwave" | "light-plus" | "material-theme" | "material-theme-darker" | "material-theme-lighter" | "material-theme-ocean" | "material-theme-palenight" | "min-dark" | "min-light" | "monokai" | "night-owl" | "night-owl-light" | "nord" | "one-dark-pro" | "one-light" | "plastic" | "poimandres" | "red" | "rose-pine" | "rose-pine-dawn" | "rose-pine-moon" | "slack-dark" | "slack-ochin" | "snazzy-light" | "solarized-dark" | "solarized-light" | "synthwave-84" | "tokyo-night" | "vesper" | "vitesse-black" | "vitesse-dark" | "vitesse-light" | (NonNullable<(import("shiki").BundledTheme | "css-variables") | import("shiki").ThemeRegistration | import("shiki").ThemeRegistrationRaw | undefined> & import("../../config/schemas/base.js").ComplexifyUnionObj)>;
|
|
95
|
+
wrap: boolean | null;
|
|
96
|
+
transformers: (import("shiki").ShikiTransformer & import("../../config/schemas/base.js").ComplexifyUnionObj)[];
|
|
97
|
+
defaultColor?: string | false | undefined;
|
|
98
|
+
};
|
|
99
|
+
remarkPlugins: (string | [string, any] | (import("@astrojs/markdown-remark").RemarkPlugin & import("../../config/schemas/base.js").ComplexifyUnionObj) | [import("@astrojs/markdown-remark").RemarkPlugin & import("../../config/schemas/base.js").ComplexifyUnionObj, any])[];
|
|
100
|
+
rehypePlugins: (string | [string, any] | (import("@astrojs/markdown-remark").RehypePlugin & import("../../config/schemas/base.js").ComplexifyUnionObj) | [import("@astrojs/markdown-remark").RehypePlugin & import("../../config/schemas/base.js").ComplexifyUnionObj, any])[];
|
|
101
|
+
remarkRehype: import("../../config/schemas/base.js").RemarkRehype;
|
|
102
|
+
processor: {
|
|
103
|
+
name: string;
|
|
104
|
+
options: object;
|
|
105
|
+
createRenderer: (shared: import("@astrojs/markdown-remark").AstroMarkdownOptions) => Promise<import("@astrojs/markdown-remark").MarkdownRenderer>;
|
|
106
|
+
createMdxRenderer?: ((shared: import("@astrojs/markdown-remark").AstroMarkdownOptions, mdx: import("@astrojs/internal-helpers/markdown").MdxRendererOptions) => Promise<import("@astrojs/internal-helpers/markdown").MdxRenderer>) | undefined;
|
|
107
|
+
};
|
|
108
|
+
gfm?: boolean | undefined;
|
|
109
|
+
smartypants?: false | import("../../config/schemas/base.js").Smartypants | undefined;
|
|
110
|
+
};
|
|
111
|
+
env: {
|
|
112
|
+
schema: Record<string, ({
|
|
113
|
+
context: "client";
|
|
114
|
+
access: "public";
|
|
115
|
+
} | {
|
|
116
|
+
context: "server";
|
|
117
|
+
access: "public";
|
|
118
|
+
} | {
|
|
119
|
+
context: "server";
|
|
120
|
+
access: "secret";
|
|
121
|
+
}) & ({
|
|
122
|
+
type: "enum";
|
|
123
|
+
values: string[];
|
|
124
|
+
optional?: boolean | undefined;
|
|
125
|
+
default?: string | undefined;
|
|
126
|
+
} | {
|
|
127
|
+
type: "string";
|
|
128
|
+
optional?: boolean | undefined;
|
|
129
|
+
default?: string | undefined;
|
|
130
|
+
max?: number | undefined;
|
|
131
|
+
min?: number | undefined;
|
|
132
|
+
length?: number | undefined;
|
|
133
|
+
url?: boolean | undefined;
|
|
134
|
+
includes?: string | undefined;
|
|
135
|
+
startsWith?: string | undefined;
|
|
136
|
+
endsWith?: string | undefined;
|
|
137
|
+
} | {
|
|
138
|
+
type: "number";
|
|
139
|
+
optional?: boolean | undefined;
|
|
140
|
+
default?: number | undefined;
|
|
141
|
+
gt?: number | undefined;
|
|
142
|
+
min?: number | undefined;
|
|
143
|
+
lt?: number | undefined;
|
|
144
|
+
max?: number | undefined;
|
|
145
|
+
int?: boolean | undefined;
|
|
146
|
+
} | {
|
|
147
|
+
type: "boolean";
|
|
148
|
+
optional?: boolean | undefined;
|
|
149
|
+
default?: boolean | undefined;
|
|
150
|
+
})>;
|
|
151
|
+
};
|
|
152
|
+
security: {
|
|
153
|
+
csp: boolean | {
|
|
154
|
+
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
|
|
155
|
+
directives?: (`base-uri${string}` | `child-src${string}` | `connect-src${string}` | `default-src${string}` | `fenced-frame-src${string}` | `font-src${string}` | `form-action${string}` | `frame-ancestors${string}` | `frame-src${string}` | `img-src${string}` | `manifest-src${string}` | `media-src${string}` | `object-src${string}` | `referrer${string}` | `report-to${string}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`)[] | undefined;
|
|
156
|
+
styleDirective?: {
|
|
157
|
+
resources?: (string | {
|
|
158
|
+
resource: string;
|
|
159
|
+
kind: "default" | "attribute" | "element";
|
|
160
|
+
})[] | undefined;
|
|
161
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
162
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
163
|
+
kind: "default" | "attribute" | "element";
|
|
164
|
+
})[] | undefined;
|
|
165
|
+
} | undefined;
|
|
166
|
+
scriptDirective?: {
|
|
167
|
+
resources?: (string | {
|
|
168
|
+
resource: string;
|
|
169
|
+
kind: "default" | "attribute" | "element";
|
|
170
|
+
})[] | undefined;
|
|
171
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
172
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
173
|
+
kind: "default" | "attribute" | "element";
|
|
174
|
+
})[] | undefined;
|
|
175
|
+
strictDynamic?: boolean | undefined;
|
|
176
|
+
} | undefined;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
prefetch: boolean | {
|
|
180
|
+
prefetchAll?: boolean | undefined;
|
|
181
|
+
defaultStrategy?: "tap" | "hover" | "viewport" | "load" | undefined;
|
|
182
|
+
} | undefined;
|
|
183
|
+
vite: {
|
|
184
|
+
build: {
|
|
185
|
+
assetsInlineLimit: number | ((filePath: string, content: Buffer) => boolean | undefined) | undefined;
|
|
186
|
+
minify: boolean | "esbuild" | "oxc" | "terser" | undefined;
|
|
187
|
+
cssMinify: boolean | "esbuild" | "lightningcss" | undefined;
|
|
188
|
+
cssTarget: false | import("vite/types/internal/esbuildOptions.js").EsbuildTarget | undefined;
|
|
189
|
+
target: false | import("vite/types/internal/esbuildOptions.js").EsbuildTarget | undefined;
|
|
190
|
+
};
|
|
191
|
+
css: import("vite").CSSOptions | undefined;
|
|
192
|
+
json: import("vite").JsonOptions | undefined;
|
|
193
|
+
define: Record<string, any> | undefined;
|
|
194
|
+
oxc: false | import("vite").OxcOptions | undefined;
|
|
195
|
+
};
|
|
196
|
+
experimental: {
|
|
197
|
+
clientPrerender: boolean;
|
|
198
|
+
};
|
|
199
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function getConfigHashInput(config) {
|
|
2
|
+
return {
|
|
3
|
+
site: config.site,
|
|
4
|
+
base: config.base,
|
|
5
|
+
trailingSlash: config.trailingSlash,
|
|
6
|
+
output: config.output,
|
|
7
|
+
compressHTML: config.compressHTML,
|
|
8
|
+
scopedStyleStrategy: config.scopedStyleStrategy,
|
|
9
|
+
build: {
|
|
10
|
+
format: config.build.format,
|
|
11
|
+
assets: config.build.assets,
|
|
12
|
+
assetsPrefix: config.build.assetsPrefix,
|
|
13
|
+
inlineStylesheets: config.build.inlineStylesheets,
|
|
14
|
+
redirects: config.build.redirects
|
|
15
|
+
},
|
|
16
|
+
redirects: config.redirects,
|
|
17
|
+
i18n: config.i18n,
|
|
18
|
+
image: config.image,
|
|
19
|
+
markdown: config.markdown,
|
|
20
|
+
env: { schema: config.env?.schema },
|
|
21
|
+
security: { csp: config.security?.csp },
|
|
22
|
+
prefetch: config.prefetch,
|
|
23
|
+
vite: {
|
|
24
|
+
build: {
|
|
25
|
+
assetsInlineLimit: config.vite.build?.assetsInlineLimit,
|
|
26
|
+
minify: config.vite.build?.minify,
|
|
27
|
+
cssMinify: config.vite.build?.cssMinify,
|
|
28
|
+
cssTarget: config.vite.build?.cssTarget,
|
|
29
|
+
target: config.vite.build?.target
|
|
30
|
+
},
|
|
31
|
+
css: config.vite.css,
|
|
32
|
+
json: config.vite.json,
|
|
33
|
+
define: config.vite.define,
|
|
34
|
+
oxc: config.vite.oxc
|
|
35
|
+
},
|
|
36
|
+
experimental: {
|
|
37
|
+
clientPrerender: config.experimental.clientPrerender
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
getConfigHashInput
|
|
43
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AstroLogger } from '../logger/core.js';
|
|
2
|
-
import type { AstroPrerenderer, RouteToHeaders } from '../../types/public/index.js';
|
|
2
|
+
import type { AstroPrerenderer, PrerenderResult, RouteToHeaders } from '../../types/public/index.js';
|
|
3
3
|
import type { RouteData } from '../../types/public/internal.js';
|
|
4
4
|
import { type BuildInternals } from './internal.js';
|
|
5
5
|
import type { StaticBuildOptions } from './types.js';
|
|
@@ -13,6 +13,8 @@ export interface RenderPathResult {
|
|
|
13
13
|
body: string | Uint8Array;
|
|
14
14
|
outFile: URL;
|
|
15
15
|
outFolder: URL;
|
|
16
|
+
/** Incremental-build metadata the prerenderer reported for this page, if any. */
|
|
17
|
+
metadata?: PrerenderResult['metadata'];
|
|
16
18
|
}
|
|
17
19
|
interface RenderToPathPayload {
|
|
18
20
|
prerenderer: AstroPrerenderer;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import nodeFs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
3
4
|
import PLimit from "p-limit";
|
|
4
5
|
import PQueue from "p-queue";
|
|
5
6
|
import colors from "piccolore";
|
|
6
7
|
import {
|
|
7
8
|
generateImagesForPath,
|
|
8
9
|
getStaticImageList,
|
|
9
|
-
prepareAssetsGenerationEnv
|
|
10
|
+
prepareAssetsGenerationEnv,
|
|
11
|
+
restoreStaticImages
|
|
10
12
|
} from "../../assets/build/generate.js";
|
|
11
13
|
import {
|
|
12
14
|
appendForwardSlash,
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
trimSlashes
|
|
19
21
|
} from "../../core/path.js";
|
|
20
22
|
import { runHookBuildGenerated, toIntegrationResolvedRoute } from "../../integrations/hooks.js";
|
|
23
|
+
import { hashCryptoKey } from "../encryption.js";
|
|
21
24
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
22
25
|
import { getRedirectLocationOrThrow } from "../redirects/index.js";
|
|
23
26
|
import { createRequest } from "../request.js";
|
|
@@ -27,6 +30,14 @@ import { matchRoute } from "../routing/match.js";
|
|
|
27
30
|
import { getOutputFilename } from "../output-filename.js";
|
|
28
31
|
import { getOutFile, getOutFolder } from "./common.js";
|
|
29
32
|
import { createDefaultPrerenderer } from "./default-prerenderer.js";
|
|
33
|
+
import {
|
|
34
|
+
beginContentEntryCollection,
|
|
35
|
+
endContentEntryCollection
|
|
36
|
+
} from "./incremental-content-collector.js";
|
|
37
|
+
import { beginImageCollection, endImageCollection } from "./incremental-image-collector.js";
|
|
38
|
+
import { IncrementalBuildCache } from "./incremental.js";
|
|
39
|
+
import { computeConfigHash } from "./config-hash/index.js";
|
|
40
|
+
import { computeLockfileHash } from "./lockfile/index.js";
|
|
30
41
|
import { hasPrerenderedPages } from "./internal.js";
|
|
31
42
|
import { getTimeStat, shouldAppendForwardSlash } from "./util.js";
|
|
32
43
|
async function generatePages(options, internals, prerenderOutputDir) {
|
|
@@ -64,6 +75,29 @@ async function generatePages(options, internals, prerenderOutputDir) {
|
|
|
64
75
|
${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
65
76
|
const routeToHeaders = /* @__PURE__ */ new Map();
|
|
66
77
|
let staticImageList = getStaticImageList();
|
|
78
|
+
let cache = null;
|
|
79
|
+
if (options.settings.config.experimental.incrementalBuild) {
|
|
80
|
+
if (options.settings.config.build.concurrency > 1) {
|
|
81
|
+
logger.warn(
|
|
82
|
+
"build",
|
|
83
|
+
"The incremental build cache is disabled because `build.concurrency` is greater than 1."
|
|
84
|
+
);
|
|
85
|
+
} else {
|
|
86
|
+
const [configHash, lockfileHash, keyDigest] = await Promise.all([
|
|
87
|
+
computeConfigHash(options.settings.config),
|
|
88
|
+
computeLockfileHash(fileURLToPath(options.settings.config.root)),
|
|
89
|
+
options.key.then(hashCryptoKey)
|
|
90
|
+
]);
|
|
91
|
+
cache = IncrementalBuildCache.load(
|
|
92
|
+
options.settings,
|
|
93
|
+
configHash,
|
|
94
|
+
lockfileHash,
|
|
95
|
+
keyDigest,
|
|
96
|
+
internals.contentEntryRenderHashes ?? /* @__PURE__ */ new Map(),
|
|
97
|
+
options.force
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
67
101
|
try {
|
|
68
102
|
const pathsWithRoutes = await prerenderer.getStaticPaths();
|
|
69
103
|
const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0;
|
|
@@ -119,14 +153,17 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
119
153
|
for (const paths of generationPhases) {
|
|
120
154
|
for (let i = 0; i < paths.length; i += BATCH_SIZE) {
|
|
121
155
|
const promises = paths.slice(i, i + BATCH_SIZE).map(
|
|
122
|
-
({ pathname, route }) => limit(
|
|
156
|
+
({ pathname, route, cacheKey }) => limit(
|
|
123
157
|
() => generatePathWithPrerenderer(
|
|
124
158
|
prerenderer,
|
|
125
159
|
pathname,
|
|
126
160
|
route,
|
|
127
161
|
options,
|
|
162
|
+
internals,
|
|
128
163
|
routeToHeaders,
|
|
129
|
-
logger
|
|
164
|
+
logger,
|
|
165
|
+
cache,
|
|
166
|
+
cacheKey
|
|
130
167
|
)
|
|
131
168
|
)
|
|
132
169
|
);
|
|
@@ -135,14 +172,17 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
135
172
|
}
|
|
136
173
|
} else {
|
|
137
174
|
for (const paths of generationPhases) {
|
|
138
|
-
for (const { pathname, route } of paths) {
|
|
175
|
+
for (const { pathname, route, cacheKey } of paths) {
|
|
139
176
|
await generatePathWithPrerenderer(
|
|
140
177
|
prerenderer,
|
|
141
178
|
pathname,
|
|
142
179
|
route,
|
|
143
180
|
options,
|
|
181
|
+
internals,
|
|
144
182
|
routeToHeaders,
|
|
145
|
-
logger
|
|
183
|
+
logger,
|
|
184
|
+
cache,
|
|
185
|
+
cacheKey
|
|
146
186
|
);
|
|
147
187
|
}
|
|
148
188
|
}
|
|
@@ -159,6 +199,25 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
159
199
|
}
|
|
160
200
|
}
|
|
161
201
|
}
|
|
202
|
+
if (cache) {
|
|
203
|
+
const orphans = cache.findOrphanedFiles();
|
|
204
|
+
let pruned = 0;
|
|
205
|
+
for (const orphanFile of orphans) {
|
|
206
|
+
try {
|
|
207
|
+
await cache.deleteOutputFile(options.settings, orphanFile);
|
|
208
|
+
pruned++;
|
|
209
|
+
} catch (err) {
|
|
210
|
+
logger.warn(
|
|
211
|
+
"build",
|
|
212
|
+
`Could not prune stale incremental cache file ${orphanFile}: ${err}`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (pruned > 0) {
|
|
217
|
+
logger.info("build", `Pruned ${pruned} stale file(s) from the incremental cache.`);
|
|
218
|
+
}
|
|
219
|
+
cache.writeManifest(options.settings);
|
|
220
|
+
}
|
|
162
221
|
staticImageList = getStaticImageList();
|
|
163
222
|
if (prerenderer.collectStaticImages) {
|
|
164
223
|
const adapterImages = await prerenderer.collectStaticImages();
|
|
@@ -206,6 +265,9 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
206
265
|
});
|
|
207
266
|
}
|
|
208
267
|
const THRESHOLD_SLOW_RENDER_TIME_MS = 500;
|
|
268
|
+
function normalizePrerenderResult(result) {
|
|
269
|
+
return result instanceof Response ? { response: result } : result;
|
|
270
|
+
}
|
|
209
271
|
async function renderPath({
|
|
210
272
|
prerenderer,
|
|
211
273
|
pathname,
|
|
@@ -239,7 +301,8 @@ async function renderPath({
|
|
|
239
301
|
options.origin,
|
|
240
302
|
config.build.format,
|
|
241
303
|
config.trailingSlash,
|
|
242
|
-
route.type
|
|
304
|
+
route.type,
|
|
305
|
+
route.isIndex
|
|
243
306
|
);
|
|
244
307
|
const request = createRequest({
|
|
245
308
|
url,
|
|
@@ -249,8 +312,13 @@ async function renderPath({
|
|
|
249
312
|
routePattern: route.component
|
|
250
313
|
});
|
|
251
314
|
let response;
|
|
315
|
+
let metadata;
|
|
252
316
|
try {
|
|
253
|
-
|
|
317
|
+
const rendered = normalizePrerenderResult(
|
|
318
|
+
await prerenderer.render(request, { routeData: route })
|
|
319
|
+
);
|
|
320
|
+
response = rendered.response;
|
|
321
|
+
metadata = rendered.metadata;
|
|
254
322
|
} catch (err) {
|
|
255
323
|
logger.error("build", `Caught error rendering ${pathname}: ${err}`);
|
|
256
324
|
if (err && !AstroError.is(err) && !err.id && typeof err === "object") {
|
|
@@ -299,16 +367,65 @@ async function renderPath({
|
|
|
299
367
|
routeToHeaders.set(pathname, { headers: responseHeaders, route: integrationRoute });
|
|
300
368
|
}
|
|
301
369
|
if (checkPublicConflict(outFile, route, options.settings, logger)) return null;
|
|
302
|
-
return { body, outFile, outFolder };
|
|
370
|
+
return { body, outFile, outFolder, metadata };
|
|
303
371
|
}
|
|
304
|
-
async function generatePathWithPrerenderer(prerenderer, pathname, route, options, routeToHeaders, logger) {
|
|
372
|
+
async function generatePathWithPrerenderer(prerenderer, pathname, route, options, internals, routeToHeaders, logger, cache, cacheKey) {
|
|
305
373
|
const timeStart = performance.now();
|
|
306
374
|
const { config } = options.settings;
|
|
307
375
|
const filePath = getOutputFilename(config.build.format, pathname, route);
|
|
376
|
+
const encodedPath = encodeURI(pathname);
|
|
377
|
+
const outFolder = getOutFolder(options.settings, encodedPath, route);
|
|
378
|
+
const outFile = getOutFile(config.build.format, outFolder, encodedPath, route);
|
|
379
|
+
const relativeOutFile = outFile.href.slice(config.outDir.href.length);
|
|
380
|
+
const dependencyHash = internals.pageDependencyHashes?.get(route.component) ?? "";
|
|
381
|
+
const hasServerIsland = internals.serverIslandPageComponents?.has(route.component) ?? false;
|
|
382
|
+
if (cacheKey !== void 0 && cache?.canSkip(route.component, pathname, dependencyHash, cacheKey, hasServerIsland)) {
|
|
383
|
+
const existsInDist = nodeFs.existsSync(outFile);
|
|
384
|
+
const restored = !existsInDist && await cache.restoreOutputFile(options.settings, relativeOutFile, outFile);
|
|
385
|
+
if (existsInDist || restored) {
|
|
386
|
+
const restoredImages = cache.previousStaticImages(route.component, pathname);
|
|
387
|
+
if (restoredImages) restoreStaticImages(restoredImages);
|
|
388
|
+
const restoredHeaders = cache.previousHeaders(route.component, pathname);
|
|
389
|
+
if (restoredHeaders && options.settings.adapter?.adapterFeatures?.staticHeaders) {
|
|
390
|
+
routeToHeaders.set(pathname, {
|
|
391
|
+
headers: new Headers(restoredHeaders),
|
|
392
|
+
route: toIntegrationResolvedRoute(route, config.trailingSlash)
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
cache.record(
|
|
396
|
+
route.component,
|
|
397
|
+
dependencyHash,
|
|
398
|
+
pathname,
|
|
399
|
+
cacheKey,
|
|
400
|
+
relativeOutFile,
|
|
401
|
+
cache.previousContentEntryKeys(route.component, pathname),
|
|
402
|
+
restoredImages,
|
|
403
|
+
restoredHeaders
|
|
404
|
+
);
|
|
405
|
+
if (route.type === "page") {
|
|
406
|
+
addPageName(pathname, options);
|
|
407
|
+
}
|
|
408
|
+
if (route.distURL) {
|
|
409
|
+
route.distURL.push(outFile);
|
|
410
|
+
} else {
|
|
411
|
+
route.distURL = [outFile];
|
|
412
|
+
}
|
|
413
|
+
logger.info(null, ` ${colors.green("\u251C\u2500")} ${colors.dim(filePath)}`, false);
|
|
414
|
+
logger.info(
|
|
415
|
+
"SKIP_FORMAT",
|
|
416
|
+
restored ? ` ${colors.green("(restored)")}` : ` ${colors.green("(cached)")}`
|
|
417
|
+
);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
308
421
|
logger.info(null, ` ${colors.blue("\u251C\u2500")} ${colors.dim(filePath)}`, false);
|
|
309
422
|
if (route.type === "page") {
|
|
310
423
|
addPageName(pathname, options);
|
|
311
424
|
}
|
|
425
|
+
if (cache) {
|
|
426
|
+
beginContentEntryCollection();
|
|
427
|
+
beginImageCollection();
|
|
428
|
+
}
|
|
312
429
|
const result = await renderPath({
|
|
313
430
|
prerenderer,
|
|
314
431
|
pathname,
|
|
@@ -317,12 +434,30 @@ async function generatePathWithPrerenderer(prerenderer, pathname, route, options
|
|
|
317
434
|
routeToHeaders,
|
|
318
435
|
logger
|
|
319
436
|
});
|
|
437
|
+
const collectedContentEntryKeys = cache ? endContentEntryCollection() : void 0;
|
|
438
|
+
const collectedStaticImages = cache ? endImageCollection() : void 0;
|
|
439
|
+
const contentEntryKeys = result?.metadata?.contentEntryKeys ?? collectedContentEntryKeys;
|
|
440
|
+
const staticImages = result?.metadata?.staticImages ?? collectedStaticImages;
|
|
441
|
+
const headers = cache ? [...routeToHeaders.get(pathname)?.headers ?? []] : void 0;
|
|
320
442
|
if (!result) {
|
|
321
443
|
logRenderTime(logger, timeStart, true);
|
|
322
444
|
return;
|
|
323
445
|
}
|
|
324
446
|
await nodeFs.promises.mkdir(result.outFolder, { recursive: true });
|
|
325
447
|
await nodeFs.promises.writeFile(result.outFile, result.body);
|
|
448
|
+
if (cache && cacheKey !== void 0) {
|
|
449
|
+
await cache.writeOutputFile(options.settings, relativeOutFile, result.body);
|
|
450
|
+
cache.record(
|
|
451
|
+
route.component,
|
|
452
|
+
dependencyHash,
|
|
453
|
+
pathname,
|
|
454
|
+
cacheKey,
|
|
455
|
+
relativeOutFile,
|
|
456
|
+
contentEntryKeys,
|
|
457
|
+
staticImages,
|
|
458
|
+
headers
|
|
459
|
+
);
|
|
460
|
+
}
|
|
326
461
|
logRenderTime(logger, timeStart, false);
|
|
327
462
|
}
|
|
328
463
|
function logRenderTime(logger, timeStart, notCreated) {
|
|
@@ -338,11 +473,11 @@ function addPageName(pathname, opts) {
|
|
|
338
473
|
const pageName = shouldAppendForwardSlash(trailingSlash, buildFormat) ? pathname.replace(/\/?$/, "/").replace(/^\//, "") : pathname.replace(/^\//, "");
|
|
339
474
|
opts.pageNames.push(pageName);
|
|
340
475
|
}
|
|
341
|
-
function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType) {
|
|
476
|
+
function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType, isIndex) {
|
|
342
477
|
let ending;
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
case "
|
|
478
|
+
const effectiveFormat = format === "preserve" ? isIndex ? "directory" : "file" : format;
|
|
479
|
+
switch (effectiveFormat) {
|
|
480
|
+
case "directory": {
|
|
346
481
|
ending = trailingSlash === "never" ? "" : "/";
|
|
347
482
|
break;
|
|
348
483
|
}
|
|
@@ -354,7 +489,7 @@ function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType)
|
|
|
354
489
|
}
|
|
355
490
|
let buildPathname;
|
|
356
491
|
if (pathname === "/" || pathname === "") {
|
|
357
|
-
if (
|
|
492
|
+
if (effectiveFormat === "file") {
|
|
358
493
|
buildPathname = joinPaths(base, "index.html");
|
|
359
494
|
} else {
|
|
360
495
|
buildPathname = collapseDuplicateTrailingSlashes(base + ending, trailingSlash !== "never");
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Start collecting the content entries rendered on the current path. */
|
|
2
|
+
export declare function beginContentEntryCollection(): void;
|
|
3
|
+
/** Record that a content entry was rendered, keyed by its root-relative `filePath`. */
|
|
4
|
+
export declare function recordContentEntryRender(filePath: string | undefined): void;
|
|
5
|
+
/**
|
|
6
|
+
* Finish collection and return the rendered entries, or `undefined` when no
|
|
7
|
+
* collection was active (so callers can distinguish "nothing rendered" from
|
|
8
|
+
* "not tracked").
|
|
9
|
+
*/
|
|
10
|
+
export declare function endContentEntryCollection(): string[] | undefined;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const COLLECTOR_KEY = /* @__PURE__ */ Symbol.for("astro:incremental-content-entries");
|
|
2
|
+
function collector() {
|
|
3
|
+
const host = globalThis;
|
|
4
|
+
let value = host[COLLECTOR_KEY];
|
|
5
|
+
if (!value) {
|
|
6
|
+
value = { current: void 0 };
|
|
7
|
+
Object.defineProperty(host, COLLECTOR_KEY, {
|
|
8
|
+
value,
|
|
9
|
+
configurable: false,
|
|
10
|
+
writable: false,
|
|
11
|
+
enumerable: false
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function beginContentEntryCollection() {
|
|
17
|
+
collector().current = /* @__PURE__ */ new Set();
|
|
18
|
+
}
|
|
19
|
+
function recordContentEntryRender(filePath) {
|
|
20
|
+
if (!filePath) return;
|
|
21
|
+
collector().current?.add(filePath);
|
|
22
|
+
}
|
|
23
|
+
function endContentEntryCollection() {
|
|
24
|
+
const c = collector();
|
|
25
|
+
const entries = c.current;
|
|
26
|
+
c.current = void 0;
|
|
27
|
+
return entries ? [...entries] : void 0;
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
beginContentEntryCollection,
|
|
31
|
+
endContentEntryCollection,
|
|
32
|
+
recordContentEntryRender
|
|
33
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SerializedStaticImage } from '../../assets/types.js';
|
|
2
|
+
/** Start collecting the image transforms resolved on the current path. */
|
|
3
|
+
export declare function beginImageCollection(): void;
|
|
4
|
+
/** Record an image transform resolved while rendering the current path. */
|
|
5
|
+
export declare function recordStaticImage(image: SerializedStaticImage): void;
|
|
6
|
+
/**
|
|
7
|
+
* Finish collection and return the collected transforms, or `undefined` when no
|
|
8
|
+
* collection was active (so callers can distinguish "no images" from
|
|
9
|
+
* "not tracked").
|
|
10
|
+
*/
|
|
11
|
+
export declare function endImageCollection(): SerializedStaticImage[] | undefined;
|