diff options
Diffstat (limited to 'packages/integrations/netlify/src')
5 files changed, 24 insertions, 129 deletions
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts index 510e560f1..a374020f9 100644 --- a/packages/integrations/netlify/src/index.ts +++ b/packages/integrations/netlify/src/index.ts @@ -1,3 +1,2 @@ -export { netlifyEdgeFunctions } from './integration-edge-functions.js'; export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js'; export { netlifyStatic } from './integration-static.js'; diff --git a/packages/integrations/netlify/src/integration-edge-functions.ts b/packages/integrations/netlify/src/integration-edge-functions.ts deleted file mode 100644 index ac7c124fb..000000000 --- a/packages/integrations/netlify/src/integration-edge-functions.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro'; -import { - bundleServerEntry, - createEdgeManifest, - createRedirects, - type NetlifyEdgeFunctionsOptions, -} from './shared.js'; - -export function getAdapter(): AstroAdapter { - return { - name: '@astrojs/netlify/edge-functions', - serverEntrypoint: '@astrojs/netlify/netlify-edge-functions.js', - exports: ['default'], - }; -} - -export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {}): AstroIntegration { - let _config: AstroConfig; - let entryFile: string; - let _buildConfig: AstroConfig['build']; - let _vite: any; - return { - name: '@astrojs/netlify/edge-functions', - hooks: { - 'astro:config:setup': ({ config, updateConfig }) => { - const outDir = dist ?? new URL('./dist/', config.root); - updateConfig({ - outDir, - build: { - client: outDir, - server: new URL('./.netlify/edge-functions/', config.root), - // Netlify expects .js and will always interpret as ESM - serverEntry: 'entry.js', - }, - }); - }, - 'astro:config:done': ({ config, setAdapter }) => { - setAdapter(getAdapter()); - _config = config; - _buildConfig = config.build; - entryFile = config.build.serverEntry.replace(/\.m?js/, ''); - - if (config.output === 'static') { - console.warn( - `[@astrojs/netlify] \`output: "server"\` or \`output: "hybrid"\` is required to use this adapter.` - ); - console.warn( - `[@astrojs/netlify] Otherwise, this adapter is not required to deploy a static site to Netlify.` - ); - } - }, - 'astro:build:setup': ({ vite, target }) => { - if (target === 'server') { - _vite = vite; - vite.resolve = vite.resolve || {}; - vite.resolve.alias = vite.resolve.alias || {}; - - const aliases = [{ find: 'react-dom/server', replacement: 'react-dom/server.browser' }]; - - if (Array.isArray(vite.resolve.alias)) { - vite.resolve.alias = [...vite.resolve.alias, ...aliases]; - } else { - for (const alias of aliases) { - (vite.resolve.alias as Record<string, string>)[alias.find] = alias.replacement; - } - } - - vite.ssr = { - noExternal: true, - }; - } - }, - 'astro:build:done': async ({ routes, dir }) => { - const entryUrl = new URL(_buildConfig.serverEntry, _buildConfig.server); - await bundleServerEntry(entryUrl, _buildConfig.server, _vite); - await createEdgeManifest(routes, entryFile, _config.root); - const dynamicTarget = `/.netlify/edge-functions/${entryFile}`; - const map: [RouteData, string][] = routes.map((route) => { - return [route, dynamicTarget]; - }); - const routeToDynamicTargetMap = new Map(Array.from(map)); - await createRedirects(_config, routeToDynamicTargetMap, dir); - }, - }, - }; -} - -export { netlifyEdgeFunctions as default }; diff --git a/packages/integrations/netlify/src/integration-functions.ts b/packages/integrations/netlify/src/integration-functions.ts index a950167e5..b8d56ad65 100644 --- a/packages/integrations/netlify/src/integration-functions.ts +++ b/packages/integrations/netlify/src/integration-functions.ts @@ -8,12 +8,26 @@ 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, + }, + supportedAstroFeatures: { + hybridOutput: 'stable', + staticOutput: 'stable', + serverOutput: 'stable', + assets: { + supportKind: 'stable', + isSharpCompatible: true, + isSquooshCompatible: true, + }, + }, }; } @@ -21,12 +35,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 +71,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/, ''); diff --git a/packages/integrations/netlify/src/netlify-edge-functions.ts b/packages/integrations/netlify/src/netlify-edge-functions.ts deleted file mode 100644 index 5e95035a6..000000000 --- a/packages/integrations/netlify/src/netlify-edge-functions.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { Context } from '@netlify/edge-functions'; -import type { SSRManifest } from 'astro'; -import { App } from 'astro/app'; - -const clientAddressSymbol = Symbol.for('astro.clientAddress'); - -export function createExports(manifest: SSRManifest) { - const app = new App(manifest); - - const handler = async (request: Request, context: Context): Promise<Response | void> => { - const url = new URL(request.url); - - // If this matches a static asset, just return and Netlify will forward it - // to its static asset handler. - if (manifest.assets.has(url.pathname)) { - return; - } - const routeData = app.match(request); - const ip = - request.headers.get('x-nf-client-connection-ip') || - context?.ip || - (context as any)?.remoteAddr?.hostname; - Reflect.set(request, clientAddressSymbol, ip); - const response = await app.render(request, routeData); - if (app.setCookieHeaders) { - for (const setCookieHeader of app.setCookieHeaders(response)) { - response.headers.append('Set-Cookie', setCookieHeader); - } - } - return response; - }; - - return { default: handler }; -} diff --git a/packages/integrations/netlify/src/netlify-functions.ts b/packages/integrations/netlify/src/netlify-functions.ts index c45c1b9ef..8c051d9f6 100644 --- a/packages/integrations/netlify/src/netlify-functions.ts +++ b/packages/integrations/netlify/src/netlify-functions.ts @@ -1,16 +1,16 @@ -import { polyfill } from '@astrojs/webapi'; import { builder, type Handler } from '@netlify/functions'; import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; +import { applyPolyfills } from 'astro/app/node'; import { ASTRO_LOCALS_HEADER } from './integration-functions.js'; -polyfill(globalThis, { - exclude: 'window document', -}); +applyPolyfills(); export interface Args { builders?: boolean; binaryMediaTypes?: string[]; + edgeMiddleware: boolean; + functionPerRoute: boolean; } function parseContentType(header?: string) { |