summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Richard Cooke <hello@richardcooke.io> 2022-08-08 18:10:48 +0100
committerGravatar GitHub <noreply@github.com> 2022-08-08 12:10:48 -0500
commitf4c571bdb0bbcd0dfed68a484dfbfe274f8a5f45 (patch)
treedae136308dc7292608ccc3ee0e8d02303af0ff48
parent821074fcb5fee6f43d8dcd37e4dbec3c4ff504a4 (diff)
downloadastro-f4c571bdb0bbcd0dfed68a484dfbfe274f8a5f45.tar.gz
astro-f4c571bdb0bbcd0dfed68a484dfbfe274f8a5f45.tar.zst
astro-f4c571bdb0bbcd0dfed68a484dfbfe274f8a5f45.zip
feat: add support to `@astrojs/cloudflare` directory deploy mode (#3806)
Co-authored-by: Matthew Phillips <matthew@skypack.dev> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
-rw-r--r--.changeset/proud-moose-push.md5
-rw-r--r--packages/integrations/cloudflare/README.md23
-rw-r--r--packages/integrations/cloudflare/package.json3
-rw-r--r--packages/integrations/cloudflare/src/index.ts37
-rw-r--r--packages/integrations/cloudflare/src/server.advanced.ts (renamed from packages/integrations/cloudflare/src/server.ts)0
-rw-r--r--packages/integrations/cloudflare/src/server.directory.ts41
6 files changed, 98 insertions, 11 deletions
diff --git a/.changeset/proud-moose-push.md b/.changeset/proud-moose-push.md
new file mode 100644
index 000000000..43dd7ecd9
--- /dev/null
+++ b/.changeset/proud-moose-push.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/cloudflare': minor
+---
+
+add support for compiling functions to a functions directory rather than `_worker.js`
diff --git a/packages/integrations/cloudflare/README.md b/packages/integrations/cloudflare/README.md
index 3ab29b444..1bd65f5ae 100644
--- a/packages/integrations/cloudflare/README.md
+++ b/packages/integrations/cloudflare/README.md
@@ -14,6 +14,29 @@ export default defineConfig({
});
```
+## Options
+
+
+### Mode
+
+`mode: "advanced" | "directory"`
+
+default `"advanced"`
+
+Cloudflare Pages has 2 different modes for deploying functions, `advanced` mode which picks up the `_worker.js` in `dist`, or a directory mode where pages will compile the worker out of a functions folder in the project root.
+
+For most projects the adaptor default of `advanced` will be sufficiant, when in this mode the `dist` folder will contain your compiled project. However if you'd like to use [pages plugins](https://developers.cloudflare.com/pages/platform/functions/plugins/) such as [Sentry](https://developers.cloudflare.com/pages/platform/functions/plugins/sentry/) for example to enable logging, you'll need to use directory mode.
+
+In directory mode the adaptor will compile the client side part of you app the same way, but it will move the worker script into a `functions` folder in the project root. The adaptor will only ever place a `[[path]].js` in that folder, allowing you to add additional plugins and pages middlewhere which can be checked into version control .
+
+```ts
+// directory mode
+export default defineConfig({
+ adapter: cloudflare({ mode: "directory" }),
+});
+
+```
+
## Enabling Preview
In order for preview to work you must install `wrangler`
diff --git a/packages/integrations/cloudflare/package.json b/packages/integrations/cloudflare/package.json
index da192ec0c..0056cec12 100644
--- a/packages/integrations/cloudflare/package.json
+++ b/packages/integrations/cloudflare/package.json
@@ -18,7 +18,8 @@
"homepage": "https://docs.astro.build/en/guides/integrations-guide/cloudflare/",
"exports": {
".": "./dist/index.js",
- "./server.js": "./dist/server.js",
+ "./server.advanced.js": "./dist/server.advanced.js",
+ "./server.directory.js": "./dist/server.directory.js",
"./package.json": "./package.json"
},
"scripts": {
diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts
index 76904ed95..e207bdb44 100644
--- a/packages/integrations/cloudflare/src/index.ts
+++ b/packages/integrations/cloudflare/src/index.ts
@@ -3,12 +3,22 @@ import esbuild from 'esbuild';
import * as fs from 'fs';
import { fileURLToPath } from 'url';
-export function getAdapter(): AstroAdapter {
- return {
- name: '@astrojs/cloudflare',
- serverEntrypoint: '@astrojs/cloudflare/server.js',
- exports: ['default'],
- };
+type Options = {
+ mode: 'directory' | 'advanced';
+};
+
+export function getAdapter(isModeDirectory: boolean): AstroAdapter {
+ return isModeDirectory
+ ? {
+ name: '@astrojs/cloudflare',
+ serverEntrypoint: '@astrojs/cloudflare/server.directory.js',
+ exports: ['onRequest'],
+ }
+ : {
+ name: '@astrojs/cloudflare',
+ serverEntrypoint: '@astrojs/cloudflare/server.advanced.js',
+ exports: ['default'],
+ };
}
const SHIM = `globalThis.process = {
@@ -16,15 +26,16 @@ const SHIM = `globalThis.process = {
env: {},
};`;
-export default function createIntegration(): AstroIntegration {
+export default function createIntegration(args?: Options): AstroIntegration {
let _config: AstroConfig;
let _buildConfig: BuildConfig;
+ const isModeDirectory = args?.mode === 'directory';
return {
name: '@astrojs/cloudflare',
hooks: {
'astro:config:done': ({ setAdapter, config }) => {
- setAdapter(getAdapter());
+ setAdapter(getAdapter(isModeDirectory));
_config = config;
if (config.output === 'static') {
@@ -36,8 +47,8 @@ export default function createIntegration(): AstroIntegration {
},
'astro:build:start': ({ buildConfig }) => {
_buildConfig = buildConfig;
- buildConfig.serverEntry = '_worker.js';
buildConfig.client = new URL('./static/', _config.outDir);
+ buildConfig.serverEntry = '_worker.js';
buildConfig.server = new URL('./', _config.outDir);
},
'astro:build:setup': ({ vite, target }) => {
@@ -64,7 +75,6 @@ export default function createIntegration(): AstroIntegration {
'astro:build:done': async () => {
const entryUrl = new URL(_buildConfig.serverEntry, _buildConfig.server);
const pkg = fileURLToPath(entryUrl);
-
await esbuild.build({
target: 'es2020',
platform: 'browser',
@@ -82,6 +92,13 @@ export default function createIntegration(): AstroIntegration {
// throw the server folder in the bin
const chunksUrl = new URL('./chunks', _buildConfig.server);
await fs.promises.rm(chunksUrl, { recursive: true, force: true });
+
+ if (isModeDirectory) {
+ const functionsUrl = new URL(`file://${process.cwd()}/functions/`);
+ await fs.promises.mkdir(functionsUrl, { recursive: true });
+ const directoryUrl = new URL('[[path]].js', functionsUrl);
+ await fs.promises.rename(entryUrl, directoryUrl);
+ }
},
},
};
diff --git a/packages/integrations/cloudflare/src/server.ts b/packages/integrations/cloudflare/src/server.advanced.ts
index 7b88c7b1e..7b88c7b1e 100644
--- a/packages/integrations/cloudflare/src/server.ts
+++ b/packages/integrations/cloudflare/src/server.advanced.ts
diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts
new file mode 100644
index 000000000..abcc49b10
--- /dev/null
+++ b/packages/integrations/cloudflare/src/server.directory.ts
@@ -0,0 +1,41 @@
+import './shim.js';
+
+import type { SSRManifest } from 'astro';
+import { App } from 'astro/app';
+
+export function createExports(manifest: SSRManifest) {
+ const app = new App(manifest, false)
+
+ const onRequest = async ({
+ request,
+ next,
+ }: {
+ request: Request;
+ next: (request: Request) => void;
+ }) => {
+ const { origin, pathname } = new URL(request.url);
+
+ // static assets
+ if (manifest.assets.has(pathname)) {
+ const assetRequest = new Request(`${origin}/static${pathname}`, request);
+ return next(assetRequest);
+ }
+
+ let routeData = app.match(request, { matchNotFound: true });
+ if (routeData) {
+ Reflect.set(
+ request,
+ Symbol.for('astro.clientAddress'),
+ request.headers.get('cf-connecting-ip')
+ );
+ return app.render(request, routeData);
+ }
+
+ return new Response(null, {
+ status: 404,
+ statusText: 'Not found',
+ });
+ };
+
+ return { onRequest };
+}