diff --git a/.changeset/weak-wombats-swim.md b/.changeset/weak-wombats-swim.md
deleted file mode 100644
index b26399ac87..0000000000
--- a/.changeset/weak-wombats-swim.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-'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.
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 1766968c09..c3372ec25d 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -1141,6 +1141,44 @@ export interface AstroUserConfig {
* ```
*/
middleware?: 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
+ * }
+ * ---
+ *
+ * ```
+ */
+ hybridOutput?: boolean;
};
// Legacy options to be removed
diff --git a/packages/astro/src/assets/generate.ts b/packages/astro/src/assets/generate.ts
index d6cb02e560..a7a9ddd2d3 100644
--- a/packages/astro/src/assets/generate.ts
+++ b/packages/astro/src/assets/generate.ts
@@ -3,7 +3,7 @@ import { basename, join } from 'node:path/posix';
import type { StaticBuildOptions } from '../core/build/types.js';
import { warn } from '../core/logger/core.js';
import { prependForwardSlash } from '../core/path.js';
-import { isServerLikeOutput } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { getConfiguredImageService, isESMImportedImage } from './internal.js';
import type { LocalImageService } from './services/service.js';
import type { ImageTransform } from './types.js';
@@ -47,7 +47,7 @@ export async function generateImage(
}
let serverRoot: URL, clientRoot: URL;
- if (isServerLikeOutput(buildOpts.settings.config)) {
+ if (buildOpts.settings.config.output === 'server' || isHybridOutput(buildOpts.settings.config)) {
serverRoot = buildOpts.settings.config.build.server;
clientRoot = buildOpts.settings.config.build.client;
} else {
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 056b91263a..a12313987b 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -31,7 +31,7 @@ import {
removeTrailingForwardSlash,
} from '../../core/path.js';
import { runHookBuildGenerated } from '../../integrations/index.js';
-import { isServerLikeOutput } from '../../prerender/utils.js';
+import { isHybridOutput } from '../../prerender/utils.js';
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { callEndpoint, createAPIContext, throwIfRedirectNotAllowed } from '../endpoint/index.js';
import { AstroError } from '../errors/index.js';
@@ -94,7 +94,7 @@ export function chunkIsPage(
export async function generatePages(opts: StaticBuildOptions, internals: BuildInternals) {
const timer = performance.now();
- const ssr = isServerLikeOutput(opts.settings.config);
+ const ssr = opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config); // hybrid mode is essentially SSR with prerender by default
const serverEntry = opts.buildConfig.serverEntry;
const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
@@ -237,7 +237,7 @@ async function getPathsForRoute(
route: pageData.route,
isValidate: false,
logging: opts.logging,
- ssr: isServerLikeOutput(opts.settings.config),
+ ssr: opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config),
})
.then((_result) => {
const label = _result.staticPaths.length === 1 ? 'page' : 'pages';
@@ -413,7 +413,7 @@ async function generatePath(
}
}
- const ssr = isServerLikeOutput(settings.config);
+ const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
const url = getUrlForPath(
pathname,
opts.settings.config.base,
diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts
index 062fab77b0..accdd01ad6 100644
--- a/packages/astro/src/core/build/plugins/plugin-ssr.ts
+++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts
@@ -3,7 +3,7 @@ import { fileURLToPath } from 'url';
import type { Plugin as VitePlugin } from 'vite';
import type { AstroAdapter } from '../../../@types/astro';
import { runHookBuildSsr } from '../../../integrations/index.js';
-import { isServerLikeOutput } from '../../../prerender/utils.js';
+import { isHybridOutput } from '../../../prerender/utils.js';
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js';
import type { SerializedRouteInfo, SerializedSSRManifest } from '../../app/types';
import { joinPaths, prependForwardSlash } from '../../path.js';
@@ -272,7 +272,8 @@ export function pluginSSR(
options: StaticBuildOptions,
internals: BuildInternals
): AstroBuildPlugin {
- const ssr = isServerLikeOutput(options.settings.config);
+ const ssr =
+ options.settings.config.output === 'server' || isHybridOutput(options.settings.config);
return {
build: 'ssr',
hooks: {
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 06ce9d7eed..cceaa03613 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -15,7 +15,7 @@ import { emptyDir, removeEmptyDirs } from '../../core/fs/index.js';
import { appendForwardSlash, prependForwardSlash } from '../../core/path.js';
import { isModeServerWithNoAdapter } from '../../core/util.js';
import { runHookBuildSetup } from '../../integrations/index.js';
-import { isServerLikeOutput } from '../../prerender/utils.js';
+import { isHybridOutput } from '../../prerender/utils.js';
import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import { info } from '../logger/core.js';
@@ -117,6 +117,7 @@ export async function viteBuild(opts: StaticBuildOptions) {
export async function staticBuild(opts: StaticBuildOptions, internals: BuildInternals) {
const { settings } = opts;
+ const hybridOutput = isHybridOutput(settings.config);
switch (true) {
case settings.config.output === 'static': {
settings.timer.start('Static generate');
@@ -125,7 +126,7 @@ export async function staticBuild(opts: StaticBuildOptions, internals: BuildInte
settings.timer.end('Static generate');
return;
}
- case isServerLikeOutput(settings.config): {
+ case settings.config.output === 'server' || hybridOutput: {
settings.timer.start('Server generate');
await generatePages(opts, internals);
await cleanStaticOutput(opts, internals);
@@ -144,7 +145,7 @@ async function ssrBuild(
container: AstroBuildPluginContainer
) {
const { settings, viteConfig } = opts;
- const ssr = isServerLikeOutput(settings.config);
+ const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir);
const { lastVitePlugins, vitePlugins } = container.runBeforeHook('ssr', input);
@@ -224,7 +225,7 @@ async function clientBuild(
) {
const { settings, viteConfig } = opts;
const timer = performance.now();
- const ssr = isServerLikeOutput(settings.config);
+ const ssr = settings.config.output === 'server' || isHybridOutput(settings.config);
const out = ssr ? opts.buildConfig.client : getOutDirWithinCwd(settings.config.outDir);
// Nothing to do if there is no client-side JS.
@@ -289,11 +290,12 @@ async function runPostBuildHooks(
const config = container.options.settings.config;
const buildConfig = container.options.settings.config.build;
for (const [fileName, mutation] of mutations) {
- const root = isServerLikeOutput(config)
- ? mutation.build === 'server'
- ? buildConfig.server
- : buildConfig.client
- : config.outDir;
+ const root =
+ config.output === 'server' || isHybridOutput(config)
+ ? mutation.build === 'server'
+ ? buildConfig.server
+ : buildConfig.client
+ : config.outDir;
const fileURL = new URL(fileName, root);
await fs.promises.mkdir(new URL('./', fileURL), { recursive: true });
await fs.promises.writeFile(fileURL, mutation.code, 'utf-8');
@@ -310,7 +312,7 @@ async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInter
if (pageData.route.prerender)
allStaticFiles.add(internals.pageToBundleMap.get(pageData.moduleSpecifier));
}
- const ssr = isServerLikeOutput(opts.settings.config);
+ const ssr = opts.settings.config.output === 'server' || isHybridOutput(opts.settings.config);
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
// The SSR output is all .mjs files, the client output is not.
const files = await glob('**/*.mjs', {
diff --git a/packages/astro/src/core/config/config.ts b/packages/astro/src/core/config/config.ts
index 9915ed162b..0ca13a2209 100644
--- a/packages/astro/src/core/config/config.ts
+++ b/packages/astro/src/core/config/config.ts
@@ -6,6 +6,7 @@ import * as colors from 'kleur/colors';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import { mergeConfig as mergeViteConfig } from 'vite';
+import { isHybridMalconfigured } from '../../prerender/utils.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
import type { LogOptions } from '../logger/core.js';
import { arraify, isObject, isURL } from '../util.js';
@@ -223,6 +224,12 @@ export async function openConfig(configOptions: LoadConfigOptions): Promise = new Set(['.js', '.ts']);
const localFs = fsMod ?? nodeFs;
- const prerender = getPrerenderDefault(settings.config);
+ const isPrerenderDefault = isHybridOutput(settings.config);
const foundInvalidFileExtensions: Set = new Set();
@@ -341,7 +341,7 @@ export function createRouteManifest(
component,
generate,
pathname: pathname || undefined,
- prerender,
+ prerender: isPrerenderDefault,
});
}
});
@@ -417,7 +417,7 @@ export function createRouteManifest(
component,
generate,
pathname: pathname || void 0,
- prerender,
+ prerender: isPrerenderDefault,
});
});
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 11e792b78d..c12bd03add 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -4,7 +4,7 @@ import slash from 'slash';
import { fileURLToPath } from 'url';
import { normalizePath } from 'vite';
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
-import { isServerLikeOutput } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
import type { ModuleLoader } from './module-loader';
import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
@@ -139,7 +139,9 @@ export function isEndpoint(file: URL, settings: AstroSettings): boolean {
}
export function isModeServerWithNoAdapter(settings: AstroSettings): boolean {
- return isServerLikeOutput(settings.config) && !settings.adapter;
+ return (
+ (settings.config.output === 'server' || isHybridOutput(settings.config)) && !settings.adapter
+ );
}
export function relativeToSrcDir(config: AstroConfig, idOrUrl: URL | string) {
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index 0d8cd6700a..5d88a1196b 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -18,7 +18,7 @@ import type { PageBuildData } from '../core/build/types';
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
import { mergeConfig } from '../core/config/config.js';
import { info, type LogOptions } from '../core/logger/core.js';
-import { isServerLikeOutput } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { mdxContentEntryType } from '../vite-plugin-markdown/content-entry-type.js';
async function withTakingALongTimeMsg({
@@ -339,7 +339,8 @@ export async function runHookBuildGenerated({
buildConfig: BuildConfig;
logging: LogOptions;
}) {
- const dir = isServerLikeOutput(config) ? buildConfig.client : config.outDir;
+ const dir =
+ config.output === 'server' || isHybridOutput(config) ? buildConfig.client : config.outDir;
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:generated']) {
@@ -365,7 +366,8 @@ export async function runHookBuildDone({
routes: RouteData[];
logging: LogOptions;
}) {
- const dir = isServerLikeOutput(config) ? buildConfig.client : config.outDir;
+ const dir =
+ config.output === 'server' || isHybridOutput(config) ? buildConfig.client : config.outDir;
await fs.promises.mkdir(dir, { recursive: true });
for (const integration of config.integrations) {
diff --git a/packages/astro/src/prerender/utils.ts b/packages/astro/src/prerender/utils.ts
index bd6e367ad5..40066035cf 100644
--- a/packages/astro/src/prerender/utils.ts
+++ b/packages/astro/src/prerender/utils.ts
@@ -1,9 +1,11 @@
+// TODO: remove after the experimetal phase when
+
import type { AstroConfig } from '../@types/astro';
-export function isServerLikeOutput(config: AstroConfig) {
- return config.output === 'server' || config.output === 'hybrid';
+export function isHybridMalconfigured(config: AstroConfig) {
+ return config.experimental.hybridOutput ? config.output !== 'hybrid' : config.output === 'hybrid';
}
-export function getPrerenderDefault(config: AstroConfig) {
- return config.output === 'hybrid';
+export function isHybridOutput(config: AstroConfig) {
+ return config.experimental.hybridOutput && config.output === 'hybrid';
}
diff --git a/packages/astro/src/vite-plugin-astro-server/request.ts b/packages/astro/src/vite-plugin-astro-server/request.ts
index adf4199d16..865c5b4013 100644
--- a/packages/astro/src/vite-plugin-astro-server/request.ts
+++ b/packages/astro/src/vite-plugin-astro-server/request.ts
@@ -9,7 +9,7 @@ import { error } from '../core/logger/core.js';
import * as msg from '../core/messages.js';
import { removeTrailingForwardSlash } from '../core/path.js';
import { eventError, telemetry } from '../events/index.js';
-import { isServerLikeOutput } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { runWithErrorHandling } from './controller.js';
import { handle500Response } from './response.js';
import { handleRoute, matchRoute } from './route.js';
@@ -25,7 +25,7 @@ export async function handleRequest(
const { settings, loader: moduleLoader } = env;
const { config } = settings;
const origin = `${moduleLoader.isHttps() ? 'https' : 'http'}://${req.headers.host}`;
- const buildingToSSR = isServerLikeOutput(config);
+ const buildingToSSR = config.output === 'server' || isHybridOutput(config);
const url = new URL(origin + req.url);
let pathname: string;
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index 1e6d1b87d1..dae4162296 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -17,7 +17,7 @@ import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/index.
import { createRequest } from '../core/request.js';
import { matchAllRoutes } from '../core/routing/index.js';
import { getSortedPreloadedMatches } from '../prerender/routing.js';
-import { isServerLikeOutput } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { log404 } from './common.js';
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
@@ -59,7 +59,7 @@ export async function matchRoute(
routeCache,
pathname: pathname,
logging,
- ssr: isServerLikeOutput(settings.config),
+ ssr: settings.config.output === 'server' || isHybridOutput(settings.config),
});
if (paramsAndPropsRes !== GetParamsAndPropsError.NoMatchingStaticPath) {
@@ -132,7 +132,7 @@ export async function handleRoute(
const { config } = settings;
const filePath: URL | undefined = matchedRoute.filePath;
const { route, preloadedComponent, mod } = matchedRoute;
- const buildingToSSR = isServerLikeOutput(config);
+ const buildingToSSR = config.output === 'server' || isHybridOutput(config);
// Headers are only available when using SSR.
const request = createRequest({
@@ -158,7 +158,7 @@ export async function handleRoute(
routeCache: env.routeCache,
pathname: pathname,
logging,
- ssr: isServerLikeOutput(config),
+ ssr: config.output === 'server' || isHybridOutput(config),
});
const options: SSROptions = {
diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts
index 465ff74ed6..a349e7fa6a 100644
--- a/packages/astro/src/vite-plugin-scanner/index.ts
+++ b/packages/astro/src/vite-plugin-scanner/index.ts
@@ -2,7 +2,7 @@ import { normalizePath, type Plugin as VitePlugin } from 'vite';
import type { AstroSettings } from '../@types/astro.js';
import { isEndpoint, isPage } from '../core/util.js';
-import { getPrerenderDefault } from '../prerender/utils.js';
+import { isHybridOutput } from '../prerender/utils.js';
import { scan } from './scan.js';
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 fileIsEndpoint = isEndpoint(fileURL, settings);
if (!(fileIsPage || fileIsEndpoint)) return;
- const defaultPrerender = getPrerenderDefault(settings.config);
- const pageOptions = await scan(code, id, settings.config.output === 'hybrid');
+ const hybridOutput = isHybridOutput(settings.config);
+ const pageOptions = await scan(code, id, hybridOutput);
if (typeof pageOptions.prerender === 'undefined') {
- pageOptions.prerender = defaultPrerender;
+ pageOptions.prerender = hybridOutput ? true : false;
}
const { meta = {} } = this.getModuleInfo(id) ?? {};
diff --git a/packages/astro/test/ssr-prerender-get-static-paths.test.js b/packages/astro/test/ssr-prerender-get-static-paths.test.js
index 6316561d6c..1a17123041 100644
--- a/packages/astro/test/ssr-prerender-get-static-paths.test.js
+++ b/packages/astro/test/ssr-prerender-get-static-paths.test.js
@@ -144,6 +144,9 @@ describe('Prerender', () => {
adapter: testAdapter(),
base: '/blog',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
vite: {
plugins: [vitePluginRemovePrerenderExport()],
},
diff --git a/packages/astro/test/units/routing/route-matching.test.js b/packages/astro/test/units/routing/route-matching.test.js
index 4653617653..6925183828 100644
--- a/packages/astro/test/units/routing/route-matching.test.js
+++ b/packages/astro/test/units/routing/route-matching.test.js
@@ -133,6 +133,9 @@ describe('Route matching', () => {
userConfig: {
trailingSlash: 'never',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
adapter: testAdapter(),
},
disableTelemetry: true,
diff --git a/packages/integrations/cloudflare/test/prerender.test.js b/packages/integrations/cloudflare/test/prerender.test.js
index 526f8a4ac5..5d3ff9f10a 100644
--- a/packages/integrations/cloudflare/test/prerender.test.js
+++ b/packages/integrations/cloudflare/test/prerender.test.js
@@ -38,6 +38,9 @@ describe('Hybrid rendering', () => {
fixture = await loadFixture({
root: './fixtures/prerender/',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
});
await fixture.build();
});
diff --git a/packages/integrations/image/src/index.ts b/packages/integrations/image/src/index.ts
index fb6496c0c0..b2bc114477 100644
--- a/packages/integrations/image/src/index.ts
+++ b/packages/integrations/image/src/index.ts
@@ -3,7 +3,7 @@ import { ssgBuild } from './build/ssg.js';
import type { ImageService, SSRImageService, TransformOptions } from './loaders/index.js';
import type { LoggerLevel } from './utils/logger.js';
import { joinPaths, prependForwardSlash, propsToFilename } from './utils/paths.js';
-import { isServerLikeOutput } from './utils/prerender.js';
+import { isHybridOutput } from './utils/prerender.js';
import { createPlugin } from './vite-plugin-astro-image.js';
export { getImage } from './lib/get-image.js';
@@ -85,7 +85,7 @@ export default function integration(options: IntegrationOptions = {}): AstroInte
vite: getViteConfiguration(command === 'dev'),
});
- if (command === 'dev' || isServerLikeOutput(config)) {
+ if (command === 'dev' || config.output === 'server' || isHybridOutput(config)) {
injectRoute({
pattern: ROUTE_PATTERN,
entryPoint: '@astrojs/image/endpoint',
diff --git a/packages/integrations/image/src/utils/prerender.ts b/packages/integrations/image/src/utils/prerender.ts
index f69f3b5d47..9265c80bf0 100644
--- a/packages/integrations/image/src/utils/prerender.ts
+++ b/packages/integrations/image/src/utils/prerender.ts
@@ -1,5 +1,5 @@
import type { AstroConfig } from 'astro';
-export function isServerLikeOutput(config: AstroConfig) {
- return config.output === 'server' || config.output === 'hybrid';
+export function isHybridOutput(config: AstroConfig) {
+ return config.experimental.hybridOutput && config.output === 'hybrid';
}
diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/prerender/astro.config.mjs
index d049599e59..c579d74eff 100644
--- a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/astro.config.mjs
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/prerender/astro.config.mjs
@@ -6,6 +6,13 @@ const isHybridMode = process.env.PRERENDER === "false";
/** @type {import('astro').AstroConfig} */
const partialConfig = {
output: isHybridMode ? "hybrid" : "server",
+ ...(isHybridMode
+ ? ({
+ experimental: {
+ hybridOutput: true,
+ },
+ })
+ : ({})),
};
export default defineConfig({
diff --git a/packages/integrations/netlify/test/functions/prerender.test.js b/packages/integrations/netlify/test/functions/prerender.test.js
index a571dd76e4..9718df083c 100644
--- a/packages/integrations/netlify/test/functions/prerender.test.js
+++ b/packages/integrations/netlify/test/functions/prerender.test.js
@@ -46,6 +46,9 @@ describe('Mixed Hybrid rendering with SSR', () => {
fixture = await loadFixture({
root: new URL('./fixtures/prerender/', import.meta.url).toString(),
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
adapter: netlifyAdapter({
dist: new URL('./fixtures/prerender/dist/', import.meta.url),
}),
diff --git a/packages/integrations/node/test/prerender.test.js b/packages/integrations/node/test/prerender.test.js
index 4b5522a319..751ed2ae71 100644
--- a/packages/integrations/node/test/prerender.test.js
+++ b/packages/integrations/node/test/prerender.test.js
@@ -140,6 +140,9 @@ describe('Hybrid rendering', () => {
base: '/some-base',
root: './fixtures/prerender/',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
@@ -196,6 +199,9 @@ describe('Hybrid rendering', () => {
fixture = await loadFixture({
root: './fixtures/prerender/',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
diff --git a/packages/integrations/vercel/src/lib/prerender.ts b/packages/integrations/vercel/src/lib/prerender.ts
index f69f3b5d47..9265c80bf0 100644
--- a/packages/integrations/vercel/src/lib/prerender.ts
+++ b/packages/integrations/vercel/src/lib/prerender.ts
@@ -1,5 +1,5 @@
import type { AstroConfig } from 'astro';
-export function isServerLikeOutput(config: AstroConfig) {
- return config.output === 'server' || config.output === 'hybrid';
+export function isHybridOutput(config: AstroConfig) {
+ return config.experimental.hybridOutput && config.output === 'hybrid';
}
diff --git a/packages/integrations/vercel/src/static/adapter.ts b/packages/integrations/vercel/src/static/adapter.ts
index ccbf26e570..0b3579cdd1 100644
--- a/packages/integrations/vercel/src/static/adapter.ts
+++ b/packages/integrations/vercel/src/static/adapter.ts
@@ -8,7 +8,7 @@ import {
} from '../image/shared.js';
import { exposeEnv } from '../lib/env.js';
import { emptyDir, getVercelOutput, writeJson } from '../lib/fs.js';
-import { isServerLikeOutput } from '../lib/prerender.js';
+import { isHybridOutput } from '../lib/prerender.js';
import { getRedirects } from '../lib/redirects.js';
const PACKAGE_NAME = '@astrojs/vercel/static';
@@ -55,7 +55,7 @@ export default function vercelStatic({
setAdapter(getAdapter());
_config = config;
- if (isServerLikeOutput(config)) {
+ if (config.output === 'server' || isHybridOutput(config)) {
throw new Error(`${PACKAGE_NAME} should be used with output: 'static'`);
}
},
diff --git a/packages/integrations/vercel/test/serverless-prerender.test.js b/packages/integrations/vercel/test/serverless-prerender.test.js
index 18b1653404..94d9081f41 100644
--- a/packages/integrations/vercel/test/serverless-prerender.test.js
+++ b/packages/integrations/vercel/test/serverless-prerender.test.js
@@ -27,6 +27,9 @@ describe('Serverless hybrid rendering', () => {
fixture = await loadFixture({
root: './fixtures/serverless-prerender/',
output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
});
});