aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2022-04-22 10:03:25 -0400
committerGravatar GitHub <noreply@github.com> 2022-04-22 10:03:25 -0400
commit19667c45f318ec13cdc2b51016f3fa3487b2a32d (patch)
tree7092f20c31d95fd74c412d188cbc02eab67402de
parente632c090494b70d563eebc9f961e76cd9c28551b (diff)
downloadastro-19667c45f318ec13cdc2b51016f3fa3487b2a32d.tar.gz
astro-19667c45f318ec13cdc2b51016f3fa3487b2a32d.tar.zst
astro-19667c45f318ec13cdc2b51016f3fa3487b2a32d.zip
Netlify Edge: forward requests for static assets (#3170)
* Netlify Edge: forward requests for static assets * Adds a changeset * Don't run edge tests, yet
-rw-r--r--.changeset/smooth-tables-tan.md6
-rw-r--r--packages/astro/src/core/app/common.ts3
-rw-r--r--packages/astro/src/core/app/types.ts4
-rw-r--r--packages/astro/src/core/build/static-build.ts2
-rw-r--r--packages/astro/src/core/build/vite-plugin-ssr.ts19
-rw-r--r--packages/integrations/netlify/package.json1
-rw-r--r--packages/integrations/netlify/src/netlify-edge-functions.ts9
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/astro.config.mjs11
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/package.json9
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/public/styles.css3
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/src/pages/[...all].astro9
-rw-r--r--packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts16
-rw-r--r--packages/integrations/netlify/tsconfig.json6
-rw-r--r--pnpm-lock.yaml16
14 files changed, 106 insertions, 8 deletions
diff --git a/.changeset/smooth-tables-tan.md b/.changeset/smooth-tables-tan.md
new file mode 100644
index 000000000..fc9a1eb8a
--- /dev/null
+++ b/.changeset/smooth-tables-tan.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/netlify': patch
+---
+
+Netlify Edge: Forward requests for static assets
diff --git a/packages/astro/src/core/app/common.ts b/packages/astro/src/core/app/common.ts
index 5ef0bce64..c8b27c35a 100644
--- a/packages/astro/src/core/app/common.ts
+++ b/packages/astro/src/core/app/common.ts
@@ -13,8 +13,11 @@ export function deserializeManifest(serializedManifest: SerializedSSRManifest):
route.routeData = deserializeRouteData(serializedRoute.routeData);
}
+ const assets = new Set<string>(serializedManifest.assets);
+
return {
...serializedManifest,
+ assets,
routes,
};
}
diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts
index 95ccfeba1..aa4481141 100644
--- a/packages/astro/src/core/app/types.ts
+++ b/packages/astro/src/core/app/types.ts
@@ -26,10 +26,12 @@ export interface SSRManifest {
pageMap: Map<ComponentPath, ComponentInstance>;
renderers: SSRLoadedRenderer[];
entryModules: Record<string, string>;
+ assets: Set<string>;
}
-export type SerializedSSRManifest = Omit<SSRManifest, 'routes'> & {
+export type SerializedSSRManifest = Omit<SSRManifest, 'routes' | 'assets'> & {
routes: SerializedRouteInfo[];
+ assets: string[];
};
export type AdapterCreateExports<T = any> = (
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 0288f8bc9..b06f3c4f1 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -10,7 +10,7 @@ import { fileURLToPath } from 'url';
import * as vite from 'vite';
import { createBuildInternals } from '../../core/build/internal.js';
import { info } from '../logger/core.js';
-import { appendForwardSlash, prependForwardSlash } from '../../core/path.js';
+import { prependForwardSlash } from '../../core/path.js';
import { emptyDir, removeDir } from '../../core/util.js';
import { rollupPluginAstroBuildCSS } from '../../vite-plugin-build-css/index.js';
import { vitePluginHoistedScripts } from './vite-plugin-hoisted-scripts.js';
diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts
index aa07fe3a8..656d01d81 100644
--- a/packages/astro/src/core/build/vite-plugin-ssr.ts
+++ b/packages/astro/src/core/build/vite-plugin-ssr.ts
@@ -7,6 +7,8 @@ import type { SerializedRouteInfo, SerializedSSRManifest } from '../app/types';
import { serializeRouteData } from '../routing/index.js';
import { eachPageData } from './internal.js';
import { addRollupInput } from './add-rollup-input.js';
+import { fileURLToPath } from 'url';
+import glob from 'fast-glob';
import { virtualModuleId as pagesVirtualModuleId } from './vite-plugin-pages.js';
import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
@@ -65,11 +67,19 @@ if(_start in adapter) {
}
return void 0;
},
- generateBundle(_opts, bundle) {
- const manifest = buildManifest(buildOpts, internals);
+ async generateBundle(_opts, bundle) {
+ const staticFiles = await glob('**/*', {
+ cwd: fileURLToPath(buildOpts.buildConfig.client),
+ });
+
+ const manifest = buildManifest(buildOpts, internals, staticFiles);
+
+
for (const [_chunkName, chunk] of Object.entries(bundle)) {
- if (chunk.type === 'asset') continue;
+ if (chunk.type === 'asset') {
+ continue;
+ };
if (chunk.modules[resolvedVirtualModuleId]) {
const code = chunk.code;
chunk.code = code.replace(replaceExp, () => {
@@ -81,7 +91,7 @@ if(_start in adapter) {
};
}
-function buildManifest(opts: StaticBuildOptions, internals: BuildInternals): SerializedSSRManifest {
+function buildManifest(opts: StaticBuildOptions, internals: BuildInternals, staticFiles: string[]): SerializedSSRManifest {
const { astroConfig } = opts;
const routes: SerializedRouteInfo[] = [];
@@ -112,6 +122,7 @@ function buildManifest(opts: StaticBuildOptions, internals: BuildInternals): Ser
pageMap: null as any,
renderers: [],
entryModules,
+ assets: staticFiles.map(s => '/' + s)
};
return ssrManifest;
diff --git a/packages/integrations/netlify/package.json b/packages/integrations/netlify/package.json
index 3d4bde0c3..d4a452f6a 100644
--- a/packages/integrations/netlify/package.json
+++ b/packages/integrations/netlify/package.json
@@ -33,6 +33,7 @@
"@astrojs/webapi": "^0.11.1"
},
"devDependencies": {
+ "@netlify/edge-handler-types": "^0.34.1",
"@netlify/functions": "^1.0.0",
"astro": "workspace:*",
"astro-scripts": "workspace:*"
diff --git a/packages/integrations/netlify/src/netlify-edge-functions.ts b/packages/integrations/netlify/src/netlify-edge-functions.ts
index 1bb8e2c3a..040228241 100644
--- a/packages/integrations/netlify/src/netlify-edge-functions.ts
+++ b/packages/integrations/netlify/src/netlify-edge-functions.ts
@@ -5,7 +5,14 @@ import { App } from 'astro/app';
export function createExports(manifest: SSRManifest) {
const app = new App(manifest);
- const handler = async (request: Request): Promise<Response> => {
+ const handler = async (request: Request): 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;
+ }
if (app.match(request)) {
return app.render(request);
}
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
new file mode 100644
index 000000000..c55135e43
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/astro.config.mjs
@@ -0,0 +1,11 @@
+import { defineConfig } from 'astro/config';
+import { netlifyEdgeFunctions } from '@astrojs/netlify';
+
+export default defineConfig({
+ adapter: netlifyEdgeFunctions({
+ dist: new URL('./dist/', import.meta.url),
+ }),
+ experimental: {
+ ssr: true
+ }
+})
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
new file mode 100644
index 000000000..6e548c151
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/package.json
@@ -0,0 +1,9 @@
+{
+ "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
new file mode 100644
index 000000000..eedeb9d0f
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/public/styles.css
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 000000000..b61f6fc44
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic/src/pages/[...all].astro
@@ -0,0 +1,9 @@
+<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/root-dynamic.test.ts b/packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts
new file mode 100644
index 000000000..c6504e188
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/root-dynamic.test.ts
@@ -0,0 +1,16 @@
+// @ts-ignore
+import { runBuild } from './test-utils.ts';
+// @ts-ignore
+import { assertEquals, assert, DOMParser } from './deps.ts';
+
+// @ts-ignore
+Deno.test({
+ name: 'Assets are preferred over HTML routes',
+ async fn() {
+ let close = await runBuild('./fixtures/root-dynamic/');
+ const { default: handler } = await import('./fixtures/root-dynamic/dist/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 close();
+ },
+});
diff --git a/packages/integrations/netlify/tsconfig.json b/packages/integrations/netlify/tsconfig.json
index 44baf375c..b057b6880 100644
--- a/packages/integrations/netlify/tsconfig.json
+++ b/packages/integrations/netlify/tsconfig.json
@@ -5,6 +5,10 @@
"allowJs": true,
"module": "ES2020",
"outDir": "./dist",
- "target": "ES2020"
+ "target": "ES2020",
+ "typeRoots": [
+ "node_modules/@types",
+ "node_modules/@netlify"
+ ]
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2b5c2f51c..0c9fc3f8b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1267,12 +1267,14 @@ importers:
packages/integrations/netlify:
specifiers:
'@astrojs/webapi': ^0.11.1
+ '@netlify/edge-handler-types': ^0.34.1
'@netlify/functions': ^1.0.0
astro: workspace:*
astro-scripts: workspace:*
dependencies:
'@astrojs/webapi': link:../../webapi
devDependencies:
+ '@netlify/edge-handler-types': 0.34.1
'@netlify/functions': 1.0.0
astro: link:../../astro
astro-scripts: link:../../../scripts
@@ -1287,6 +1289,14 @@ importers:
'@astrojs/react': link:../../../../../react
astro: link:../../../../../../astro
+ packages/integrations/netlify/test/edge-functions/fixtures/root-dynamic:
+ specifiers:
+ '@astrojs/netlify': workspace:*
+ astro: workspace:*
+ dependencies:
+ '@astrojs/netlify': link:../../../..
+ astro: link:../../../../../../astro
+
packages/integrations/node:
specifiers:
'@astrojs/webapi': ^0.11.1
@@ -3485,6 +3495,12 @@ packages:
vue: 3.2.33
dev: false
+ /@netlify/edge-handler-types/0.34.1:
+ resolution: {integrity: sha512-YTwn8cw89M4lRTmoUhl9s8ljSGMDt7FOIsxsrx7YrRz/RZlbh4Yuh4RU13DDafDRBEVuRbjGo93cnN621ZfBjA==}
+ dependencies:
+ web-streams-polyfill: 3.2.1
+ dev: true
+
/@netlify/functions/1.0.0:
resolution: {integrity: sha512-7fnJv3vr8uyyyOYPChwoec6MjzsCw1CoRUO2DhQ1BD6bOyJRlD4DUaOOGlMILB2LCT8P24p5LexEGx8AJb7xdA==}
engines: {node: '>=8.3.0'}