From 9855db676e61ad616c64382adeaa8c74de05f7e1 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Thu, 26 Jan 2023 12:43:39 -0500 Subject: [PATCH] Support for prerendering in the Cloudflare integration (#5993) * Cloudflare prerender branch * Add prerendered routes to Cloudflare routes.json * Adding changeset * Prevent process proxy from running during prerender phase --- .changeset/good-avocados-repeat.md | 7 +++++++ packages/integrations/cloudflare/src/index.ts | 16 ++++++++++++++-- .../cloudflare/src/server.advanced.ts | 6 ++++-- .../cloudflare/src/server.directory.ts | 6 ++++-- packages/integrations/cloudflare/src/util.ts | 2 ++ .../test/fixtures/prerender/astro.config.mjs | 7 +++++++ .../test/fixtures/prerender/package.json | 9 +++++++++ .../fixtures/prerender/src/pages/index.astro | 8 ++++++++ .../fixtures/prerender/src/pages/one.astro | 11 +++++++++++ .../cloudflare/test/prerender.test.js | 19 +++++++++++++++++++ pnpm-lock.yaml | 8 ++++++++ 11 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 .changeset/good-avocados-repeat.md create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender/astro.config.mjs create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender/package.json create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender/src/pages/index.astro create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender/src/pages/one.astro create mode 100644 packages/integrations/cloudflare/test/prerender.test.js diff --git a/.changeset/good-avocados-repeat.md b/.changeset/good-avocados-repeat.md new file mode 100644 index 000000000000..3ff9846de7a3 --- /dev/null +++ b/.changeset/good-avocados-repeat.md @@ -0,0 +1,7 @@ +--- +'@astrojs/cloudflare': patch +--- + +Support for prerendering in the Cloudflare integration + +This fixes prerendering in the Cloudflare adapter. Now any prerendered routes are added to the `_routes.json` config so that the worker script is skipped for those routes. diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts index 1df284fbbb19..3a077c4d6188 100644 --- a/packages/integrations/cloudflare/src/index.ts +++ b/packages/integrations/cloudflare/src/index.ts @@ -49,7 +49,7 @@ export default function createIntegration(args?: Options): AstroIntegration { build: { client: new URL(`.${config.base}`, config.outDir), server: new URL(`.${SERVER_BUILD_FOLDER}`, config.outDir), - serverEntry: '_worker.js', + serverEntry: '_worker.mjs', }, }); }, @@ -88,10 +88,11 @@ export default function createIntegration(args?: Options): AstroIntegration { vite.ssr.target = vite.ssr.target || 'webworker'; } }, - 'astro:build:done': async () => { + 'astro:build:done': async ({ pages }) => { const entryPath = fileURLToPath(new URL(_buildConfig.serverEntry, _buildConfig.server)), entryUrl = new URL(_buildConfig.serverEntry, _config.outDir), buildPath = fileURLToPath(entryUrl); + await esbuild.build({ target: 'es2020', platform: 'browser', @@ -106,6 +107,9 @@ export default function createIntegration(args?: Options): AstroIntegration { }, }); + // Rename to worker.js + await fs.promises.rename(buildPath, buildPath.replace(/\.mjs$/, '.js')); + // throw the server folder in the bin const serverUrl = new URL(_buildConfig.server); await fs.promises.rm(serverUrl, { recursive: true, force: true }); @@ -143,6 +147,10 @@ export default function createIntegration(args?: Options): AstroIntegration { .filter((file: string) => cloudflareSpecialFiles.indexOf(file) < 0) .map((file: string) => `/${file}`); + for(let page of pages) { + staticPathList.push(prependForwardSlash(page.pathname)); + } + const redirectsExists = await fs.promises .stat(new URL('./_redirects', _config.outDir)) .then((stat) => stat.isFile()) @@ -202,3 +210,7 @@ export default function createIntegration(args?: Options): AstroIntegration { }, }; } + +function prependForwardSlash(path: string) { + return path[0] === '/' ? path : '/' + path; +} diff --git a/packages/integrations/cloudflare/src/server.advanced.ts b/packages/integrations/cloudflare/src/server.advanced.ts index b57a480f945e..3d6b4fbcd20b 100644 --- a/packages/integrations/cloudflare/src/server.advanced.ts +++ b/packages/integrations/cloudflare/src/server.advanced.ts @@ -1,8 +1,10 @@ import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; -import { getProcessEnvProxy } from './util.js'; +import { getProcessEnvProxy, isNode } from './util.js'; -process.env = getProcessEnvProxy(); +if(!isNode) { + process.env = getProcessEnvProxy(); +} type Env = { ASSETS: { fetch: (req: Request) => Promise }; diff --git a/packages/integrations/cloudflare/src/server.directory.ts b/packages/integrations/cloudflare/src/server.directory.ts index 8f1b3b8ab4ae..17a35f15a0f6 100644 --- a/packages/integrations/cloudflare/src/server.directory.ts +++ b/packages/integrations/cloudflare/src/server.directory.ts @@ -1,8 +1,10 @@ import type { SSRManifest } from 'astro'; import { App } from 'astro/app'; -import { getProcessEnvProxy } from './util.js'; +import { getProcessEnvProxy, isNode } from './util.js'; -process.env = getProcessEnvProxy(); +if(!isNode) { + process.env = getProcessEnvProxy(); +} export function createExports(manifest: SSRManifest) { const app = new App(manifest); diff --git a/packages/integrations/cloudflare/src/util.ts b/packages/integrations/cloudflare/src/util.ts index a44780863f91..96927e57a9a3 100644 --- a/packages/integrations/cloudflare/src/util.ts +++ b/packages/integrations/cloudflare/src/util.ts @@ -1,3 +1,5 @@ +export const isNode = typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]'; + export function getProcessEnvProxy() { return new Proxy( {}, diff --git a/packages/integrations/cloudflare/test/fixtures/prerender/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/prerender/astro.config.mjs new file mode 100644 index 000000000000..bf47a0a330b4 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import cloudflare from '@astrojs/cloudflare'; + +export default defineConfig({ + adapter: cloudflare(), + output: 'server', +}); diff --git a/packages/integrations/cloudflare/test/fixtures/prerender/package.json b/packages/integrations/cloudflare/test/fixtures/prerender/package.json new file mode 100644 index 000000000000..3b2c5fef5d5c --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-cloudflare-prerender", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/cloudflare": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/index.astro new file mode 100644 index 000000000000..dfd71c3de6db --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/index.astro @@ -0,0 +1,8 @@ + + + Testing + + +

Testing

+ + diff --git a/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/one.astro b/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/one.astro new file mode 100644 index 000000000000..30386a625ab6 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender/src/pages/one.astro @@ -0,0 +1,11 @@ +--- +export const prerender = true; +--- + + + Testing + + +

Testing

+ + diff --git a/packages/integrations/cloudflare/test/prerender.test.js b/packages/integrations/cloudflare/test/prerender.test.js new file mode 100644 index 000000000000..a3ce50d08c96 --- /dev/null +++ b/packages/integrations/cloudflare/test/prerender.test.js @@ -0,0 +1,19 @@ +import { loadFixture } from './test-utils.js'; +import { expect } from 'chai'; + +describe('Prerendering', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/prerender/', + }); + await fixture.build(); + }); + + it('includes prerendered routes in the routes.json config', async () => { + const routes = JSON.parse(await fixture.readFile('/_routes.json')); + expect(routes.exclude).to.include('/one/'); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 454931ff2f55..c3b3920a8f24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2645,6 +2645,14 @@ importers: '@astrojs/cloudflare': link:../../.. astro: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/prerender: + specifiers: + '@astrojs/cloudflare': workspace:* + astro: workspace:* + dependencies: + '@astrojs/cloudflare': link:../../.. + astro: link:../../../../../astro + packages/integrations/deno: specifiers: astro: workspace:*