Unflag hybrid output (#7260)
* feat(hybrid): unflag hybrid output * chore: cleanup rebase errors
This commit is contained in:
parent
414eb19d2f
commit
39403c32fa
29 changed files with 68 additions and 141 deletions
10
.changeset/weak-wombats-swim.md
Normal file
10
.changeset/weak-wombats-swim.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
'astro': minor
|
||||||
|
'@astrojs/image': minor
|
||||||
|
'@astrojs/cloudflare': patch
|
||||||
|
'@astrojs/netlify': patch
|
||||||
|
'@astrojs/node': patch
|
||||||
|
'@astrojs/vercel': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Unflags support for `output: 'hybrid'` mode, which enables pre-rendering by default. The additional `experimental.hybridOutput` flag can be safely removed from your configuration.
|
|
@ -1166,44 +1166,6 @@ export interface AstroUserConfig {
|
||||||
*/
|
*/
|
||||||
assets?: boolean;
|
assets?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* @docs
|
|
||||||
* @name experimental.hybridOutput
|
|
||||||
* @type {boolean}
|
|
||||||
* @default `false`
|
|
||||||
* @version 2.5.0
|
|
||||||
* @description
|
|
||||||
* Enable experimental support for hybrid SSR with pre-rendering enabled by default.
|
|
||||||
*
|
|
||||||
* To enable this feature, first set `experimental.hybridOutput` to `true` in your Astro config, and set `output` to `hybrid`.
|
|
||||||
*
|
|
||||||
* ```js
|
|
||||||
* {
|
|
||||||
* output: 'hybrid',
|
|
||||||
* experimental: {
|
|
||||||
* hybridOutput: true,
|
|
||||||
* },
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
* Then add `export const prerender = false` to any page or endpoint you want to opt-out of pre-rendering.
|
|
||||||
* ```astro
|
|
||||||
* ---
|
|
||||||
* // pages/contact.astro
|
|
||||||
* export const prerender = false
|
|
||||||
*
|
|
||||||
* if (Astro.request.method === 'POST') {
|
|
||||||
* // handle form submission
|
|
||||||
* }
|
|
||||||
* ---
|
|
||||||
* <form method="POST">
|
|
||||||
* <input type="text" name="name" />
|
|
||||||
* <input type="email" name="email" />
|
|
||||||
* <button type="submit">Submit</button>
|
|
||||||
* </form>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
hybridOutput?: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @docs
|
* @docs
|
||||||
* @name experimental.redirects
|
* @name experimental.redirects
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { basename, join } from 'node:path/posix';
|
||||||
import type { StaticBuildOptions } from '../core/build/types.js';
|
import type { StaticBuildOptions } from '../core/build/types.js';
|
||||||
import { warn } from '../core/logger/core.js';
|
import { warn } from '../core/logger/core.js';
|
||||||
import { prependForwardSlash } from '../core/path.js';
|
import { prependForwardSlash } from '../core/path.js';
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { getConfiguredImageService, isESMImportedImage } from './internal.js';
|
import { getConfiguredImageService, isESMImportedImage } from './internal.js';
|
||||||
import type { LocalImageService } from './services/service.js';
|
import type { LocalImageService } from './services/service.js';
|
||||||
import type { ImageTransform } from './types.js';
|
import type { ImageTransform } from './types.js';
|
||||||
|
@ -47,7 +47,7 @@ export async function generateImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
let serverRoot: URL, clientRoot: URL;
|
let serverRoot: URL, clientRoot: URL;
|
||||||
if (buildOpts.settings.config.output === 'server' || isHybridOutput(buildOpts.settings.config)) {
|
if (isServerLikeOutput(buildOpts.settings.config)) {
|
||||||
serverRoot = buildOpts.settings.config.build.server;
|
serverRoot = buildOpts.settings.config.build.server;
|
||||||
clientRoot = buildOpts.settings.config.build.client;
|
clientRoot = buildOpts.settings.config.build.client;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import {
|
||||||
removeTrailingForwardSlash,
|
removeTrailingForwardSlash,
|
||||||
} from '../../core/path.js';
|
} from '../../core/path.js';
|
||||||
import { runHookBuildGenerated } from '../../integrations/index.js';
|
import { runHookBuildGenerated } from '../../integrations/index.js';
|
||||||
import { isHybridOutput } from '../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
||||||
import { callEndpoint, createAPIContext, throwIfRedirectNotAllowed } from '../endpoint/index.js';
|
import { callEndpoint, createAPIContext, throwIfRedirectNotAllowed } from '../endpoint/index.js';
|
||||||
import { AstroError } from '../errors/index.js';
|
import { AstroError } from '../errors/index.js';
|
||||||
|
@ -130,7 +130,8 @@ export function chunkIsPage(
|
||||||
|
|
||||||
export async function generatePages(opts: StaticBuildOptions, internals: BuildInternals) {
|
export async function generatePages(opts: StaticBuildOptions, internals: BuildInternals) {
|
||||||
const timer = performance.now();
|
const timer = performance.now();
|
||||||
const ssr = opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config); // hybrid mode is essentially SSR with prerender by default
|
const ssr = isServerLikeOutput(opts.settings.config);
|
||||||
|
const serverEntry = opts.buildConfig.serverEntry;
|
||||||
const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
|
const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
|
||||||
|
|
||||||
if (ssr && !hasPrerenderedPages(internals)) return;
|
if (ssr && !hasPrerenderedPages(internals)) return;
|
||||||
|
@ -284,7 +285,7 @@ async function getPathsForRoute(
|
||||||
route: pageData.route,
|
route: pageData.route,
|
||||||
isValidate: false,
|
isValidate: false,
|
||||||
logging: opts.logging,
|
logging: opts.logging,
|
||||||
ssr: opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config),
|
ssr: isServerLikeOutput(opts.settings.config),
|
||||||
})
|
})
|
||||||
.then((_result) => {
|
.then((_result) => {
|
||||||
const label = _result.staticPaths.length === 1 ? 'page' : 'pages';
|
const label = _result.staticPaths.length === 1 ? 'page' : 'pages';
|
||||||
|
@ -460,7 +461,7 @@ async function generatePath(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
|
const ssr = isServerLikeOutput(settings.config);
|
||||||
const url = getUrlForPath(
|
const url = getUrlForPath(
|
||||||
pathname,
|
pathname,
|
||||||
opts.settings.config.base,
|
opts.settings.config.base,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { fileURLToPath } from 'url';
|
||||||
import type { Plugin as VitePlugin } from 'vite';
|
import type { Plugin as VitePlugin } from 'vite';
|
||||||
import type { AstroAdapter } from '../../../@types/astro';
|
import type { AstroAdapter } from '../../../@types/astro';
|
||||||
import { runHookBuildSsr } from '../../../integrations/index.js';
|
import { runHookBuildSsr } from '../../../integrations/index.js';
|
||||||
import { isHybridOutput } from '../../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../../prerender/utils.js';
|
||||||
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js';
|
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js';
|
||||||
import type { SerializedRouteInfo, SerializedSSRManifest } from '../../app/types';
|
import type { SerializedRouteInfo, SerializedSSRManifest } from '../../app/types';
|
||||||
import { joinPaths, prependForwardSlash } from '../../path.js';
|
import { joinPaths, prependForwardSlash } from '../../path.js';
|
||||||
|
@ -269,8 +269,7 @@ export function pluginSSR(
|
||||||
options: StaticBuildOptions,
|
options: StaticBuildOptions,
|
||||||
internals: BuildInternals
|
internals: BuildInternals
|
||||||
): AstroBuildPlugin {
|
): AstroBuildPlugin {
|
||||||
const ssr =
|
const ssr = isServerLikeOutput(options.settings.config);
|
||||||
options.settings.config.output === 'server' || isHybridOutput(options.settings.config);
|
|
||||||
return {
|
return {
|
||||||
build: 'ssr',
|
build: 'ssr',
|
||||||
hooks: {
|
hooks: {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { emptyDir, removeEmptyDirs } from '../../core/fs/index.js';
|
||||||
import { appendForwardSlash, prependForwardSlash } from '../../core/path.js';
|
import { appendForwardSlash, prependForwardSlash } from '../../core/path.js';
|
||||||
import { isModeServerWithNoAdapter } from '../../core/util.js';
|
import { isModeServerWithNoAdapter } from '../../core/util.js';
|
||||||
import { runHookBuildSetup } from '../../integrations/index.js';
|
import { runHookBuildSetup } from '../../integrations/index.js';
|
||||||
import { isHybridOutput } from '../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
import { info } from '../logger/core.js';
|
import { info } from '../logger/core.js';
|
||||||
|
@ -117,7 +117,6 @@ export async function viteBuild(opts: StaticBuildOptions) {
|
||||||
|
|
||||||
export async function staticBuild(opts: StaticBuildOptions, internals: BuildInternals) {
|
export async function staticBuild(opts: StaticBuildOptions, internals: BuildInternals) {
|
||||||
const { settings } = opts;
|
const { settings } = opts;
|
||||||
const hybridOutput = isHybridOutput(settings.config);
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case settings.config.output === 'static': {
|
case settings.config.output === 'static': {
|
||||||
settings.timer.start('Static generate');
|
settings.timer.start('Static generate');
|
||||||
|
@ -126,7 +125,7 @@ export async function staticBuild(opts: StaticBuildOptions, internals: BuildInte
|
||||||
settings.timer.end('Static generate');
|
settings.timer.end('Static generate');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case settings.config.output === 'server' || hybridOutput: {
|
case isServerLikeOutput(settings.config): {
|
||||||
settings.timer.start('Server generate');
|
settings.timer.start('Server generate');
|
||||||
await generatePages(opts, internals);
|
await generatePages(opts, internals);
|
||||||
await cleanStaticOutput(opts, internals);
|
await cleanStaticOutput(opts, internals);
|
||||||
|
@ -145,7 +144,7 @@ async function ssrBuild(
|
||||||
container: AstroBuildPluginContainer
|
container: AstroBuildPluginContainer
|
||||||
) {
|
) {
|
||||||
const { settings, viteConfig } = opts;
|
const { settings, viteConfig } = opts;
|
||||||
const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
|
const ssr = isServerLikeOutput(settings.config);
|
||||||
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir);
|
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir);
|
||||||
|
|
||||||
const { lastVitePlugins, vitePlugins } = container.runBeforeHook('ssr', input);
|
const { lastVitePlugins, vitePlugins } = container.runBeforeHook('ssr', input);
|
||||||
|
@ -225,7 +224,7 @@ async function clientBuild(
|
||||||
) {
|
) {
|
||||||
const { settings, viteConfig } = opts;
|
const { settings, viteConfig } = opts;
|
||||||
const timer = performance.now();
|
const timer = performance.now();
|
||||||
const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
|
const ssr = isServerLikeOutput(settings.config);
|
||||||
const out = ssr ? opts.buildConfig.client : getOutDirWithinCwd(settings.config.outDir);
|
const out = ssr ? opts.buildConfig.client : getOutDirWithinCwd(settings.config.outDir);
|
||||||
|
|
||||||
// Nothing to do if there is no client-side JS.
|
// Nothing to do if there is no client-side JS.
|
||||||
|
@ -290,12 +289,11 @@ async function runPostBuildHooks(
|
||||||
const config = container.options.settings.config;
|
const config = container.options.settings.config;
|
||||||
const buildConfig = container.options.settings.config.build;
|
const buildConfig = container.options.settings.config.build;
|
||||||
for (const [fileName, mutation] of mutations) {
|
for (const [fileName, mutation] of mutations) {
|
||||||
const root =
|
const root = isServerLikeOutput(config)
|
||||||
config.output === 'server' || isHybridOutput(config)
|
? mutation.build === 'server'
|
||||||
? mutation.build === 'server'
|
? buildConfig.server
|
||||||
? buildConfig.server
|
: buildConfig.client
|
||||||
: buildConfig.client
|
: config.outDir;
|
||||||
: config.outDir;
|
|
||||||
const fileURL = new URL(fileName, root);
|
const fileURL = new URL(fileName, root);
|
||||||
await fs.promises.mkdir(new URL('./', fileURL), { recursive: true });
|
await fs.promises.mkdir(new URL('./', fileURL), { recursive: true });
|
||||||
await fs.promises.writeFile(fileURL, mutation.code, 'utf-8');
|
await fs.promises.writeFile(fileURL, mutation.code, 'utf-8');
|
||||||
|
@ -312,7 +310,7 @@ async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInter
|
||||||
if (pageData.route.prerender)
|
if (pageData.route.prerender)
|
||||||
allStaticFiles.add(internals.pageToBundleMap.get(pageData.moduleSpecifier));
|
allStaticFiles.add(internals.pageToBundleMap.get(pageData.moduleSpecifier));
|
||||||
}
|
}
|
||||||
const ssr = opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config);
|
const ssr = isServerLikeOutput(opts.settings.config);
|
||||||
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
|
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
|
||||||
// The SSR output is all .mjs files, the client output is not.
|
// The SSR output is all .mjs files, the client output is not.
|
||||||
const files = await glob('**/*.mjs', {
|
const files = await glob('**/*.mjs', {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import * as colors from 'kleur/colors';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath, pathToFileURL } from 'url';
|
import { fileURLToPath, pathToFileURL } from 'url';
|
||||||
import { mergeConfig as mergeViteConfig } from 'vite';
|
import { mergeConfig as mergeViteConfig } from 'vite';
|
||||||
import { isHybridMalconfigured } from '../../prerender/utils.js';
|
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
import type { LogOptions } from '../logger/core.js';
|
import type { LogOptions } from '../logger/core.js';
|
||||||
import { arraify, isObject, isURL } from '../util.js';
|
import { arraify, isObject, isURL } from '../util.js';
|
||||||
|
@ -221,12 +220,6 @@ export async function openConfig(configOptions: LoadConfigOptions): Promise<Open
|
||||||
}
|
}
|
||||||
const astroConfig = await resolveConfig(userConfig, root, flags, configOptions.cmd);
|
const astroConfig = await resolveConfig(userConfig, root, flags, configOptions.cmd);
|
||||||
|
|
||||||
if (isHybridMalconfigured(astroConfig)) {
|
|
||||||
throw new Error(
|
|
||||||
`The "output" config option must be set to "hybrid" and "experimental.hybridOutput" must be set to true to use the hybrid output mode. Falling back to "static" output mode.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
astroConfig,
|
astroConfig,
|
||||||
userConfig,
|
userConfig,
|
||||||
|
|
|
@ -42,8 +42,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
|
||||||
redirects: {},
|
redirects: {},
|
||||||
experimental: {
|
experimental: {
|
||||||
assets: false,
|
assets: false,
|
||||||
hybridOutput: false,
|
redirects: false
|
||||||
redirects: false,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -206,8 +205,7 @@ export const AstroConfigSchema = z.object({
|
||||||
experimental: z
|
experimental: z
|
||||||
.object({
|
.object({
|
||||||
assets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.assets),
|
assets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.assets),
|
||||||
hybridOutput: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.hybridOutput),
|
redirects: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.redirects)
|
||||||
redirects: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.redirects),
|
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
.refine(
|
.refine(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { fileURLToPath, pathToFileURL } from 'url';
|
||||||
import type { AstroConfig, AstroSettings, AstroUserConfig } from '../../@types/astro';
|
import type { AstroConfig, AstroSettings, AstroUserConfig } from '../../@types/astro';
|
||||||
import { getContentPaths } from '../../content/index.js';
|
import { getContentPaths } from '../../content/index.js';
|
||||||
import jsxRenderer from '../../jsx/renderer.js';
|
import jsxRenderer from '../../jsx/renderer.js';
|
||||||
import { isHybridOutput } from '../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { markdownContentEntryType } from '../../vite-plugin-markdown/content-entry-type.js';
|
import { markdownContentEntryType } from '../../vite-plugin-markdown/content-entry-type.js';
|
||||||
import { getDefaultClientDirectives } from '../client-directive/index.js';
|
import { getDefaultClientDirectives } from '../client-directive/index.js';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
|
@ -23,7 +23,7 @@ export function createBaseSettings(config: AstroConfig): AstroSettings {
|
||||||
|
|
||||||
adapter: undefined,
|
adapter: undefined,
|
||||||
injectedRoutes:
|
injectedRoutes:
|
||||||
config.experimental.assets && (config.output === 'server' || isHybridOutput(config))
|
config.experimental.assets && isServerLikeOutput(config)
|
||||||
? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint' }]
|
? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint' }]
|
||||||
: [],
|
: [],
|
||||||
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
|
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type {
|
||||||
} from '../../@types/astro';
|
} from '../../@types/astro';
|
||||||
import type { Environment, RenderContext } from '../render/index';
|
import type { Environment, RenderContext } from '../render/index';
|
||||||
|
|
||||||
import { isHybridOutput } from '../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { renderEndpoint } from '../../runtime/server/index.js';
|
import { renderEndpoint } from '../../runtime/server/index.js';
|
||||||
import { ASTRO_VERSION } from '../constants.js';
|
import { ASTRO_VERSION } from '../constants.js';
|
||||||
import { AstroCookies, attachToResponse } from '../cookies/index.js';
|
import { AstroCookies, attachToResponse } from '../cookies/index.js';
|
||||||
|
@ -161,7 +161,7 @@ function isRedirect(statusCode: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) {
|
export function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) {
|
||||||
if (config.output !== 'server' && !isHybridOutput(config) && isRedirect(response.status)) {
|
if (!isServerLikeOutput(config) && isRedirect(response.status)) {
|
||||||
throw new AstroError(AstroErrorData.StaticRedirectNotAvailable);
|
throw new AstroError(AstroErrorData.StaticRedirectNotAvailable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { AstroSettings, RuntimeMode } from '../../../@types/astro';
|
import type { AstroSettings, RuntimeMode } from '../../../@types/astro';
|
||||||
import { isHybridOutput } from '../../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../../prerender/utils.js';
|
||||||
import type { LogOptions } from '../../logger/core.js';
|
import type { LogOptions } from '../../logger/core.js';
|
||||||
import type { ModuleLoader } from '../../module-loader/index';
|
import type { ModuleLoader } from '../../module-loader/index';
|
||||||
import type { Environment } from '../index';
|
import type { Environment } from '../index';
|
||||||
|
@ -30,7 +30,7 @@ export function createDevelopmentEnvironment(
|
||||||
resolve: createResolve(loader, settings.config.root),
|
resolve: createResolve(loader, settings.config.root),
|
||||||
routeCache: new RouteCache(logging, mode),
|
routeCache: new RouteCache(logging, mode),
|
||||||
site: settings.config.site,
|
site: settings.config.site,
|
||||||
ssr: settings.config.output === 'server' || isHybridOutput(settings.config),
|
ssr: isServerLikeOutput(settings.config),
|
||||||
streaming: true,
|
streaming: true,
|
||||||
telemetry: Boolean(settings.forceDisableTelemetry),
|
telemetry: Boolean(settings.forceDisableTelemetry),
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { createRequire } from 'module';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import slash from 'slash';
|
import slash from 'slash';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { isHybridOutput } from '../../../prerender/utils.js';
|
import { getPrerenderDefault } from '../../../prerender/utils.js';
|
||||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
|
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
|
||||||
import { warn } from '../../logger/core.js';
|
import { warn } from '../../logger/core.js';
|
||||||
import { removeLeadingForwardSlash } from '../../path.js';
|
import { removeLeadingForwardSlash } from '../../path.js';
|
||||||
|
@ -251,7 +251,7 @@ export function createRouteManifest(
|
||||||
]);
|
]);
|
||||||
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
|
const validEndpointExtensions: Set<string> = new Set(['.js', '.ts']);
|
||||||
const localFs = fsMod ?? nodeFs;
|
const localFs = fsMod ?? nodeFs;
|
||||||
const isPrerenderDefault = isHybridOutput(settings.config);
|
const prerender = getPrerenderDefault(settings.config);
|
||||||
|
|
||||||
const foundInvalidFileExtensions: Set<string> = new Set();
|
const foundInvalidFileExtensions: Set<string> = new Set();
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ export function createRouteManifest(
|
||||||
component,
|
component,
|
||||||
generate,
|
generate,
|
||||||
pathname: pathname || undefined,
|
pathname: pathname || undefined,
|
||||||
prerender: isPrerenderDefault,
|
prerender,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -440,7 +440,7 @@ export function createRouteManifest(
|
||||||
component,
|
component,
|
||||||
generate,
|
generate,
|
||||||
pathname: pathname || void 0,
|
pathname: pathname || void 0,
|
||||||
prerender: isPrerenderDefault,
|
prerender,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import slash from 'slash';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { normalizePath } from 'vite';
|
import { normalizePath } from 'vite';
|
||||||
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
|
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
|
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
|
||||||
import type { ModuleLoader } from './module-loader';
|
import type { ModuleLoader } from './module-loader';
|
||||||
import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
|
import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
|
||||||
|
@ -139,9 +139,7 @@ export function isEndpoint(file: URL, settings: AstroSettings): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isModeServerWithNoAdapter(settings: AstroSettings): boolean {
|
export function isModeServerWithNoAdapter(settings: AstroSettings): boolean {
|
||||||
return (
|
return isServerLikeOutput(settings.config) && !settings.adapter;
|
||||||
(settings.config.output === 'server' || isHybridOutput(settings.config)) && !settings.adapter
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function relativeToSrcDir(config: AstroConfig, idOrUrl: URL | string) {
|
export function relativeToSrcDir(config: AstroConfig, idOrUrl: URL | string) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import type { PageBuildData } from '../core/build/types';
|
||||||
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
|
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
|
||||||
import { mergeConfig } from '../core/config/config.js';
|
import { mergeConfig } from '../core/config/config.js';
|
||||||
import { info, type LogOptions } from '../core/logger/core.js';
|
import { info, type LogOptions } from '../core/logger/core.js';
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { mdxContentEntryType } from '../vite-plugin-markdown/content-entry-type.js';
|
import { mdxContentEntryType } from '../vite-plugin-markdown/content-entry-type.js';
|
||||||
|
|
||||||
async function withTakingALongTimeMsg<T>({
|
async function withTakingALongTimeMsg<T>({
|
||||||
|
@ -334,8 +334,7 @@ export async function runHookBuildGenerated({
|
||||||
buildConfig: BuildConfig;
|
buildConfig: BuildConfig;
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
}) {
|
}) {
|
||||||
const dir =
|
const dir = isServerLikeOutput(config) ? buildConfig.client : config.outDir;
|
||||||
config.output === 'server' || isHybridOutput(config) ? buildConfig.client : config.outDir;
|
|
||||||
|
|
||||||
for (const integration of config.integrations) {
|
for (const integration of config.integrations) {
|
||||||
if (integration?.hooks?.['astro:build:generated']) {
|
if (integration?.hooks?.['astro:build:generated']) {
|
||||||
|
@ -361,8 +360,7 @@ export async function runHookBuildDone({
|
||||||
routes: RouteData[];
|
routes: RouteData[];
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
}) {
|
}) {
|
||||||
const dir =
|
const dir = isServerLikeOutput(config) ? buildConfig.client : config.outDir;
|
||||||
config.output === 'server' || isHybridOutput(config) ? buildConfig.client : config.outDir;
|
|
||||||
await fs.promises.mkdir(dir, { recursive: true });
|
await fs.promises.mkdir(dir, { recursive: true });
|
||||||
|
|
||||||
for (const integration of config.integrations) {
|
for (const integration of config.integrations) {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
// TODO: remove after the experimetal phase when
|
|
||||||
|
|
||||||
import type { AstroConfig } from '../@types/astro';
|
import type { AstroConfig } from '../@types/astro';
|
||||||
|
|
||||||
export function isHybridMalconfigured(config: AstroConfig) {
|
export function isServerLikeOutput(config: AstroConfig) {
|
||||||
return config.experimental.hybridOutput ? config.output !== 'hybrid' : config.output === 'hybrid';
|
return config.output === 'server' || config.output === 'hybrid';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isHybridOutput(config: AstroConfig) {
|
export function getPrerenderDefault(config: AstroConfig) {
|
||||||
return config.experimental.hybridOutput && config.output === 'hybrid';
|
return config.output === 'hybrid';
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { error } from '../core/logger/core.js';
|
||||||
import * as msg from '../core/messages.js';
|
import * as msg from '../core/messages.js';
|
||||||
import { removeTrailingForwardSlash } from '../core/path.js';
|
import { removeTrailingForwardSlash } from '../core/path.js';
|
||||||
import { eventError, telemetry } from '../events/index.js';
|
import { eventError, telemetry } from '../events/index.js';
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { runWithErrorHandling } from './controller.js';
|
import { runWithErrorHandling } from './controller.js';
|
||||||
import { handle500Response } from './response.js';
|
import { handle500Response } from './response.js';
|
||||||
import { handleRoute, matchRoute } from './route.js';
|
import { handleRoute, matchRoute } from './route.js';
|
||||||
|
@ -25,7 +25,7 @@ export async function handleRequest(
|
||||||
const { settings, loader: moduleLoader } = env;
|
const { settings, loader: moduleLoader } = env;
|
||||||
const { config } = settings;
|
const { config } = settings;
|
||||||
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
|
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
|
||||||
const buildingToSSR = config.output === 'server' || isHybridOutput(config);
|
const buildingToSSR = isServerLikeOutput(config);
|
||||||
|
|
||||||
const url = new URL(origin + req.url);
|
const url = new URL(origin + req.url);
|
||||||
let pathname: string;
|
let pathname: string;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/index.
|
||||||
import { createRequest } from '../core/request.js';
|
import { createRequest } from '../core/request.js';
|
||||||
import { matchAllRoutes } from '../core/routing/index.js';
|
import { matchAllRoutes } from '../core/routing/index.js';
|
||||||
import { getSortedPreloadedMatches } from '../prerender/routing.js';
|
import { getSortedPreloadedMatches } from '../prerender/routing.js';
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||||
import { log404 } from './common.js';
|
import { log404 } from './common.js';
|
||||||
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
|
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ export async function matchRoute(
|
||||||
routeCache,
|
routeCache,
|
||||||
pathname: pathname,
|
pathname: pathname,
|
||||||
logging,
|
logging,
|
||||||
ssr: settings.config.output === 'server' || isHybridOutput(settings.config),
|
ssr: isServerLikeOutput(settings.config),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (paramsAndPropsRes !== GetParamsAndPropsError.NoMatchingStaticPath) {
|
if (paramsAndPropsRes !== GetParamsAndPropsError.NoMatchingStaticPath) {
|
||||||
|
@ -142,7 +142,7 @@ export async function handleRoute(
|
||||||
const { config } = settings;
|
const { config } = settings;
|
||||||
const filePath: URL | undefined = matchedRoute.filePath;
|
const filePath: URL | undefined = matchedRoute.filePath;
|
||||||
const { route, preloadedComponent, mod } = matchedRoute;
|
const { route, preloadedComponent, mod } = matchedRoute;
|
||||||
const buildingToSSR = config.output === 'server' || isHybridOutput(config);
|
const buildingToSSR = isServerLikeOutput(config);
|
||||||
|
|
||||||
// Headers are only available when using SSR.
|
// Headers are only available when using SSR.
|
||||||
const request = createRequest({
|
const request = createRequest({
|
||||||
|
@ -168,7 +168,7 @@ export async function handleRoute(
|
||||||
routeCache: env.routeCache,
|
routeCache: env.routeCache,
|
||||||
pathname: pathname,
|
pathname: pathname,
|
||||||
logging,
|
logging,
|
||||||
ssr: config.output === 'server' || isHybridOutput(config),
|
ssr: isServerLikeOutput(config),
|
||||||
});
|
});
|
||||||
|
|
||||||
const options: SSROptions = {
|
const options: SSROptions = {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { normalizePath, type Plugin as VitePlugin } from 'vite';
|
||||||
import type { AstroSettings } from '../@types/astro.js';
|
import type { AstroSettings } from '../@types/astro.js';
|
||||||
import { isEndpoint, isPage } from '../core/util.js';
|
import { isEndpoint, isPage } from '../core/util.js';
|
||||||
|
|
||||||
import { isHybridOutput } from '../prerender/utils.js';
|
import { getPrerenderDefault } from '../prerender/utils.js';
|
||||||
import { scan } from './scan.js';
|
import { scan } from './scan.js';
|
||||||
|
|
||||||
export default function astroScannerPlugin({ settings }: { settings: AstroSettings }): VitePlugin {
|
export default function astroScannerPlugin({ settings }: { settings: AstroSettings }): VitePlugin {
|
||||||
|
@ -25,11 +25,11 @@ export default function astroScannerPlugin({ settings }: { settings: AstroSettin
|
||||||
const fileIsPage = isPage(fileURL, settings);
|
const fileIsPage = isPage(fileURL, settings);
|
||||||
const fileIsEndpoint = isEndpoint(fileURL, settings);
|
const fileIsEndpoint = isEndpoint(fileURL, settings);
|
||||||
if (!(fileIsPage || fileIsEndpoint)) return;
|
if (!(fileIsPage || fileIsEndpoint)) return;
|
||||||
const hybridOutput = isHybridOutput(settings.config);
|
const defaultPrerender = getPrerenderDefault(settings.config);
|
||||||
const pageOptions = await scan(code, id, hybridOutput);
|
const pageOptions = await scan(code, id, settings.config.output === 'hybrid');
|
||||||
|
|
||||||
if (typeof pageOptions.prerender === 'undefined') {
|
if (typeof pageOptions.prerender === 'undefined') {
|
||||||
pageOptions.prerender = hybridOutput ? true : false;
|
pageOptions.prerender = defaultPrerender;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { meta = {} } = this.getModuleInfo(id) ?? {};
|
const { meta = {} } = this.getModuleInfo(id) ?? {};
|
||||||
|
|
|
@ -144,9 +144,6 @@ describe('Prerender', () => {
|
||||||
adapter: testAdapter(),
|
adapter: testAdapter(),
|
||||||
base: '/blog',
|
base: '/blog',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [vitePluginRemovePrerenderExport()],
|
plugins: [vitePluginRemovePrerenderExport()],
|
||||||
},
|
},
|
||||||
|
|
|
@ -133,9 +133,6 @@ describe('Route matching', () => {
|
||||||
userConfig: {
|
userConfig: {
|
||||||
trailingSlash: 'never',
|
trailingSlash: 'never',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
adapter: testAdapter(),
|
adapter: testAdapter(),
|
||||||
},
|
},
|
||||||
disableTelemetry: true,
|
disableTelemetry: true,
|
||||||
|
|
|
@ -38,9 +38,6 @@ describe('Hybrid rendering', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/prerender/',
|
root: './fixtures/prerender/',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ssgBuild } from './build/ssg.js';
|
||||||
import type { ImageService, SSRImageService, TransformOptions } from './loaders/index.js';
|
import type { ImageService, SSRImageService, TransformOptions } from './loaders/index.js';
|
||||||
import type { LoggerLevel } from './utils/logger.js';
|
import type { LoggerLevel } from './utils/logger.js';
|
||||||
import { joinPaths, prependForwardSlash, propsToFilename } from './utils/paths.js';
|
import { joinPaths, prependForwardSlash, propsToFilename } from './utils/paths.js';
|
||||||
import { isHybridOutput } from './utils/prerender.js';
|
import { isServerLikeOutput } from './utils/prerender.js';
|
||||||
import { createPlugin } from './vite-plugin-astro-image.js';
|
import { createPlugin } from './vite-plugin-astro-image.js';
|
||||||
|
|
||||||
export { getImage } from './lib/get-image.js';
|
export { getImage } from './lib/get-image.js';
|
||||||
|
@ -85,7 +85,7 @@ export default function integration(options: IntegrationOptions = {}): AstroInte
|
||||||
vite: getViteConfiguration(command === 'dev'),
|
vite: getViteConfiguration(command === 'dev'),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (command === 'dev' || config.output === 'server' || isHybridOutput(config)) {
|
if (command === 'dev' || isServerLikeOutput(config)) {
|
||||||
injectRoute({
|
injectRoute({
|
||||||
pattern: ROUTE_PATTERN,
|
pattern: ROUTE_PATTERN,
|
||||||
entryPoint: '@astrojs/image/endpoint',
|
entryPoint: '@astrojs/image/endpoint',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { AstroConfig } from 'astro';
|
import type { AstroConfig } from 'astro';
|
||||||
|
|
||||||
export function isHybridOutput(config: AstroConfig) {
|
export function isServerLikeOutput(config: AstroConfig) {
|
||||||
return config.experimental.hybridOutput && config.output === 'hybrid';
|
return config.output === 'server' || config.output === 'hybrid';
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,6 @@ const isHybridMode = process.env.PRERENDER === "false";
|
||||||
/** @type {import('astro').AstroConfig} */
|
/** @type {import('astro').AstroConfig} */
|
||||||
const partialConfig = {
|
const partialConfig = {
|
||||||
output: isHybridMode ? "hybrid" : "server",
|
output: isHybridMode ? "hybrid" : "server",
|
||||||
...(isHybridMode
|
|
||||||
? ({
|
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
: ({})),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
|
|
@ -46,9 +46,6 @@ describe('Mixed Hybrid rendering with SSR', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: new URL('./fixtures/prerender/', import.meta.url).toString(),
|
root: new URL('./fixtures/prerender/', import.meta.url).toString(),
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
adapter: netlifyAdapter({
|
adapter: netlifyAdapter({
|
||||||
dist: new URL('./fixtures/prerender/dist/', import.meta.url),
|
dist: new URL('./fixtures/prerender/dist/', import.meta.url),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -140,9 +140,6 @@ describe('Hybrid rendering', () => {
|
||||||
base: '/some-base',
|
base: '/some-base',
|
||||||
root: './fixtures/prerender/',
|
root: './fixtures/prerender/',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
adapter: nodejs({ mode: 'standalone' }),
|
adapter: nodejs({ mode: 'standalone' }),
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
|
@ -199,9 +196,6 @@ describe('Hybrid rendering', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/prerender/',
|
root: './fixtures/prerender/',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
adapter: nodejs({ mode: 'standalone' }),
|
adapter: nodejs({ mode: 'standalone' }),
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { AstroConfig } from 'astro';
|
import type { AstroConfig } from 'astro';
|
||||||
|
|
||||||
export function isHybridOutput(config: AstroConfig) {
|
export function isServerLikeOutput(config: AstroConfig) {
|
||||||
return config.experimental.hybridOutput && config.output === 'hybrid';
|
return config.output === 'server' || config.output === 'hybrid';
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
} from '../image/shared.js';
|
} from '../image/shared.js';
|
||||||
import { exposeEnv } from '../lib/env.js';
|
import { exposeEnv } from '../lib/env.js';
|
||||||
import { emptyDir, getVercelOutput, writeJson } from '../lib/fs.js';
|
import { emptyDir, getVercelOutput, writeJson } from '../lib/fs.js';
|
||||||
import { isHybridOutput } from '../lib/prerender.js';
|
import { isServerLikeOutput } from '../lib/prerender.js';
|
||||||
import { getRedirects } from '../lib/redirects.js';
|
import { getRedirects } from '../lib/redirects.js';
|
||||||
|
|
||||||
const PACKAGE_NAME = '@astrojs/vercel/static';
|
const PACKAGE_NAME = '@astrojs/vercel/static';
|
||||||
|
@ -56,7 +56,7 @@ export default function vercelStatic({
|
||||||
setAdapter(getAdapter());
|
setAdapter(getAdapter());
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
if (config.output === 'server' || isHybridOutput(config)) {
|
if (isServerLikeOutput(config)) {
|
||||||
throw new Error(`${PACKAGE_NAME} should be used with output: 'static'`);
|
throw new Error(`${PACKAGE_NAME} should be used with output: 'static'`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,9 +27,6 @@ describe('Serverless hybrid rendering', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/serverless-prerender/',
|
root: './fixtures/serverless-prerender/',
|
||||||
output: 'hybrid',
|
output: 'hybrid',
|
||||||
experimental: {
|
|
||||||
hybridOutput: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue