Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
cb3f394
refactor: use environments to load modules (#14191)
ematipico Aug 7, 2025
c6a8ac8
refactor: make `App` more extensible using `BaseApp` (#14197)
ematipico Aug 11, 2025
c970fc4
refactor: App to extends the new BaseApp (#14213)
ematipico Aug 22, 2025
a9b4871
refactor: manifest as virtual module (#14298)
ematipico Sep 2, 2025
5df82a0
chore: resolve merging conflicts
ematipico Sep 3, 2025
c701fe4
chore: resolve merging conflicts
ematipico Sep 3, 2025
019336e
refactor: create generate when needed (#14303)
ematipico Sep 3, 2025
9ed7a3c
refactor: routes as virtual module (#14313)
ematipico Sep 8, 2025
ed90bcb
Merge branch 'main' into feat/environment-api
ascorbic Sep 8, 2025
2b17868
Lock
ascorbic Sep 8, 2025
5c41688
Use separate env to load content config (#14324)
ascorbic Sep 8, 2025
4a80ecf
fix: creation of routes list in build (#14325)
ematipico Sep 9, 2025
43b3ed5
refactor(dev): use entry point to bootstrap the app (#14333)
ematipico Sep 9, 2025
de4e76d
refactor(dev): expose dev app and entrypoint (#14337)
ematipico Sep 9, 2025
e168464
Add Cloudflare Vite plugin (#14309)
ascorbic Sep 9, 2025
a2e2965
refactor: dedicated `App` for astro server and for external servers (…
ematipico Sep 15, 2025
1e50d7d
Add support for content layer in env API (#14357)
ascorbic Sep 15, 2025
d5979c2
Add support for Cloudflare images binding in environment API (#14358)
ascorbic Sep 15, 2025
48197bb
Use imported Cloudflare handler in env API (#14360)
ascorbic Sep 15, 2025
b8ba777
Merge branch 'main' into feat/environment-api
ascorbic Sep 15, 2025
22b9c33
Dedupe
ascorbic Sep 15, 2025
77fdf98
Support framework components (#14382)
matthewp Sep 15, 2025
56718e0
Update vite plugin
ascorbic Sep 16, 2025
1a184bc
feat: add support for server islands in Environment API (#14390)
ascorbic Sep 16, 2025
f55775e
Merge branch 'main' into feat/environment-api
ascorbic Sep 16, 2025
dc345ca
Support HMR in Environment API (#14393)
ascorbic Sep 16, 2025
aa355a0
Fix unit tests for environment API (#14394)
ascorbic Sep 17, 2025
28b2f42
refactor: clean up dead code for env API (#14395)
ascorbic Sep 18, 2025
14dd565
Merge branch 'next' into feat/environment-api
ascorbic Sep 18, 2025
62051d5
Add draft changesets
ascorbic Sep 18, 2025
a545ca7
Merge branch 'next' into feat/environment-api
ascorbic Sep 24, 2025
ea1543a
lock
ascorbic Sep 24, 2025
d6caec8
feat: support for astro actions (#14478)
ematipico Oct 2, 2025
a2a07aa
feat: support i18n (#14486)
ematipico Oct 3, 2025
015e4e2
chore: add `astro:env` examples to cloudflare (#14534)
ematipico Oct 14, 2025
f91503f
chore: upgrade vite to v7 (#14535)
ematipico Oct 14, 2025
9d2b501
chore: handle invalidation of manifest (#14537)
ematipico Oct 14, 2025
492cc59
refactor: support devtoolbar (#14549)
ematipico Oct 16, 2025
74ddeaa
chore: fix regression in tests
ematipico Oct 16, 2025
974fdea
chore: add view transitions example (#14561)
ematipico Oct 17, 2025
082d47d
Merge remote-tracking branch 'origin/next' into feat/environment-api
ematipico Oct 20, 2025
5303c50
chore: fix rebase with next
ematipico Oct 20, 2025
f6b0a73
refactor: entrypoint DX (#14563)
ematipico Oct 20, 2025
1fcab24
environments: get images to build in fixture (#14599)
matthewp Oct 22, 2025
783daf6
refactor: support middleware in entrypoint (#14616)
ematipico Oct 28, 2025
714f755
refactor(sessions): import driver via vite plugin (#14632)
ematipico Oct 29, 2025
6c066d5
Get demo app deploying to Cloudflare (#14634)
matthewp Oct 29, 2025
05b8ff9
refactor(core): clean up of apps (#14637)
ematipico Oct 30, 2025
1f1e669
refactor: fonts (#14694)
ematipico Oct 31, 2025
7fcd225
feat: full sessions support w/ environment api (#14696)
matthewp Oct 31, 2025
21d819d
refactor: remove `getRunnableDevEnvironment` (#14705)
ematipico Oct 31, 2025
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
7 changes: 7 additions & 0 deletions .changeset/open-monkeys-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astrojs/cloudflare': major
---

Runs "astro dev" using Cloudflare Vite plugin. This means that dev runs in workerd, giving a dev experience much closer to production.

TODO: add a lot more detail on what this means and what it breaks
7 changes: 7 additions & 0 deletions .changeset/warm-things-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'astro': major
---

Implements Vite Environment API

TODO: add more details
12 changes: 10 additions & 2 deletions benchmark/packages/adapter/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as fs from 'node:fs';
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { AppPipeline, BaseApp } from 'astro/app';

class MyApp extends App {
class MyApp extends BaseApp {
#manifest: SSRManifest | undefined;
constructor(manifest: SSRManifest, streaming = false) {
super(manifest, streaming);
Expand All @@ -19,6 +19,14 @@ class MyApp extends App {

return super.render(request);
}

createPipeline(streaming: boolean) {
return AppPipeline.create({
logger: this.logger,
manifest: this.manifest,
streaming,
});
}
}

export function createExports(manifest: SSRManifest) {
Expand Down
9 changes: 8 additions & 1 deletion knip.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ export default {
'test/types/**/*',
'e2e/**/*.test.js',
'test/units/teardown.js',
// Can't detect this file when using inside a vite plugin
'src/vite-plugin-app/createAstroServerApp.ts',
],
ignore: [
'**/e2e/**/{fixtures,_temp-fixtures}/**',
'performance/**/*',
// This export is resolved dynamically in packages/astro/src/vite-plugin-app/index.ts
'src/vite-plugin-app/createExports.ts',
],
ignore: ['**/e2e/**/{fixtures,_temp-fixtures}/**', 'performance/**/*'],
// Those deps are used in tests but only referenced as strings
ignoreDependencies: [
'rehype-autolink-headings',
Expand Down
31 changes: 31 additions & 0 deletions packages/astro/dev-only.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,34 @@ declare module 'virtual:astro:actions/options' {
declare module 'virtual:astro:actions/runtime' {
export * from './src/actions/runtime/client.js';
}

declare module 'virtual:astro:actions/entrypoint' {
import type { SSRActions } from './src/index.js';
export const server: SSRActions;
}

declare module 'virtual:astro:serialized-manifest' {
import type { SSRManifest } from './src/index.js';
export const manifest: SSRManifest;
}

declare module 'virtual:astro:routes' {
import type { RoutesList } from './src/types/astro.js';
export const routes: RoutesList[];
}

declare module 'virtual:astro:renderers' {
import type { AstroRenderer } from './src/index.js';
export const renderers: AstroRenderer[];
}

declare module 'virtual:astro:middleware' {
import type { AstroMiddlewareInstance } from './src/index.js';
const middleware: AstroMiddlewareInstance;
export default middleware;
}

declare module 'virtual:astro:session-driver' {
import type { Driver } from 'unstorage';
export const driver: Driver;
}
2 changes: 2 additions & 0 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"./container": "./dist/container/index.js",
"./app": "./dist/core/app/index.js",
"./app/node": "./dist/core/app/node.js",
"./app/entrypoint": "./dist/core/app/entrypoint.js",
"./client/*": "./dist/runtime/client/*",
"./components": "./components/index.ts",
"./components/*": "./components/*",
Expand All @@ -55,6 +56,7 @@
"./assets": "./dist/assets/index.js",
"./assets/runtime": "./dist/assets/runtime.js",
"./assets/utils": "./dist/assets/utils/index.js",
"./assets/utils/node": "./dist/assets/utils/node.js",
"./assets/utils/inferRemoteSize.js": "./dist/assets/utils/remoteProbe.js",
"./assets/endpoint/*": "./dist/assets/endpoint/*.js",
"./assets/services/sharp": "./dist/assets/services/sharp.js",
Expand Down
18 changes: 0 additions & 18 deletions packages/astro/src/actions/loadActions.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/astro/src/assets/endpoint/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ function getImageEndpointData(
segments,
params: [],
component: resolveInjectedRoute(endpointEntrypoint, settings.config.root, cwd).component,
generate: () => '',
pathname: settings.config.image.endpoint.route,
prerender: false,
fallbackRoutes: [],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ViteDevServer } from 'vite';
import type { RunnableDevEnvironment } from 'vite';
import type { RemoteFontProviderModResolver } from '../definitions.js';

export function createBuildRemoteFontProviderModResolver(): RemoteFontProviderModResolver {
Expand All @@ -10,13 +10,13 @@ export function createBuildRemoteFontProviderModResolver(): RemoteFontProviderMo
}

export function createDevServerRemoteFontProviderModResolver({
server,
environment,
}: {
server: ViteDevServer;
environment: RunnableDevEnvironment;
}): RemoteFontProviderModResolver {
return {
resolve(id) {
return server.ssrLoadModule(id);
return environment.runner.import(id);
},
};
}
6 changes: 4 additions & 2 deletions packages/astro/src/assets/fonts/vite-plugin-fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { readFile } from 'node:fs/promises';
import { isAbsolute } from 'node:path';
import { fileURLToPath } from 'node:url';
import { bold } from 'kleur/colors';
import type { Plugin } from 'vite';
import type { Plugin, RunnableDevEnvironment } from 'vite';
import { getAlgorithm, shouldTrackCspHashes } from '../../core/csp/common.js';
import { generateCspDigest } from '../../core/encryption.js';
import { collectErrorMetadata } from '../../core/errors/dev/utils.js';
Expand Down Expand Up @@ -232,7 +232,9 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
await initialize({
// In dev, we cache fonts data in .astro so it can be easily inspected and cleared
cacheDir: new URL(CACHE_DIR, settings.dotAstroDir),
modResolver: createDevServerRemoteFontProviderModResolver({ server }),
modResolver: createDevServerRemoteFontProviderModResolver({
environment: server.environments.astro as RunnableDevEnvironment,
}),
cssRenderer: createMinifiableCssRenderer({ minify: false }),
urlResolver: createDevUrlResolver({ base: baseUrl }),
createHashResolver: (dependencies) =>
Expand Down
2 changes: 0 additions & 2 deletions packages/astro/src/assets/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

export { isESMImportedImage, isRemoteImage, resolveSrc } from './imageKind.js';
export { imageMetadata } from './metadata.js';
export { emitImageMetadata } from './node/emitAsset.js';
export { getOrigQueryParams } from './queryParams.js';
export {
isRemoteAllowed,
Expand All @@ -19,4 +18,3 @@ export {
type RemotePattern,
} from './remotePattern.js';
export { inferRemoteSize } from './remoteProbe.js';
export { hashTransform, propsToFilename } from './transformToPath.js';
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import path, { basename, dirname, extname } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { deterministicString } from 'deterministic-object-hash';
import type * as vite from 'vite';
import { generateContentHash } from '../../../core/encryption.js';
import { prependForwardSlash, slash } from '../../../core/path.js';
import type { ImageMetadata } from '../../types.js';
import { imageMetadata } from '../metadata.js';
import { generateContentHash } from '../../core/encryption.js';
import { prependForwardSlash, removeQueryString, slash } from '../../core/path.js';
import { shorthash } from '../../runtime/server/shorthash.js';
import type { ImageMetadata, ImageTransform } from '../types.js';
import { isESMImportedImage } from './imageKind.js';
import { imageMetadata } from './metadata.js';

type FileEmitter = vite.Rollup.EmitFile;
type ImageMetadataWithContents = ImageMetadata & { contents?: Buffer };
Expand Down Expand Up @@ -139,3 +142,70 @@ function fileURLToNormalizedPath(filePath: URL): string {
// Uses `slash` instead of Vite's `normalizePath` to avoid CJS bundling issues.
return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/');
}

// Taken from https://github.com/rollup/rollup/blob/a8647dac0fe46c86183be8596ef7de25bc5b4e4b/src/utils/sanitizeFileName.ts
// eslint-disable-next-line no-control-regex
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$%&*+,:;<=>?[\]^`{|}\u007F]/g;

/**
* Converts a file path and transformation properties of the transformation image service, into a formatted filename.
*
* The formatted filename follows this structure:
*
* `<prefixDirname>/<baseFilename>_<hash><outputExtension>`
*
* - `prefixDirname`: If the image is an ESM imported image, this is the directory name of the original file path; otherwise, it will be an empty string.
* - `baseFilename`: The base name of the file or a hashed short name if the file is a `data:` URI.
* - `hash`: A unique hash string generated to distinguish the transformed file.
* - `outputExtension`: The desired output file extension derived from the `transform.format` or the original file extension.
*
* ## Example
* - Input: `filePath = '/images/photo.jpg'`, `transform = { format: 'png', src: '/images/photo.jpg' }`, `hash = 'abcd1234'`.
* - Output: `/images/photo_abcd1234.png`
*
* @param {string} filePath - The original file path or data URI of the source image.
* @param {ImageTransform} transform - An object representing the transformation properties, including format and source.
* @param {string} hash - A unique hash used to differentiate the transformed file.
* @return {string} The generated filename based on the provided input, transformations, and hash.
*/

export function propsToFilename(filePath: string, transform: ImageTransform, hash: string): string {
let filename = decodeURIComponent(removeQueryString(filePath));
const ext = extname(filename);
if (filePath.startsWith('data:')) {
filename = shorthash(filePath);
} else {
filename = basename(filename, ext).replace(INVALID_CHAR_REGEX, '_');
}
const prefixDirname = isESMImportedImage(transform.src) ? dirname(filePath) : '';

let outputExt = transform.format ? `.${transform.format}` : ext;
return `${prefixDirname}/${filename}_${hash}${outputExt}`;
}

/**
* Transforms the provided `transform` object into a hash string based on selected properties
* and the specified `imageService`.
*
* @param {ImageTransform} transform - The transform object containing various image transformation properties.
* @param {string} imageService - The name of the image service related to the transform.
* @param {string[]} propertiesToHash - An array of property names from the `transform` object that should be used to generate the hash.
* @return {string} A hashed string created from the specified properties of the `transform` object and the image service.
*/
export function hashTransform(
transform: ImageTransform,
imageService: string,
propertiesToHash: string[],
): string {
// Extract the fields we want to hash
const hashFields = propertiesToHash.reduce(
(acc, prop) => {
// It's possible for `transform[prop]` here to be undefined, or null, but that's fine because it's still consistent
// between different transforms. (ex: every transform without a height will explicitly have a `height: undefined` property)
acc[prop] = transform[prop];
return acc;
},
{ imageService } as Record<string, unknown>,
);
return shorthash(deterministicString(hashFields));
}
73 changes: 0 additions & 73 deletions packages/astro/src/assets/utils/transformToPath.ts

This file was deleted.

5 changes: 2 additions & 3 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from './co
import { fontsPlugin } from './fonts/vite-plugin-fonts.js';
import type { ImageTransform } from './types.js';
import { getAssetsPrefix } from './utils/getAssetsPrefix.js';
import { isESMImportedImage } from './utils/imageKind.js';
import { emitImageMetadata } from './utils/node/emitAsset.js';
import { isESMImportedImage } from './utils/index.js';
import { emitImageMetadata, hashTransform, propsToFilename } from './utils/node.js';
import { getProxyCode } from './utils/proxy.js';
import { makeSvgComponent } from './utils/svg.js';
import { hashTransform, propsToFilename } from './utils/transformToPath.js';

const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;

Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/config/entrypoint.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// IMPORTANT: this file is the entrypoint for "astro/config". Keep it as light as possible!

import type { SharpImageServiceConfig } from '../assets/services/sharp.js';

import type { ImageServiceConfig } from '../types/public/index.js';

export { defineAstroFontProvider, fontProviders } from '../assets/fonts/providers/index.js';
Expand Down
Loading
Loading