Remove the Nelify Edge adapter (#8029)
This commit is contained in:
parent
9cc4e48e6a
commit
2ee418e06a
28 changed files with 27 additions and 543 deletions
23
.changeset/tame-files-glow.md
Normal file
23
.changeset/tame-files-glow.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
'@astrojs/netlify': major
|
||||||
|
---
|
||||||
|
|
||||||
|
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.
|
|
@ -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
|
### Run middleware in Edge Functions
|
||||||
|
|
||||||
When deploying to Netlify Functions, you can choose to use an Edge Function to run your Astro middleware.
|
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}
|
```js ins={9}
|
||||||
// astro.config.mjs
|
// astro.config.mjs
|
||||||
|
@ -85,10 +68,9 @@ import netlify from '@astrojs/netlify/functions';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: 'server',
|
output: 'server',
|
||||||
adapter: netlify(),
|
adapter: netlify({
|
||||||
build: {
|
edgeMiddleware: true,
|
||||||
excludeMiddleware: true,
|
}),
|
||||||
},
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
export { netlifyEdgeFunctions } from './integration-edge-functions.js';
|
|
||||||
export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js';
|
export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js';
|
||||||
export { netlifyStatic } from './integration-static.js';
|
export { netlifyStatic } from './integration-static.js';
|
||||||
|
|
|
@ -1,98 +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'],
|
|
||||||
supportedAstroFeatures: {
|
|
||||||
hybridOutput: 'stable',
|
|
||||||
staticOutput: 'stable',
|
|
||||||
serverOutput: 'stable',
|
|
||||||
assets: {
|
|
||||||
supportKind: 'stable',
|
|
||||||
isSharpCompatible: false,
|
|
||||||
isSquooshCompatible: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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 };
|
|
|
@ -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 };
|
|
||||||
}
|
|
|
@ -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';
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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',
|
|
||||||
})
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/netlify-edge-astro-dynimport",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"astro": "workspace:*",
|
|
||||||
"@astrojs/netlify": "workspace:*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`);
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
<div id="thing">testing</div>
|
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
const { default: Thing } = await import('../components/Thing.astro');
|
|
||||||
---
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>testing</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<Thing />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -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',
|
|
||||||
})
|
|
|
@ -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:*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
title: Hey there!
|
|
||||||
---
|
|
||||||
|
|
||||||
# {frontmatter.title}!
|
|
||||||
|
|
||||||
It's a markdown file!
|
|
|
@ -1,6 +0,0 @@
|
||||||
<html>
|
|
||||||
<head><title>Page Two</title></head>
|
|
||||||
<body>
|
|
||||||
<h1>Page two</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -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,
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/astro-netlify-prerender",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@astrojs/netlify": "workspace:*",
|
|
||||||
"astro": "workspace:*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
export const prerender = import.meta.env.PRERENDER;
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>testing</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>testing</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -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',
|
|
||||||
})
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@test/netlify-edge-root-dynamic",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"astro": "workspace:*",
|
|
||||||
"@astrojs/netlify": "workspace:*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
body {
|
|
||||||
background: blue;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Testing</title>
|
|
||||||
<link rel="stylesheet" href="/styles.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Testing</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -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();
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in a new issue