feat: adapter features, deprecate astro configs (#7839)
This commit is contained in:
parent
7ee1861557
commit
c17e265c0d
20 changed files with 214 additions and 31 deletions
39
.changeset/fair-emus-divide.md
Normal file
39
.changeset/fair-emus-divide.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
'astro': major
|
||||
'@astrojs/netlify': minor
|
||||
---
|
||||
|
||||
The configuration `build.split` and `build.excludeMiddleware` are deprecated.
|
||||
|
||||
Configuration that were inside the astro configuration, are now moved inside the adapter:
|
||||
|
||||
```diff
|
||||
import {defineConfig} from "astro/config";
|
||||
import netlify from "@astrojs/netlify/functions";
|
||||
|
||||
export default defineConfig({
|
||||
- build: {
|
||||
- excludeMiddleware: true
|
||||
- },
|
||||
- adapter: netlify()
|
||||
+ adapter: netlify({
|
||||
+ edgeMiddleware: true
|
||||
+ })
|
||||
})
|
||||
```
|
||||
|
||||
```diff
|
||||
import {defineConfig} from "astro/config";
|
||||
import netlify from "@astrojs/netlify/functions";
|
||||
|
||||
export default defineConfig({
|
||||
- build: {
|
||||
- split: true
|
||||
- },
|
||||
- adapter: netlify()
|
||||
+ adapter: netlify({
|
||||
+ functionPerRoute: true
|
||||
+ })
|
||||
})
|
||||
```
|
||||
|
39
.changeset/tricky-candles-suffer.md
Normal file
39
.changeset/tricky-candles-suffer.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
'astro': major
|
||||
'@astrojs/vercel': minor
|
||||
---
|
||||
|
||||
The configuration `build.split` and `build.excludeMiddleware` are deprecated.
|
||||
|
||||
Configuration that were inside the astro configuration, are now moved inside the adapter:
|
||||
|
||||
```diff
|
||||
import {defineConfig} from "astro/config";
|
||||
import vercel from "@astrojs/vercel/serverless";
|
||||
|
||||
export default defineConfig({
|
||||
- build: {
|
||||
- excludeMiddleware: true
|
||||
- },
|
||||
- adapter: vercel()
|
||||
+ adapter: vercel({
|
||||
+ edgeMiddleware: true
|
||||
+ })
|
||||
})
|
||||
```
|
||||
|
||||
```diff
|
||||
import {defineConfig} from "astro/config";
|
||||
import vercel from "@astrojs/vercel/serverless";
|
||||
|
||||
export default defineConfig({
|
||||
- build: {
|
||||
- split: true
|
||||
- },
|
||||
- adapter: vercel()
|
||||
+ adapter: vercel({
|
||||
+ functionPerRoute: true
|
||||
+ })
|
||||
})
|
||||
```
|
||||
|
|
@ -1410,6 +1410,17 @@ export interface DataEntryType {
|
|||
|
||||
export type GetDataEntryInfoReturnType = { data: Record<string, unknown>; rawData?: string };
|
||||
|
||||
export interface AstroAdapterFeatures {
|
||||
/**
|
||||
* Creates and edge function that will communiate with the Astro middleware
|
||||
*/
|
||||
edgeMiddleware: boolean;
|
||||
/**
|
||||
* SSR only. Each route becomes its own function/file.
|
||||
*/
|
||||
functionPerRoute: boolean;
|
||||
}
|
||||
|
||||
export interface AstroSettings {
|
||||
config: AstroConfig;
|
||||
adapter: AstroAdapter | undefined;
|
||||
|
@ -1674,6 +1685,7 @@ export interface AstroAdapter {
|
|||
previewEntrypoint?: string;
|
||||
exports?: string[];
|
||||
args?: any;
|
||||
adapterFeatures?: AstroAdapterFeatures;
|
||||
}
|
||||
|
||||
type Body = string;
|
||||
|
|
|
@ -74,7 +74,11 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
|
|||
exports.push(`export { renderers };`);
|
||||
|
||||
// The middleware should not be imported by the pages
|
||||
if (!opts.settings.config.build.excludeMiddleware) {
|
||||
if (
|
||||
// TODO: remover in Astro 4.0
|
||||
!opts.settings.config.build.excludeMiddleware ||
|
||||
opts.settings.adapter?.adapterFeatures?.edgeMiddleware === true
|
||||
) {
|
||||
const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID);
|
||||
if (middlewareModule) {
|
||||
imports.push(`import { onRequest } from "${middlewareModule.id}";`);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|||
import { fileURLToPath, pathToFileURL } from 'node:url';
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import type { AstroAdapter, AstroConfig } from '../../../@types/astro';
|
||||
import { runHookBuildSsr } from '../../../integrations/index.js';
|
||||
import { isFunctionPerRouteEnabled, runHookBuildSsr } from '../../../integrations/index.js';
|
||||
import { isServerLikeOutput } 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';
|
||||
|
@ -103,12 +103,16 @@ export function pluginSSR(
|
|||
internals: BuildInternals
|
||||
): AstroBuildPlugin {
|
||||
const ssr = isServerLikeOutput(options.settings.config);
|
||||
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||||
return {
|
||||
build: 'ssr',
|
||||
hooks: {
|
||||
'build:before': () => {
|
||||
let vitePlugin =
|
||||
ssr && !options.settings.config.build.split
|
||||
ssr &&
|
||||
// TODO: Remove in Astro 4.0
|
||||
options.settings.config.build.split === false &&
|
||||
functionPerRouteEnabled === false
|
||||
? vitePluginSSR(internals, options.settings.adapter!, options)
|
||||
: undefined;
|
||||
|
||||
|
@ -122,7 +126,7 @@ export function pluginSSR(
|
|||
return;
|
||||
}
|
||||
|
||||
if (options.settings.config.build.split) {
|
||||
if (options.settings.config.build.split || functionPerRouteEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -155,11 +159,12 @@ function vitePluginSSRSplit(
|
|||
adapter: AstroAdapter,
|
||||
options: StaticBuildOptions
|
||||
): VitePlugin {
|
||||
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||||
return {
|
||||
name: '@astrojs/vite-plugin-astro-ssr-split',
|
||||
enforce: 'post',
|
||||
options(opts) {
|
||||
if (options.settings.config.build.split) {
|
||||
if (options.settings.config.build.split || functionPerRouteEnabled) {
|
||||
const inputs = new Set<string>();
|
||||
|
||||
for (const path of Object.keys(options.allPages)) {
|
||||
|
@ -229,12 +234,14 @@ export function pluginSSRSplit(
|
|||
internals: BuildInternals
|
||||
): AstroBuildPlugin {
|
||||
const ssr = isServerLikeOutput(options.settings.config);
|
||||
const functionPerRouteEnabled = isFunctionPerRouteEnabled(options.settings.adapter);
|
||||
|
||||
return {
|
||||
build: 'ssr',
|
||||
hooks: {
|
||||
'build:before': () => {
|
||||
let vitePlugin =
|
||||
ssr && options.settings.config.build.split
|
||||
ssr && (options.settings.config.build.split || functionPerRouteEnabled)
|
||||
? vitePluginSSRSplit(internals, options.settings.adapter!, options)
|
||||
: undefined;
|
||||
|
||||
|
@ -247,7 +254,7 @@ export function pluginSSRSplit(
|
|||
if (!ssr) {
|
||||
return;
|
||||
}
|
||||
if (!options.settings.config.build.split) {
|
||||
if (!options.settings.config.build.split && !functionPerRouteEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -276,7 +283,7 @@ function generateSSRCode(config: AstroConfig, adapter: AstroAdapter) {
|
|||
const imports: string[] = [];
|
||||
const contents: string[] = [];
|
||||
let pageMap;
|
||||
if (config.build.split) {
|
||||
if (config.build.split || isFunctionPerRouteEnabled(adapter)) {
|
||||
pageMap = 'pageModule';
|
||||
} else {
|
||||
pageMap = 'pageMap';
|
||||
|
@ -337,7 +344,10 @@ export async function createManifest(
|
|||
buildOpts: StaticBuildOptions,
|
||||
internals: BuildInternals
|
||||
): Promise<SerializedSSRManifest> {
|
||||
if (buildOpts.settings.config.build.split) {
|
||||
if (
|
||||
buildOpts.settings.config.build.split ||
|
||||
isFunctionPerRouteEnabled(buildOpts.settings.adapter)
|
||||
) {
|
||||
if (internals.ssrSplitEntryChunks.size === 0) {
|
||||
throw new Error(`Did not generate an entry chunk for SSR in serverless mode`);
|
||||
}
|
||||
|
|
|
@ -124,7 +124,15 @@ export const AstroConfigSchema = z.object({
|
|||
.optional()
|
||||
.default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets),
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use the adapter feature instead
|
||||
*/
|
||||
split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split),
|
||||
/**
|
||||
* @deprecated
|
||||
* Use the adapter feature instead
|
||||
*/
|
||||
excludeMiddleware: z
|
||||
.boolean()
|
||||
.optional()
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { AddressInfo } from 'node:net';
|
|||
import { fileURLToPath } from 'node:url';
|
||||
import type { InlineConfig, ViteDevServer } from 'vite';
|
||||
import type {
|
||||
AstroAdapter,
|
||||
AstroConfig,
|
||||
AstroIntegration,
|
||||
AstroRenderer,
|
||||
|
@ -410,3 +411,19 @@ export async function runHookBuildDone({ config, pages, routes, logging }: RunHo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function isFunctionPerRouteEnabled(adapter: AstroAdapter | undefined): boolean {
|
||||
if (adapter?.adapterFeatures?.functionPerRoute === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isEdgeMiddlewareEnabled(adapter: AstroAdapter | undefined): boolean {
|
||||
if (adapter?.adapterFeatures?.edgeMiddleware === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,16 @@ import { createRedirects } from './shared.js';
|
|||
export const NETLIFY_EDGE_MIDDLEWARE_FILE = 'netlify-edge-middleware';
|
||||
export const ASTRO_LOCALS_HEADER = 'x-astro-locals';
|
||||
|
||||
export function getAdapter(args: Args = {}): AstroAdapter {
|
||||
export function getAdapter({ functionPerRoute, edgeMiddleware, ...args }: Args): AstroAdapter {
|
||||
return {
|
||||
name: '@astrojs/netlify/functions',
|
||||
serverEntrypoint: '@astrojs/netlify/netlify-functions.js',
|
||||
exports: ['handler'],
|
||||
args,
|
||||
adapterFeatures: {
|
||||
functionPerRoute,
|
||||
edgeMiddleware,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,12 +25,16 @@ interface NetlifyFunctionsOptions {
|
|||
dist?: URL;
|
||||
builders?: boolean;
|
||||
binaryMediaTypes?: string[];
|
||||
edgeMiddleware?: boolean;
|
||||
functionPerRoute?: boolean;
|
||||
}
|
||||
|
||||
function netlifyFunctions({
|
||||
dist,
|
||||
builders,
|
||||
binaryMediaTypes,
|
||||
functionPerRoute = false,
|
||||
edgeMiddleware = false,
|
||||
}: NetlifyFunctionsOptions = {}): AstroIntegration {
|
||||
let _config: AstroConfig;
|
||||
let _entryPoints: Map<RouteData, URL>;
|
||||
|
@ -53,7 +61,7 @@ function netlifyFunctions({
|
|||
_entryPoints = entryPoints;
|
||||
},
|
||||
'astro:config:done': ({ config, setAdapter }) => {
|
||||
setAdapter(getAdapter({ binaryMediaTypes, builders }));
|
||||
setAdapter(getAdapter({ binaryMediaTypes, builders, functionPerRoute, edgeMiddleware }));
|
||||
_config = config;
|
||||
ssrEntryFile = config.build.serverEntry.replace(/\.m?js/, '');
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ applyPolyfills();
|
|||
export interface Args {
|
||||
builders?: boolean;
|
||||
binaryMediaTypes?: string[];
|
||||
edgeMiddleware: boolean;
|
||||
functionPerRoute: boolean;
|
||||
}
|
||||
|
||||
function parseContentType(header?: string) {
|
||||
|
|
|
@ -10,6 +10,7 @@ describe('Middleware', () => {
|
|||
output: 'server',
|
||||
adapter: netlifyAdapter({
|
||||
dist: new URL('./fixtures/middleware-with-handler-file/dist/', import.meta.url),
|
||||
edgeMiddleware: true,
|
||||
}),
|
||||
site: `http://example.com`,
|
||||
integrations: [testIntegration()],
|
||||
|
|
|
@ -13,6 +13,7 @@ describe('Split support', () => {
|
|||
output: 'server',
|
||||
adapter: netlifyAdapter({
|
||||
dist: new URL('./fixtures/split-support/dist/', import.meta.url),
|
||||
functionPerRoute: true,
|
||||
}),
|
||||
site: `http://example.com`,
|
||||
integrations: [
|
||||
|
@ -22,9 +23,6 @@ describe('Split support', () => {
|
|||
},
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
split: true,
|
||||
},
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
|
|
@ -29,11 +29,21 @@ const SUPPORTED_NODE_VERSIONS: Record<
|
|||
18: { status: 'current' },
|
||||
};
|
||||
|
||||
function getAdapter(): AstroAdapter {
|
||||
function getAdapter({
|
||||
edgeMiddleware,
|
||||
functionPerRoute,
|
||||
}: {
|
||||
edgeMiddleware: boolean;
|
||||
functionPerRoute: boolean;
|
||||
}): AstroAdapter {
|
||||
return {
|
||||
name: PACKAGE_NAME,
|
||||
serverEntrypoint: `${PACKAGE_NAME}/entrypoint`,
|
||||
exports: ['default'],
|
||||
adapterFeatures: {
|
||||
edgeMiddleware,
|
||||
functionPerRoute,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -43,6 +53,8 @@ export interface VercelServerlessConfig {
|
|||
analytics?: boolean;
|
||||
imageService?: boolean;
|
||||
imagesConfig?: VercelImageConfig;
|
||||
edgeMiddleware?: boolean;
|
||||
functionPerRoute?: boolean;
|
||||
}
|
||||
|
||||
export default function vercelServerless({
|
||||
|
@ -51,6 +63,8 @@ export default function vercelServerless({
|
|||
analytics,
|
||||
imageService,
|
||||
imagesConfig,
|
||||
functionPerRoute = false,
|
||||
edgeMiddleware = false,
|
||||
}: VercelServerlessConfig = {}): AstroIntegration {
|
||||
let _config: AstroConfig;
|
||||
let buildTempFolder: URL;
|
||||
|
@ -112,7 +126,7 @@ export default function vercelServerless({
|
|||
},
|
||||
'astro:config:done': ({ setAdapter, config }) => {
|
||||
throwIfAssetsNotEnabled(config, imageService);
|
||||
setAdapter(getAdapter());
|
||||
setAdapter(getAdapter({ functionPerRoute, edgeMiddleware }));
|
||||
_config = config;
|
||||
buildTempFolder = config.build.server;
|
||||
serverEntry = config.build.serverEntry;
|
||||
|
|
|
@ -2,5 +2,7 @@ import { defineConfig } from 'astro/config';
|
|||
import vercel from '@astrojs/vercel/serverless';
|
||||
|
||||
export default defineConfig({
|
||||
adapter: vercel()
|
||||
adapter: vercel({
|
||||
functionPerRoute: true
|
||||
})
|
||||
});
|
||||
|
|
9
packages/integrations/vercel/test/fixtures/functionPerRoute/astro.config.mjs
vendored
Normal file
9
packages/integrations/vercel/test/fixtures/functionPerRoute/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import vercel from '@astrojs/vercel/serverless';
|
||||
|
||||
export default defineConfig({
|
||||
adapter: vercel({
|
||||
functionPerRoute: true
|
||||
}),
|
||||
output: "server"
|
||||
});
|
9
packages/integrations/vercel/test/fixtures/functionPerRoute/package.json
vendored
Normal file
9
packages/integrations/vercel/test/fixtures/functionPerRoute/package.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "@test/astro-vercel-function-per-route",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@astrojs/vercel": "workspace:*",
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
8
packages/integrations/vercel/test/fixtures/functionPerRoute/src/pages/one.astro
vendored
Normal file
8
packages/integrations/vercel/test/fixtures/functionPerRoute/src/pages/one.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>One</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>One</h1>
|
||||
</body>
|
||||
</html>
|
8
packages/integrations/vercel/test/fixtures/functionPerRoute/src/pages/two.astro
vendored
Normal file
8
packages/integrations/vercel/test/fixtures/functionPerRoute/src/pages/two.astro
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Two</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Two</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -2,9 +2,8 @@ import {defineConfig} from "astro/config";
|
|||
import vercel from "@astrojs/vercel/serverless";
|
||||
|
||||
export default defineConfig({
|
||||
adapter: vercel(),
|
||||
build: {
|
||||
excludeMiddleware: true
|
||||
},
|
||||
adapter: vercel({
|
||||
edgeMiddleware: true
|
||||
}),
|
||||
output: 'server'
|
||||
});
|
|
@ -2,9 +2,8 @@ import {defineConfig} from "astro/config";
|
|||
import vercel from "@astrojs/vercel/serverless";
|
||||
|
||||
export default defineConfig({
|
||||
adapter: vercel(),
|
||||
build: {
|
||||
excludeMiddleware: true
|
||||
},
|
||||
adapter: vercel({
|
||||
edgeMiddleware: true
|
||||
}),
|
||||
output: 'server'
|
||||
});
|
|
@ -7,11 +7,8 @@ describe('build: split', () => {
|
|||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/basic/',
|
||||
root: './fixtures/functionPerRoute/',
|
||||
output: 'server',
|
||||
build: {
|
||||
split: true,
|
||||
},
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue