Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export async function createVite(
exclude: ['astro', 'node-fetch'],
},
plugins: [
serializedManifestPlugin({ settings, command }),
serializedManifestPlugin({ settings, command, sync }),
vitePluginRenderers({ settings }),
await astroPluginRoutes({ routesList, settings, logger, fsMod: fs }),
astroVirtualManifestPlugin(),
Expand Down
7 changes: 1 addition & 6 deletions packages/astro/src/entrypoints/prerender.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { server as actions } from 'virtual:astro:actions/entrypoint';
import { manifest } from 'virtual:astro:manifest';
import { BuildApp } from '../core/build/app.js';

const app = new BuildApp(manifest);
const { renderers } = manifest;

// Export middleware lazy-loaded
const middleware = () => import('virtual:astro:middleware');

export { app, manifest, renderers, middleware, actions };
export { app, manifest };
4 changes: 3 additions & 1 deletion packages/astro/src/manifest/serialized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ export const SERIALIZED_MANIFEST_RESOLVED_ID = '\0' + SERIALIZED_MANIFEST_ID;
export function serializedManifestPlugin({
settings,
command,
sync
}: {
settings: AstroSettings;
command: 'dev' | 'build';
sync: boolean;
}): Plugin {
return {
name: SERIALIZED_MANIFEST_ID,
Expand All @@ -53,7 +55,7 @@ export function serializedManifestPlugin({
async load(id) {
if (id === SERIALIZED_MANIFEST_RESOLVED_ID) {
let manifestData: string;
if (command === 'build') {
if (command === 'build' && !sync) {
// Emit placeholder token that will be replaced by plugin-manifest.ts in build:post
// See plugin-manifest.ts for full architecture explanation
manifestData = `'${MANIFEST_REPLACE}'`;
Expand Down
6 changes: 3 additions & 3 deletions packages/integrations/cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
"dependencies": {
"@astrojs/internal-helpers": "workspace:*",
"@astrojs/underscore-redirects": "workspace:*",
"@cloudflare/vite-plugin": "^1.13.14",
"@cloudflare/workers-types": "^4.20251014.0",
"@cloudflare/vite-plugin": "^1.15.2",
"@cloudflare/workers-types": "^4.20251125.0",
"tinyglobby": "^0.2.15",
"vite": "^7.1.12",
"wrangler": "4.44.0"
"wrangler": "4.50.0"
},
"peerDependencies": {
"astro": "^6.0.0-alpha.0"
Expand Down
52 changes: 46 additions & 6 deletions packages/integrations/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createReadStream } from 'node:fs';
import { createReadStream, existsSync, writeFileSync } from 'node:fs';
import { appendFile, stat } from 'node:fs/promises';
import { createRequire } from 'node:module';
import { createInterface } from 'node:readline/promises';
Expand All @@ -9,7 +9,7 @@ import {
removeLeadingForwardSlash,
} from '@astrojs/internal-helpers/path';
import { createRedirectsFromAstroRoutes, printAsRedirects } from '@astrojs/underscore-redirects';
import { cloudflare as cfVitePlugin } from '@cloudflare/vite-plugin';
import { cloudflare as cfVitePlugin, type PluginConfig } from '@cloudflare/vite-plugin';
import type {
AstroConfig,
AstroIntegration,
Expand All @@ -20,9 +20,7 @@ import { AstroError } from 'astro/errors';
import type { PluginOption } from 'vite';
import { defaultClientConditions } from 'vite';
import { type GetPlatformProxyOptions, getPlatformProxy } from 'wrangler';
import {
cloudflareModuleLoader,
} from './utils/cloudflare-module-loader.js';
import { cloudflareModuleLoader } from './utils/cloudflare-module-loader.js';
import { createGetEnv } from './utils/env.js';
import { createRoutesFile, getParts } from './utils/generate-routes-json.js';
import { type ImageService, setImageConfig } from './utils/image-config.js';
Expand Down Expand Up @@ -179,6 +177,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
logger,
addWatchFile,
addMiddleware,
createCodegenDir,
}) => {
let session = config.session;

Expand Down Expand Up @@ -210,6 +209,13 @@ export default function createIntegration(args?: Options): AstroIntegration {
},
};
}
const cfPluginConfig: PluginConfig = { viteEnvironment: { name: 'ssr' } };
if (!hasWranglerConfig(config.root)) {
const codegenDir = createCodegenDir();
const cachedFile = new URL('wrangler.json', codegenDir);
writeFileSync(cachedFile, wranglerTemplate(), 'utf-8');
cfPluginConfig.configPath = cachedFile.pathname;
}

updateConfig({
build: {
Expand All @@ -221,7 +227,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
session,
vite: {
plugins: [
cfVitePlugin({ viteEnvironment: { name: 'ssr' } }),
cfVitePlugin(cfPluginConfig),
// https://developers.cloudflare.com/pages/functions/module-support/
// Allows imports of '.wasm', '.bin', and '.txt' file types
cloudflareModulePlugin,
Expand Down Expand Up @@ -254,13 +260,15 @@ export default function createIntegration(args?: Options): AstroIntegration {
},
image: setImageConfig(args?.imageService ?? 'compile', config.image, command, logger),
});

if (args?.platformProxy?.configPath) {
addWatchFile(new URL(args.platformProxy.configPath, config.root));
} else {
addWatchFile(new URL('./wrangler.toml', config.root));
addWatchFile(new URL('./wrangler.json', config.root));
addWatchFile(new URL('./wrangler.jsonc', config.root));
}

addMiddleware({
entrypoint: '@astrojs/cloudflare/entrypoints/middleware.js',
order: 'pre',
Expand Down Expand Up @@ -478,3 +486,35 @@ export default function createIntegration(args?: Options): AstroIntegration {
},
};
}

function hasWranglerConfig(root: URL) {
return (
existsSync(new URL('wrangler.jsonc', root)) ||
existsSync(new URL('wranger.toml', root)) ||
existsSync(new URL('wranger.json', root))
);
}

function wranglerTemplate(): string {
const wrangler = {
// TODO: better way to handle name, maybe package.json#name ?
name: 'test-application',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is name required? If not maybe we can just omit it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required yes

compatibility_date: '2024-11-01',
main: '@astrojs/cloudflare/entrypoints/server',
assets: {
directory: './dist',
binding: 'ASSETS',
},
images: {
binding: 'IMAGES',
},
kv_namespaces: [
{
binding: 'SESSION',
id: 'SESSION',
},
],
};

return JSON.stringify(wrangler, null, 2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ type ModuleType = 'CompiledWasm' | 'Text' | 'Data';
* @param enabled - if true, will load all cloudflare pages supported types
* @returns Vite plugin with additional extension method to hook into astro build
*/
export function cloudflareModuleLoader(
enabled: boolean,
): PluginOption {
export function cloudflareModuleLoader(enabled: boolean): PluginOption {
/**
* It's likely that eventually cloudflare will add support for custom extensions, like they do in vanilla cloudflare workers,
* by adding rules to your wrangler.tome
Expand Down
34 changes: 15 additions & 19 deletions packages/integrations/cloudflare/test/astro-dev-platform.test.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,46 @@
import * as assert from 'node:assert/strict';
import { after, before, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import * as cheerio from 'cheerio';
import { astroCli } from './_test-utils.js';
import { loadFixture } from './_test-utils.js';

const root = new URL('./fixtures/astro-dev-platform/', import.meta.url);
describe('AstroDevPlatform', () => {
let cli;
let fixture;
let devServer;
before(async () => {
cli = astroCli(fileURLToPath(root), 'dev', '--host', '127.0.0.1').proc;
await new Promise((resolve) => {
cli.stdout.on('data', (data) => {
if (data.includes('http://127.0.0.1:4321/')) {
resolve();
}
});
fixture = await loadFixture({
root: './fixtures/astro-dev-platform/',
logLevel: 'debug',
});
devServer = await fixture.startDevServer();
});

after((_done) => {
cli.kill();
after(async () => {
await devServer.stop();
});

it('exists', async () => {
const res = await fetch('http://127.0.0.1:4321/');
const res = await fixture.fetch('/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasRuntime').text().includes('true'), true);
});

it('adds cf object', async () => {
const res = await fetch('http://127.0.0.1:4321/');
const res = await fixture.fetch('/');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasCF').text(), 'true');
});

it('adds cache mocking', async () => {
const res = await fetch('http://127.0.0.1:4321/caches');
const res = await fixture.fetch('/caches');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasCACHE').text(), 'true');
});

it('adds D1 mocking', async () => {
const res = await fetch('http://127.0.0.1:4321/d1');
const res = await fixture.fetch('/d1');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasDB').text(), 'true');
Expand All @@ -53,7 +49,7 @@ describe('AstroDevPlatform', () => {
});

it('adds R2 mocking', async () => {
const res = await fetch('http://127.0.0.1:4321/r2');
const res = await fixture.fetch('/r2');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasBUCKET').text(), 'true');
Expand All @@ -62,7 +58,7 @@ describe('AstroDevPlatform', () => {
});

it('adds KV mocking', async () => {
const res = await fetch('http://127.0.0.1:4321/kv');
const res = await fixture.fetch('/kv');
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('#hasKV').text(), 'true');
Expand Down
Loading
Loading