diff options
Diffstat (limited to 'packages/integrations/netlify')
38 files changed, 175 insertions, 575 deletions
diff --git a/packages/integrations/netlify/CHANGELOG.md b/packages/integrations/netlify/CHANGELOG.md index 2313698d5..0d1e64302 100644 --- a/packages/integrations/netlify/CHANGELOG.md +++ b/packages/integrations/netlify/CHANGELOG.md @@ -1,5 +1,111 @@ # @astrojs/netlify +## 3.0.0-beta.1 + +### Major Changes + +- [#8029](https://github.com/withastro/astro/pull/8029) [`2ee418e06`](https://github.com/withastro/astro/commit/2ee418e06ab1f7855dee0078afbad0b06de3b183) Thanks [@matthewp](https://github.com/matthewp)! - Remove the Netlify Edge adapter + + `@astrojs/netlify/functions` now supports Edge middleware, so a separate adapter for Edge itself (deploying your entire app to the edge) is no longer necessary. Please update your Astro config to reflect this change: + + ```diff + // astro.config.mjs + import { defineConfig } from 'astro/config'; + - import netlify from '@astrojs/netlify/edge'; + + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + output: 'server', + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + This adapter had several known limitations and compatibility issues that prevented many people from using it in production. To reduce maintenance costs and because we have a better story with Serveless + Edge Middleware, we are removing the Edge adapter. + +### Patch Changes + +- Updated dependencies [[`65c354969`](https://github.com/withastro/astro/commit/65c354969e6fe0ef6d622e8f4c545e2f717ce8c6), [`3c3100851`](https://github.com/withastro/astro/commit/3c31008519ce68b5b1b1cb23b71fbe0a2d506882), [`34cb20021`](https://github.com/withastro/astro/commit/34cb2002161ba88df6bcb72fecfd12ed867c134b), [`7bd1b86f8`](https://github.com/withastro/astro/commit/7bd1b86f85c06fdde0a1ed9146d01bac69990671), [`519a1c4e8`](https://github.com/withastro/astro/commit/519a1c4e8407c7abcb8d879b67a9f4b960652cae), [`70f34f5a3`](https://github.com/withastro/astro/commit/70f34f5a355f42526ee9e5355f3de8e510002ea2), [`0f637c71e`](https://github.com/withastro/astro/commit/0f637c71e511cb4c51712128d217a26c8eee4d40), [`866ed4098`](https://github.com/withastro/astro/commit/866ed4098edffb052239cdb26e076cf8db61b1d9), [`5b1e39ef6`](https://github.com/withastro/astro/commit/5b1e39ef6ec6dcebea96584f95d9530bd9aa715d)]: + - astro@3.0.0-beta.1 + - @astrojs/underscore-redirects@0.3.0-beta.0 + +## 3.0.0-beta.0 + +### Major Changes + +- [`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023. + +- [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388) Thanks [@Princesseuh](https://github.com/Princesseuh)! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of `astro:assets` such as enforcing `alt`, no CLS etc to users + +- [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Reduced the amount of polyfills provided by Astro. Astro will no longer provide (no-op) polyfills for several web apis such as HTMLElement, Image or Document. If you need access to those APIs on the server, we recommend using more proper polyfills available on npm. + +### Minor Changes + +- [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215) Thanks [@ematipico](https://github.com/ematipico)! - Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter + can tell Astro if it can support it. + + ```ts + import { AstroIntegration } from './astro'; + + function myIntegration(): AstroIntegration { + return { + name: 'astro-awesome-list', + // new feature map + supportedAstroFeatures: { + hybridOutput: 'experimental', + staticOutput: 'stable', + serverOutput: 'stable', + assets: { + supportKind: 'stable', + isSharpCompatible: false, + isSquooshCompatible: false, + }, + }, + }; + } + ``` + +- [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769) Thanks [@ematipico](https://github.com/ematipico)! - The `build.split` and `build.excludeMiddleware` configuration options are deprecated and have been replaced by options in the adapter config. + + If your config includes the `build.excludeMiddleware` option, replace it with `edgeMiddleware` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - excludeMiddleware: true + }, + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + If your config includes the `build.split` option, replace it with `functionPerRoute` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - split: true + }, + adapter: netlify({ + + functionPerRoute: true + }), + }); + ``` + +### Patch Changes + +- Updated dependencies [[`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81), [`76ddef19c`](https://github.com/withastro/astro/commit/76ddef19ccab6e5f7d3a5740cd41acf10e334b38), [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`2f951cd40`](https://github.com/withastro/astro/commit/2f951cd403dfcc2c3ca6aae618ae3e1409516e32), [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388), [`67becaa58`](https://github.com/withastro/astro/commit/67becaa580b8f787df58de66b7008b7098f1209c), [`bc37331d8`](https://github.com/withastro/astro/commit/bc37331d8154e3e95a8df9131e4e014e78a7a9e7), [`dfc2d93e3`](https://github.com/withastro/astro/commit/dfc2d93e3c645995379358fabbdfa9aab99f43d8), [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a), [`1be84dfee`](https://github.com/withastro/astro/commit/1be84dfee3ce8e6f5cc624f99aec4e980f6fde37), [`35f01df79`](https://github.com/withastro/astro/commit/35f01df797d23315f2bee2fc3fd795adb0559c58), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`78de801f2`](https://github.com/withastro/astro/commit/78de801f21fd4ca1653950027d953bf08614566b), [`59d6e569f`](https://github.com/withastro/astro/commit/59d6e569f63e175c97e82e94aa7974febfb76f7c), [`7723c4cc9`](https://github.com/withastro/astro/commit/7723c4cc93298c2e6530e55da7afda048f22cf81), [`fb5cd6b56`](https://github.com/withastro/astro/commit/fb5cd6b56dc27a71366ed5e1ab8bfe9b8f96bac5), [`631b9c410`](https://github.com/withastro/astro/commit/631b9c410d5d66fa384674027ba95d69ebb5063f)]: + - astro@3.0.0-beta.0 + - @astrojs/underscore-redirects@0.3.0-beta.0 + ## 2.6.0 ### Minor Changes diff --git a/packages/integrations/netlify/README.md b/packages/integrations/netlify/README.md index 8d6c2096e..75e1aad3f 100644 --- a/packages/integrations/netlify/README.md +++ b/packages/integrations/netlify/README.md @@ -55,28 +55,11 @@ If you prefer to install the adapter manually instead, complete the following tw }); ``` -### Edge Functions - -Netlify has two serverless platforms, [Netlify Functions](https://docs.netlify.com/functions/overview/) and [Netlify Edge Functions](https://docs.netlify.com/edge-functions/overview/). With Edge Functions your code is distributed closer to your users, lowering latency. - -To deploy with Edge Functions, use `netlify/edge-functions` in the Astro config file instead of `netlify/functions`. - -```js ins={3} -// astro.config.mjs -import { defineConfig } from 'astro/config'; -import netlify from '@astrojs/netlify/edge-functions'; - -export default defineConfig({ - output: 'server', - adapter: netlify(), -}); -``` - ### Run middleware in Edge Functions When deploying to Netlify Functions, you can choose to use an Edge Function to run your Astro middleware. -To enable this, set the `build.excludeMiddleware` Astro config option to `true`: +To enable this, set the `edgeMiddleware` config option to `true`: ```js ins={9} // astro.config.mjs @@ -85,10 +68,9 @@ import netlify from '@astrojs/netlify/functions'; export default defineConfig({ output: 'server', - adapter: netlify(), - build: { - excludeMiddleware: true, - }, + adapter: netlify({ + edgeMiddleware: true, + }), }); ``` @@ -133,10 +115,9 @@ import netlify from '@astrojs/netlify/functions'; export default defineConfig({ output: 'server', - adapter: netlify(), - build: { - split: true, - }, + adapter: netlify({ + functionPerRoute: true + }), }); ``` diff --git a/packages/integrations/netlify/package.json b/packages/integrations/netlify/package.json index 048e0e1f2..afb841826 100644 --- a/packages/integrations/netlify/package.json +++ b/packages/integrations/netlify/package.json @@ -1,7 +1,7 @@ { "name": "@astrojs/netlify", "description": "Deploy your site to Netlify", - "version": "2.6.0", + "version": "3.0.0-beta.1", "type": "module", "types": "./dist/index.d.ts", "author": "withastro", @@ -26,8 +26,7 @@ "./package.json": "./package.json" }, "files": [ - "dist", - "builders-types.d.ts" + "dist" ], "scripts": { "build": "astro-scripts build \"src/**/*.ts\" && tsc", @@ -39,13 +38,12 @@ "test:hosted": "mocha --exit --timeout 30000 test/hosted" }, "dependencies": { - "@astrojs/underscore-redirects": "^0.2.0", - "@astrojs/webapi": "^2.2.0", + "@astrojs/underscore-redirects": "workspace:*", "@netlify/functions": "^1.6.0", - "esbuild": "^0.15.18" + "esbuild": "^0.18.16" }, "peerDependencies": { - "astro": "workspace:^2.10.9" + "astro": "workspace:^3.0.0-beta.2" }, "devDependencies": { "@netlify/edge-functions": "^2.0.0", 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) { diff --git a/packages/integrations/netlify/test/edge-functions/deps.ts b/packages/integrations/netlify/test/edge-functions/deps.ts deleted file mode 100644 index 6d729970d..000000000 --- a/packages/integrations/netlify/test/edge-functions/deps.ts +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-nocheck -export { fromFileUrl } from 'https://deno.land/std@0.110.0/path/mod.ts'; -export { - assertEquals, - assert, - assertExists, -} from 'https://deno.land/std@0.132.0/testing/asserts.ts'; -export { DOMParser } from 'https://deno.land/x/deno_dom@v0.1.35-alpha/deno-dom-wasm.ts'; -export * from 'https://deno.land/std@0.142.0/streams/conversion.ts'; -export * as cheerio from 'https://cdn.skypack.dev/cheerio?dts'; -export * as fs from 'https://deno.land/std/fs/mod.ts'; diff --git a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.ts b/packages/integrations/netlify/test/edge-functions/dynamic-import.test.ts deleted file mode 100644 index 89a640b0b..000000000 --- a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { loadFixture } from './test-utils.ts'; -import { assertEquals, assert, DOMParser } from './deps.ts'; - -Deno.test({ - name: 'Dynamic imports', - permissions: 'inherit', - async fn() { - const { runApp, runBuild } = await loadFixture('./fixtures/dynimport/'); - await runBuild(); - const stop = await runApp('./fixtures/dynimport/prod.js'); - - try { - const response = await fetch('http://127.0.0.1:8085/'); - assertEquals(response.status, 200); - const html = await response.text(); - - assert(html, 'got some html'); - const doc = new DOMParser().parseFromString(html, `text/html`); - if (doc) { - const div = doc.querySelector('#thing'); - assert(div, 'div exists'); - } - } catch (err) { - console.error(err); - } finally { - await stop(); - } - }, -}); diff --git a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts b/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts deleted file mode 100644 index 699ab0014..000000000 --- a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { loadFixture } from './test-utils.ts'; -import { assertEquals, assert, DOMParser } from './deps.ts'; - -Deno.env.set('SECRET_STUFF', 'secret'); - -Deno.test({ - ignore: true, - name: 'Edge Basics', - permissions: 'inherit', - async fn(t) { - const fixture = loadFixture('./fixtures/edge-basic/'); - await t.step('Run the build', async () => { - await fixture.runBuild(); - }); - await t.step('Should correctly render the response', async () => { - const { default: handler } = await import( - './fixtures/edge-basic/.netlify/edge-functions/entry.js' - ); - const response = await handler(new Request('http://example.com/')); - assertEquals(response.status, 200); - const html = await response.text(); - assert(html, 'got some html'); - - const doc = new DOMParser().parseFromString(html, `text/html`)!; - const div = doc.querySelector('#react'); - assert(div, 'div exists'); - - const envDiv = doc.querySelector('#env'); - assertEquals(envDiv?.innerText, 'secret'); - }); - - await t.step('Clean up', async () => { - await fixture.cleanup(); - }); - }, -}); diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/astro.config.mjs deleted file mode 100644 index cd758352b..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/astro.config.mjs +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'astro/config'; -import { netlifyEdgeFunctions } from '@astrojs/netlify'; - -export default defineConfig({ - adapter: netlifyEdgeFunctions({ - dist: new URL('./dist/', import.meta.url), - }), - output: 'server', -}) diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/package.json b/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/package.json deleted file mode 100644 index 201a243d0..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@test/netlify-edge-astro-dynimport", - "version": "0.0.0", - "private": true, - "dependencies": { - "astro": "workspace:*", - "@astrojs/netlify": "workspace:*" - } -} diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/prod.js b/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/prod.js deleted file mode 100644 index 3e7d6e64d..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/prod.js +++ /dev/null @@ -1,11 +0,0 @@ -import handler from './.netlify/edge-functions/entry.js'; -import { Server } from 'https://deno.land/std@0.132.0/http/server.ts'; - -const _server = new Server({ - port: 8085, - hostname: '0.0.0.0', - handler, -}); - -_server.listenAndServe(); -console.error(`Server running on port 8085`); diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/components/Thing.astro b/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/components/Thing.astro deleted file mode 100644 index 8d8ef929a..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/components/Thing.astro +++ /dev/null @@ -1,4 +0,0 @@ ---- - ---- -<div id="thing">testing</div> diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/pages/index.astro b/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/pages/index.astro deleted file mode 100644 index 852cb6201..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/dynimport/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -const { default: Thing } = await import('../components/Thing.astro'); ---- -<html> - <head> - <title>testing</title> - </head> - <body> - <Thing /> - </body> -</html> diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs deleted file mode 100644 index ac15ad4e9..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'astro/config'; -import { netlifyEdgeFunctions } from '@astrojs/netlify'; - -// test env var -process.env.SECRET_STUFF = 'secret' - -export default defineConfig({ - adapter: netlifyEdgeFunctions({ - dist: new URL('./dist/', import.meta.url), - }), - output: 'server', -}) diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json deleted file mode 100644 index 16ff30088..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "@test/netlify-edge-astro-basic", - "version": "0.0.0", - "private": true, - "dependencies": { - "astro": "workspace:*", - "@astrojs/react": "workspace:*", - "@astrojs/netlify": "workspace:*" - } -} diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro deleted file mode 100644 index a480cf46c..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ -<html> -<head><title>Testing</title></head> -<body> - <h1>Test page</h1> - <h2>Links</h2> - <ul> - <li><a href="/two/">Two</a></li> - </ul> - <div id="env">{import.meta.env.SECRET_STUFF}</div> -</body> -</html> diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/three.md b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/three.md deleted file mode 100644 index b588a6adc..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/three.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Hey there! ---- - -# {frontmatter.title}! - -It's a markdown file! diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/two.astro b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/two.astro deleted file mode 100644 index b5a031be3..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/two.astro +++ /dev/null @@ -1,6 +0,0 @@ -<html> -<head><title>Page Two</title></head> -<body> - <h1>Page two</h1> -</body> -</html> 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 deleted file mode 100644 index d049599e5..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/astro.config.mjs +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from "astro/config"; -import { netlifyEdgeFunctions } from "@astrojs/netlify"; - -const isHybridMode = process.env.PRERENDER === "false"; - -/** @type {import('astro').AstroConfig} */ -const partialConfig = { - output: isHybridMode ? "hybrid" : "server", -}; - -export default defineConfig({ - adapter: netlifyEdgeFunctions({ - dist: new URL("./dist/", import.meta.url), - }), - ...partialConfig, -}); diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/package.json b/packages/integrations/netlify/test/edge-functions/fixtures/prerender/package.json deleted file mode 100644 index a080cc213..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@test/astro-netlify-prerender", - "version": "0.0.0", - "private": true, - "dependencies": { - "@astrojs/netlify": "workspace:*", - "astro": "workspace:*" - } -} diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/src/pages/index.astro b/packages/integrations/netlify/test/edge-functions/fixtures/prerender/src/pages/index.astro deleted file mode 100644 index b6b833e53..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/prerender/src/pages/index.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- -export const prerender = import.meta.env.PRERENDER; ---- - -<html> - <head> - <title>testing</title> - </head> - <body> - <h1>testing</h1> - </body> -</html> diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/astro.config.mjs deleted file mode 100644 index cd758352b..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/astro.config.mjs +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from 'astro/config'; -import { netlifyEdgeFunctions } from '@astrojs/netlify'; - -export default defineConfig({ - adapter: netlifyEdgeFunctions({ - dist: new URL('./dist/', import.meta.url), - }), - output: 'server', -}) diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/package.json b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/package.json deleted file mode 100644 index 6e548c151..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@test/netlify-edge-root-dynamic", - "version": "0.0.0", - "private": true, - "dependencies": { - "astro": "workspace:*", - "@astrojs/netlify": "workspace:*" - } -} diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/public/styles.css b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/public/styles.css deleted file mode 100644 index eedeb9d0f..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/public/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: blue; -} diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/src/pages/[...all].astro b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/src/pages/[...all].astro deleted file mode 100644 index b61f6fc44..000000000 --- a/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/src/pages/[...all].astro +++ /dev/null @@ -1,9 +0,0 @@ -<html> -<head> - <title>Testing</title> - <link rel="stylesheet" href="/styles.css"> -</head> -<body> - <h1>Testing</h1> -</body> -</html> diff --git a/packages/integrations/netlify/test/edge-functions/prerender.test.ts b/packages/integrations/netlify/test/edge-functions/prerender.test.ts deleted file mode 100644 index 2c066b9b8..000000000 --- a/packages/integrations/netlify/test/edge-functions/prerender.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { loadFixture } from './test-utils.ts'; -import { assertEquals, assertExists, cheerio, fs } from './deps.ts'; - -Deno.test({ - name: 'Prerender', - permissions: 'inherit', - async fn(t) { - const environmentVariables = { - PRERENDER: 'true', - }; - const { runBuild, cleanup } = loadFixture('./fixtures/prerender/', environmentVariables); - - await t.step('Run the build', async () => { - await runBuild(); - }); - - await t.step('Handler can process requests to non-existing routes', async () => { - const { default: handler } = await import( - './fixtures/prerender/.netlify/edge-functions/entry.js' - ); - assertExists(handler); - const response = await handler(new Request('http://example.com/index.html')); - assertEquals(response.status, 404, "No response because this route doesn't exist"); - }); - - await t.step('Prerendered route exists', async () => { - let content: string | null = null; - try { - const path = new URL('./fixtures/prerender/dist/index.html', import.meta.url); - content = Deno.readTextFileSync(path); - } catch (e) {} - assertExists(content); - const $ = cheerio.load(content); - assertEquals($('h1').text(), 'testing'); - }); - - Deno.env.delete('PRERENDER'); - await cleanup(); - }, -}); - -Deno.test({ - name: 'Hybrid rendering', - permissions: 'inherit', - async fn(t) { - const environmentVariables = { - PRERENDER: 'false', - }; - const fixture = loadFixture('./fixtures/prerender/', environmentVariables); - await t.step('Run the build', async () => { - await fixture.runBuild(); - }); - - const stop = await fixture.runApp('./fixtures/prerender/prod.js'); - await t.step('Can fetch server route', async () => { - const { default: handler } = await import( - './fixtures/prerender/.netlify/edge-functions/entry.js' - ); - const response = await handler(new Request('http://example.com/')); - assertEquals(response.status, 200); - - const html = await response.text(); - const $ = cheerio.load(html); - assertEquals($('h1').text(), 'testing'); - }); - stop(); - - await t.step('Handler can process requests to non-existing routes', async () => { - const { default: handler } = await import( - './fixtures/prerender/.netlify/edge-functions/entry.js' - ); - const response = await handler(new Request('http://example.com/index.html')); - assertEquals(response.status, 404, "No response because this route doesn't exist"); - }); - - await t.step('Has no prerendered route', async () => { - let prerenderedRouteExists = false; - try { - const path = new URL('./fixtures/prerender/dist/index.html', import.meta.url); - prerenderedRouteExists = fs.existsSync(path); - } catch (e) {} - assertEquals(prerenderedRouteExists, false); - }); - await fixture.cleanup(); - }, -}); diff --git a/packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts b/packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts deleted file mode 100644 index 3fc2012c3..000000000 --- a/packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { loadFixture } from './test-utils.ts'; -import { assertEquals } from './deps.ts'; - -Deno.test({ - // TODO: debug why build cannot be found in "await import" - ignore: true, - name: 'Assets are preferred over HTML routes', - async fn() { - const fixture = loadFixture('./fixtures/root-dynamic/'); - await fixture.runBuild(); - - const { default: handler } = await import( - './fixtures/root-dynamic/.netlify/edge-functions/entry.js' - ); - const response = await handler(new Request('http://example.com/styles.css')); - assertEquals(response, undefined, 'No response because this is an asset'); - await fixture.cleanup(); - }, -}); diff --git a/packages/integrations/netlify/test/edge-functions/test-utils.ts b/packages/integrations/netlify/test/edge-functions/test-utils.ts deleted file mode 100644 index ed6e4c20c..000000000 --- a/packages/integrations/netlify/test/edge-functions/test-utils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { fromFileUrl, readableStreamFromReader } from './deps.ts'; -const dir = new URL('./', import.meta.url); - -export function loadFixture(fixturePath: string, envionmentVariables?: Record<string, string>) { - async function runBuild() { - const proc = Deno.run({ - cmd: ['node', '../../../../../../astro/astro.js', 'build'], - env: envionmentVariables, - cwd: fromFileUrl(new URL(fixturePath, dir)), - }); - await proc.status(); - proc.close(); - } - - async function runApp(entryPath: string) { - const entryUrl = new URL(entryPath, dir); - let proc = Deno.run({ - cmd: ['deno', 'run', '--allow-env', '--allow-net', fromFileUrl(entryUrl)], - env: envionmentVariables, - //cwd: fromFileUrl(entryUrl), - stderr: 'piped', - }); - const stderr = readableStreamFromReader(proc.stderr); - const dec = new TextDecoder(); - for await (let bytes of stderr) { - let msg = dec.decode(bytes); - if (msg.includes(`Server running`)) { - break; - } - } - return () => proc.close(); - } - - async function cleanup() { - const netlifyPath = new URL('.netlify', new URL(fixturePath, dir)); - const distPath = new URL('dist', new URL(fixturePath, dir)); - - // remove the netlify folder - await Deno.remove(netlifyPath, { recursive: true }); - - // remove the dist folder - await Deno.remove(distPath, { recursive: true }); - } - - return { - runApp, - runBuild, - cleanup, - }; -} diff --git a/packages/integrations/netlify/test/functions/edge-middleware.test.js b/packages/integrations/netlify/test/functions/edge-middleware.test.js index 219fd1ced..a83720a4d 100644 --- a/packages/integrations/netlify/test/functions/edge-middleware.test.js +++ b/packages/integrations/netlify/test/functions/edge-middleware.test.js @@ -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()], diff --git a/packages/integrations/netlify/test/functions/prerender.test.js b/packages/integrations/netlify/test/functions/prerender.test.js index a571dd76e..05a2c3971 100644 --- a/packages/integrations/netlify/test/functions/prerender.test.js +++ b/packages/integrations/netlify/test/functions/prerender.test.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; +import { after } from 'node:test'; import netlifyAdapter from '../../dist/index.js'; import { loadFixture, testIntegration } from './test-utils.js'; -import { after } from 'node:test'; describe('Mixed Prerendering with SSR', () => { /** @type {import('./test-utils').Fixture} */ @@ -27,9 +27,9 @@ describe('Mixed Prerendering with SSR', () => { it('Wildcard 404 is sorted last', async () => { const redir = await fixture.readFile('/_redirects'); - const baseRouteIndex = redir.indexOf('/ /.netlify/functions/entry 200'); - const oneRouteIndex = redir.indexOf('/one /one/index.html 200'); - const fourOhFourWildCardIndex = redir.indexOf('/* /.netlify/functions/entry 404'); + const baseRouteIndex = redir.indexOf('/ /.netlify/functions/entry 200'); + const oneRouteIndex = redir.indexOf('/one /one/index.html 200'); + const fourOhFourWildCardIndex = redir.indexOf('/* /.netlify/functions/entry 404'); expect(oneRouteIndex).to.not.be.equal(-1); expect(fourOhFourWildCardIndex).to.be.greaterThan(baseRouteIndex); @@ -61,12 +61,15 @@ describe('Mixed Hybrid rendering with SSR', () => { it('outputs a correct redirect file', async () => { const redir = await fixture.readFile('/_redirects'); - const baseRouteIndex = redir.indexOf('/one /.netlify/functions/entry 200'); - const rootRouteIndex = redir.indexOf('/ /index.html 200'); - const fourOhFourIndex = redir.indexOf('/404 /404.html 200'); + console.log(redir); + const baseRouteIndex = redir.indexOf('/one /.netlify/functions/entry 200'); + const rootRouteIndex = redir.indexOf('/ /index.html 200'); + const fourOhFourIndex = redir.indexOf('/404 /404.html 200'); + const imageEndpoint = redir.indexOf('/_image /.netlify/functions/entry 200'); expect(rootRouteIndex).to.not.be.equal(-1); expect(baseRouteIndex).to.not.be.equal(-1); expect(fourOhFourIndex).to.not.be.equal(-1); + expect(imageEndpoint).to.not.be.equal(-1); }); }); diff --git a/packages/integrations/netlify/test/functions/redirects.test.js b/packages/integrations/netlify/test/functions/redirects.test.js index 1995718f8..8e3d46a68 100644 --- a/packages/integrations/netlify/test/functions/redirects.test.js +++ b/packages/integrations/netlify/test/functions/redirects.test.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { loadFixture, testIntegration } from './test-utils.js'; import netlifyAdapter from '../../dist/index.js'; +import { loadFixture, testIntegration } from './test-utils.js'; describe('SSG - Redirects', () => { /** @type {import('../../../astro/test/test-utils').Fixture} */ @@ -25,6 +25,7 @@ describe('SSG - Redirects', () => { it('Creates a redirects file', async () => { let redirects = await fixture.readFile('/_redirects'); let parts = redirects.split(/\s+/); + console.log(parts); expect(parts).to.deep.equal([ '/other', '/', @@ -38,6 +39,11 @@ describe('SSG - Redirects', () => { '/.netlify/functions/entry', '200', + // Image endpoint + '/_image', + '/.netlify/functions/entry', + '200', + // A real route '/team/articles/*', '/.netlify/functions/entry', diff --git a/packages/integrations/netlify/test/functions/redirects.test.js.snap b/packages/integrations/netlify/test/functions/redirects.test.js.snap index 322b4ee85..54095f052 100644 --- a/packages/integrations/netlify/test/functions/redirects.test.js.snap +++ b/packages/integrations/netlify/test/functions/redirects.test.js.snap @@ -4,5 +4,6 @@ exports[`SSG - Redirects Creates a redirects file 1`] = ` "/other / 301 /nope /.netlify/functions/entry 200 / /.netlify/functions/entry 200 +/_image /.netlify/functions/entry 200 /team/articles/* /.netlify/functions/entry 200" `; diff --git a/packages/integrations/netlify/test/functions/split-support.test.js b/packages/integrations/netlify/test/functions/split-support.test.js index 217b3c0d3..90427523c 100644 --- a/packages/integrations/netlify/test/functions/split-support.test.js +++ b/packages/integrations/netlify/test/functions/split-support.test.js @@ -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(); }); @@ -32,7 +30,7 @@ describe('Split support', () => { it('outputs a correct redirect file', async () => { const redir = await fixture.readFile('/_redirects'); const lines = redir.split(/[\r\n]+/); - expect(lines.length).to.equal(2); + expect(lines.length).to.equal(3); expect(lines[0].includes('/blog')).to.be.true; expect(lines[0].includes('blog.astro')).to.be.true; @@ -45,15 +43,17 @@ describe('Split support', () => { describe('Should create multiple functions', () => { it('and hit 200', async () => { if (_entryPoints) { - for (const [, filePath] of _entryPoints) { - const { handler } = await import(filePath.toString()); - const resp = await handler({ - httpMethod: 'POST', - headers: {}, - rawUrl: 'http://example.com/', - body: '{}', - }); - expect(resp.statusCode).to.equal(200); + for (const [routeData, filePath] of _entryPoints) { + if (routeData.route !== '/_image') { + const { handler } = await import(filePath.toString()); + const resp = await handler({ + httpMethod: 'GET', + headers: {}, + rawUrl: `http://example.com${routeData.route}`, + body: '{}', + }); + expect(resp.statusCode).to.equal(200); + } } } else { expect(false).to.be.true; diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs b/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs index 48b1d4db1..464c03a6c 100644 --- a/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs @@ -5,7 +5,4 @@ import { defineConfig } from 'astro/config'; export default defineConfig({ output: 'server', adapter: netlify(), - experimental: { - assets: true, - }, }); diff --git a/packages/integrations/netlify/tsconfig.json b/packages/integrations/netlify/tsconfig.json index 4442d4c36..66b0102c7 100644 --- a/packages/integrations/netlify/tsconfig.json +++ b/packages/integrations/netlify/tsconfig.json @@ -5,7 +5,7 @@ "allowJs": true, "module": "ES2022", "outDir": "./dist", - "target": "ES2021", + "target": "ES2022", "typeRoots": ["node_modules/@types", "node_modules/@netlify"], "allowImportingTsExtensions": true } |