{comment.user}{' '}
- {comment.time_ago} ago
+ {comment.time_ago}
diff --git a/examples/hackernews/src/pages/stories/[id].astro b/examples/hackernews/src/pages/stories/[id].astro
index 6cd17ea456bf..84383aa9e4ab 100644
--- a/examples/hackernews/src/pages/stories/[id].astro
+++ b/examples/hackernews/src/pages/stories/[id].astro
@@ -25,7 +25,7 @@ const story = (await fetchAPI(`item/${id}`)) as IStory;
{story.user}
- {story.time_ago} ago
+ {story.time_ago}
diff --git a/examples/integration/README.md b/examples/integration/README.md
index f40c3dbd0a88..a6709d4004de 100644
--- a/examples/integration/README.md
+++ b/examples/integration/README.md
@@ -10,7 +10,6 @@ npm create astro@latest -- --template integration
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/integration)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/integration/devcontainer.json)
-
## π Project Structure
Inside of your Astro project, you'll see the following folders and files:
@@ -25,9 +24,10 @@ Inside of your Astro project, you'll see the following folders and files:
The `index.ts` file is the "entry point" for your integration. Export your integration in `index.ts` to make them importable from your package.
## π§ Commands
+
All commands are run from the root of the project, from a terminal:
-| Command | Action |
-| :--------------------- | :----------------------------------------------- |
-| `npm link` | Registers this package locally. Run `npm link my-integration` in an Astro project to install your integration
-| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser)
+| Command | Action |
+| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `npm link` | Registers this package locally. Run `npm link my-integration` in an Astro project to install your integration |
+| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser) |
diff --git a/examples/integration/package.json b/examples/integration/package.json
index 9e38a05899d5..cd69a5f00309 100644
--- a/examples/integration/package.json
+++ b/examples/integration/package.json
@@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
- "astro": "^2.5.6"
+ "astro": "^2.7.0"
},
"peerDependencies": {
"astro": "^2.0.0-beta.0"
diff --git a/examples/middleware/package.json b/examples/middleware/package.json
index 9cd76a52f152..24c1ad69fe83 100644
--- a/examples/middleware/package.json
+++ b/examples/middleware/package.json
@@ -12,8 +12,8 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
- "@astrojs/node": "^5.1.4",
- "astro": "^2.5.6",
+ "@astrojs/node": "^5.3.0",
+ "astro": "^2.7.0",
"html-minifier": "^4.0.0"
}
}
diff --git a/examples/minimal/package.json b/examples/minimal/package.json
index da59a3f411c4..ebb75fdc3ea5 100644
--- a/examples/minimal/package.json
+++ b/examples/minimal/package.json
@@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^2.5.6"
+ "astro": "^2.7.0"
}
}
diff --git a/examples/non-html-pages/package.json b/examples/non-html-pages/package.json
index 5f161e8f5b4d..5980d6ee747c 100644
--- a/examples/non-html-pages/package.json
+++ b/examples/non-html-pages/package.json
@@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^2.5.6"
+ "astro": "^2.7.0"
}
}
diff --git a/examples/portfolio/README.md b/examples/portfolio/README.md
index cc9cdd5e3871..7ca90501af54 100644
--- a/examples/portfolio/README.md
+++ b/examples/portfolio/README.md
@@ -12,7 +12,6 @@ npm create astro@latest -- --template portfolio
![portfolio](https://user-images.githubusercontent.com/357379/210779178-a98f0fb7-6b1a-4068-894c-8e1403e26654.jpg)
-
## π§ Commands
All commands are run from the root of the project, from a terminal:
diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json
index 1aeb84bce35f..2294a88a47dc 100644
--- a/examples/portfolio/package.json
+++ b/examples/portfolio/package.json
@@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^2.5.6"
+ "astro": "^2.7.0"
}
}
diff --git a/examples/ssr/package.json b/examples/ssr/package.json
index 039523d19df9..61406b4c9bc2 100644
--- a/examples/ssr/package.json
+++ b/examples/ssr/package.json
@@ -12,9 +12,9 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
- "@astrojs/node": "^5.1.4",
- "@astrojs/svelte": "^2.2.0",
- "astro": "^2.5.6",
- "svelte": "^3.58.0"
+ "@astrojs/node": "^5.3.0",
+ "@astrojs/svelte": "^3.0.0",
+ "astro": "^2.7.0",
+ "svelte": "^3.59.1"
}
}
diff --git a/examples/with-markdoc/package.json b/examples/with-markdoc/package.json
index 78464f67725b..ca45b0f247a5 100644
--- a/examples/with-markdoc/package.json
+++ b/examples/with-markdoc/package.json
@@ -11,7 +11,7 @@
"astro": "astro"
},
"dependencies": {
- "@astrojs/markdoc": "^0.3.0",
- "astro": "^2.6.2"
+ "@astrojs/markdoc": "^0.3.3",
+ "astro": "^2.7.0"
}
}
diff --git a/examples/with-markdown-plugins/package.json b/examples/with-markdown-plugins/package.json
index 73074cd65b41..3fcb9e09a78c 100644
--- a/examples/with-markdown-plugins/package.json
+++ b/examples/with-markdown-plugins/package.json
@@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/markdown-remark": "^2.2.1",
- "astro": "^2.5.6",
+ "astro": "^2.7.0",
"hast-util-select": "^5.0.5",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
diff --git a/examples/with-markdown-shiki/package.json b/examples/with-markdown-shiki/package.json
index 3693a32f3f9d..11adc9386ced 100644
--- a/examples/with-markdown-shiki/package.json
+++ b/examples/with-markdown-shiki/package.json
@@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^2.5.6"
+ "astro": "^2.7.0"
}
}
diff --git a/examples/with-mdx/package.json b/examples/with-mdx/package.json
index 5c92ed78fdef..d3aefd99f5e1 100644
--- a/examples/with-mdx/package.json
+++ b/examples/with-mdx/package.json
@@ -11,9 +11,9 @@
"astro": "astro"
},
"dependencies": {
- "@astrojs/mdx": "^0.19.5",
+ "@astrojs/mdx": "^0.19.7",
"@astrojs/preact": "^2.2.1",
- "astro": "^2.5.6",
- "preact": "^10.13.2"
+ "astro": "^2.7.0",
+ "preact": "^10.15.1"
}
}
diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json
index 6aacc796638f..aa127b5e4297 100644
--- a/examples/with-nanostores/package.json
+++ b/examples/with-nanostores/package.json
@@ -13,8 +13,8 @@
"dependencies": {
"@astrojs/preact": "^2.2.1",
"@nanostores/preact": "^0.4.1",
- "astro": "^2.5.6",
+ "astro": "^2.7.0",
"nanostores": "^0.8.1",
- "preact": "^10.13.2"
+ "preact": "^10.15.1"
}
}
diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json
index e8792dc38eff..a08f28c6ee1f 100644
--- a/examples/with-tailwindcss/package.json
+++ b/examples/with-tailwindcss/package.json
@@ -11,13 +11,13 @@
"astro": "astro"
},
"dependencies": {
- "@astrojs/mdx": "^0.19.5",
- "@astrojs/tailwind": "^3.1.3",
+ "@astrojs/mdx": "^0.19.7",
+ "@astrojs/tailwind": "^4.0.0",
"@types/canvas-confetti": "^1.6.0",
- "astro": "^2.5.6",
+ "astro": "^2.7.0",
"autoprefixer": "^10.4.14",
"canvas-confetti": "^1.6.0",
- "postcss": "^8.4.23",
+ "postcss": "^8.4.24",
"tailwindcss": "^3.3.2"
}
}
diff --git a/examples/with-vite-plugin-pwa/package.json b/examples/with-vite-plugin-pwa/package.json
index 8182f61fe9a9..d1a0b5f4db3d 100644
--- a/examples/with-vite-plugin-pwa/package.json
+++ b/examples/with-vite-plugin-pwa/package.json
@@ -11,8 +11,8 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^2.5.6",
+ "astro": "^2.7.0",
"vite-plugin-pwa": "0.14.7",
- "workbox-window": "^6.5.4"
+ "workbox-window": "^6.6.0"
}
}
diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json
index 307feda3ec12..7eff098f6512 100644
--- a/examples/with-vitest/package.json
+++ b/examples/with-vitest/package.json
@@ -12,7 +12,7 @@
"test": "vitest"
},
"dependencies": {
- "astro": "^2.5.6",
- "vitest": "^0.31.0"
+ "astro": "^2.7.0",
+ "vitest": "^0.31.4"
}
}
diff --git a/package.json b/package.json
index 5c369d22d448..b65d19e88979 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"build": "turbo run build --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"",
"build:ci": "turbo run build:ci --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"",
"build:examples": "turbo run build --filter=\"@example/*\"",
- "dev": "turbo run dev --parallel --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"",
+ "dev": "turbo run dev --concurrency=40 --parallel --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"",
"format": "pnpm run format:code",
"format:ci": "pnpm run format:imports && pnpm run format:code",
"format:code": "prettier -w . --cache --plugin-search-dir=.",
@@ -29,7 +29,7 @@
"test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match",
"benchmark": "astro-benchmark",
"lint": "eslint --cache .",
- "version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run format",
+ "version": "changeset version && node ./scripts/deps/update-example-versions.js && pnpm install --no-frozen-lockfile && pnpm run format",
"preinstall": "npx only-allow pnpm"
},
"workspaces": [
@@ -39,9 +39,9 @@
],
"engines": {
"node": ">=16.12.0",
- "pnpm": ">=8.2.0"
+ "pnpm": ">=8.6.2"
},
- "packageManager": "pnpm@8.6.0",
+ "packageManager": "pnpm@8.6.2",
"pnpm": {
"packageExtensions": {
"svelte2tsx": {
@@ -68,9 +68,6 @@
"allowAny": [
"astro"
]
- },
- "patchedDependencies": {
- "@changesets/cli@2.23.0": "patches/@changesets__cli@2.23.0.patch"
}
},
"dependencies": {
@@ -78,22 +75,22 @@
"astro-benchmark": "workspace:*"
},
"devDependencies": {
- "@changesets/changelog-github": "0.4.4",
- "@changesets/cli": "2.23.0",
- "@types/node": "^18.7.21",
- "@typescript-eslint/eslint-plugin": "^5.58.0",
- "@typescript-eslint/parser": "^5.58.0",
- "esbuild": "^0.17.12",
- "eslint": "^8.38.0",
+ "@changesets/changelog-github": "^0.4.8",
+ "@changesets/cli": "^2.26.1",
+ "@types/node": "^18.16.18",
+ "@typescript-eslint/eslint-plugin": "^5.60.0",
+ "@typescript-eslint/parser": "^5.60.0",
+ "esbuild": "^0.17.19",
+ "eslint": "^8.43.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-no-only-tests": "^2.6.0",
"eslint-plugin-prettier": "^4.2.1",
"only-allow": "^1.1.1",
"organize-imports-cli": "^0.10.0",
"prettier": "^2.8.8",
- "prettier-plugin-astro": "^0.8.0",
+ "prettier-plugin-astro": "^0.10.0",
"tiny-glob": "^0.2.9",
- "turbo": "^1.9.3",
+ "turbo": "^1.10.3",
"typescript": "~5.0.2"
}
}
diff --git a/packages/astro-prism/README.md b/packages/astro-prism/README.md
index 1e8e92fa21a4..f5627d06200c 100644
--- a/packages/astro-prism/README.md
+++ b/packages/astro-prism/README.md
@@ -8,7 +8,7 @@ This package exports a component to support highlighting inside an Astro file. E
```astro
---
-import {Β Prism } from "@astrojs/prism"
+import { Prism } from '@astrojs/prism';
---
@@ -21,11 +21,14 @@ This package exports a `runHighlighterWithAstro` function to highlight while mak
```typescript
import { runHighlighterWithAstro } from '@astrojs/prism';
-runHighlighterWithAstro(`
+runHighlighterWithAstro(
+ `
---
const helloAstro = 'Hello, Astro!';
---
{helloAstro}
-`, 'astro');
+`,
+ 'astro'
+);
```
diff --git a/packages/astro-prism/package.json b/packages/astro-prism/package.json
index c658e329385f..4ad55bf7f710 100644
--- a/packages/astro-prism/package.json
+++ b/packages/astro-prism/package.json
@@ -32,11 +32,11 @@
"astro-component"
],
"dependencies": {
- "prismjs": "^1.28.0"
+ "prismjs": "^1.29.0"
},
"devDependencies": {
- "astro-scripts": "workspace:*",
- "@types/prismjs": "1.26.0"
+ "@types/prismjs": "1.26.0",
+ "astro-scripts": "workspace:*"
},
"engines": {
"node": ">=16.12.0"
diff --git a/packages/astro-rss/README.md b/packages/astro-rss/README.md
index 43adaad92b6e..47dfc1747635 100644
--- a/packages/astro-rss/README.md
+++ b/packages/astro-rss/README.md
@@ -36,14 +36,14 @@ export async function get(context) {
// Pull in your project "site" from the endpoint context
// https://docs.astro.build/en/reference/api-reference/#contextsite
site: context.site,
- items: posts.map(post => ({
+ items: posts.map((post) => ({
// Assumes all RSS feed item properties are in post frontmatter
...post.data,
// Generate a `url` from each post `slug`
// This assumes all blog posts are rendered as `/blog/[slug]` routes
// https://docs.astro.build/en/guides/content-collections/#generating-pages-from-content-collections
link: `/blog/${post.slug}/`,
- }))
+ })),
});
}
```
@@ -180,9 +180,10 @@ By default, the library will add trailing slashes to the emitted URLs. To preven
```js
import rss from '@astrojs/rss';
-export const get = () => rss({
- trailingSlash: false
-});
+export const get = () =>
+ rss({
+ trailingSlash: false,
+ });
```
## `RSSFeedItem`
@@ -193,12 +194,13 @@ An example feed item might look like:
```js
const item = {
- title: "Alpha Centauri: so close you can touch it",
- link: "/blog/alpha-centuari",
- pubDate: new Date("2023-06-04"),
- description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.",
- categories: ["stars", "space"]
-}
+ title: 'Alpha Centauri: so close you can touch it',
+ link: '/blog/alpha-centuari',
+ pubDate: new Date('2023-06-04'),
+ description:
+ 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.',
+ categories: ['stars', 'space'],
+};
```
### `title`
@@ -259,15 +261,16 @@ An object that defines the `title` and `url` of the original feed for items that
```js
const item = {
- title: "Alpha Centauri: so close you can touch it",
- link: "/blog/alpha-centuari",
- pubDate: new Date("2023-06-04"),
- description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.",
- source: {
- title: "The Galactic Times",
- url: "https://galactictimes.space/feed.xml"
- }
-}
+ title: 'Alpha Centauri: so close you can touch it',
+ link: '/blog/alpha-centuari',
+ pubDate: new Date('2023-06-04'),
+ description:
+ 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.',
+ source: {
+ title: 'The Galactic Times',
+ url: 'https://galactictimes.space/feed.xml',
+ },
+};
```
#### `source.title`
@@ -290,16 +293,17 @@ An object to specify properties for an included media source (e.g. a podcast) wi
```js
const item = {
- title: "Alpha Centauri: so close you can touch it",
- link: "/blog/alpha-centuari",
- pubDate: new Date("2023-06-04"),
- description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.",
- enclosure: {
- url: "/media/alpha-centauri.aac",
+ title: 'Alpha Centauri: so close you can touch it',
+ link: '/blog/alpha-centuari',
+ pubDate: new Date('2023-06-04'),
+ description:
+ 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.',
+ enclosure: {
+ url: '/media/alpha-centauri.aac',
length: 124568,
- type: "audio/aac"
- }
-}
+ type: 'audio/aac',
+ },
+};
```
#### `enclosure.url`
@@ -361,9 +365,7 @@ export async function get(context) {
title: 'Buzzβs Blog',
description: 'A humble Astronautβs guide to the stars',
site: context.site,
- items: await pagesGlobToRssItems(
- import.meta.glob('./blog/*.{md,mdx}'),
- ),
+ items: await pagesGlobToRssItems(import.meta.glob('./blog/*.{md,mdx}')),
});
}
```
diff --git a/packages/astro-rss/package.json b/packages/astro-rss/package.json
index e9a97157c316..572f9649cb64 100644
--- a/packages/astro-rss/package.json
+++ b/packages/astro-rss/package.json
@@ -27,18 +27,18 @@
"test": "mocha --exit --timeout 20000"
},
"devDependencies": {
- "@types/chai": "^4.3.1",
+ "@types/chai": "^4.3.5",
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^9.1.1",
"astro": "workspace:*",
"astro-scripts": "workspace:*",
- "chai": "^4.3.6",
+ "chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
- "chai-xml": "^0.4.0",
+ "chai-xml": "^0.4.1",
"mocha": "^9.2.2"
},
"dependencies": {
- "fast-xml-parser": "^4.0.8",
+ "fast-xml-parser": "^4.2.5",
"kleur": "^4.1.5"
}
}
diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md
index ea3dbffc23bc..917271ba12c4 100644
--- a/packages/astro/CHANGELOG.md
+++ b/packages/astro/CHANGELOG.md
@@ -1,5 +1,77 @@
# astro
+## 2.7.0
+
+### Minor Changes
+
+- [#7353](https://github.com/withastro/astro/pull/7353) [`76fcdb84d`](https://github.com/withastro/astro/commit/76fcdb84dd828ac373b2dc739e57fadf650820fd) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove legacy handling for MDX content collections. Ensure you are using `@astrojs/mdx` v0.18 or above.
+
+- [#7385](https://github.com/withastro/astro/pull/7385) [`8e2923cc6`](https://github.com/withastro/astro/commit/8e2923cc6219eda01ca2c749f5c7fa2fe4319455) Thanks [@ematipico](https://github.com/ematipico)! - `Astro.locals` is now exposed to the adapter API. Node Adapter can now pass in a `locals` object in the SSR handler middleware.
+
+- [#7220](https://github.com/withastro/astro/pull/7220) [`459b5bd05`](https://github.com/withastro/astro/commit/459b5bd05f562238f7250520efe3cf0fa156bb45) Thanks [@ematipico](https://github.com/ematipico)! - Shipped a new SSR build configuration mode: `split`.
+ When enabled, Astro will "split" the single `entry.mjs` file and instead emit a separate file to render each individual page during the build process.
+
+ These files will be emitted inside `dist/pages`, mirroring the directory structure of your page files in `src/pages/`, for example:
+
+ ```
+ βββ pages
+ β βββ blog
+ β β βββ entry._slug_.astro.mjs
+ β β βββ entry.about.astro.mjs
+ β βββ entry.index.astro.mjs
+ ```
+
+ To enable, set `build.split: true` in your Astro config:
+
+ ```js
+ // src/astro.config.mjs
+ export default defineConfig({
+ output: 'server',
+ adapter: node({
+ mode: 'standalone',
+ }),
+ build: {
+ split: true,
+ },
+ });
+ ```
+
+### Patch Changes
+
+- [#7438](https://github.com/withastro/astro/pull/7438) [`30bb36371`](https://github.com/withastro/astro/commit/30bb363713e3d2c50d0d4816d970aa93b836a3b0) Thanks [@bluwy](https://github.com/bluwy)! - Fix `astro:build:setup` hook `updateConfig` utility, where the configuration wasn't correctly updated when the hook was fired.
+
+- [#7436](https://github.com/withastro/astro/pull/7436) [`3943fa390`](https://github.com/withastro/astro/commit/3943fa390a0bd41317a673d0f841e0461c7499cd) Thanks [@kossidts](https://github.com/kossidts)! - Fix an issue related to the documentation. Destructure the argument of the function to customize the Astro dev server based on the command run.
+
+- [#7424](https://github.com/withastro/astro/pull/7424) [`7877a06d8`](https://github.com/withastro/astro/commit/7877a06d829305eed356fbb8bfd1ef578cd5466e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Update internal types for more stable builds for Astro maintainers.
+
+- [#7427](https://github.com/withastro/astro/pull/7427) [`e314a04bf`](https://github.com/withastro/astro/commit/e314a04bfbf0526838b7c9aac452251b27d69719) Thanks [@ematipico](https://github.com/ematipico)! - Correctly emit the middleware code during the build phase. The file emitted is now `dist/middleware.mjs`
+
+- [#7423](https://github.com/withastro/astro/pull/7423) [`33cdc8622`](https://github.com/withastro/astro/commit/33cdc8622a56c8e5465b7a50f627ecc568870c6b) Thanks [@bmenant](https://github.com/bmenant)! - Ensure injected `/_image` endpoint for image optimization is not prerendered on hybrid output.
+
+## 2.6.6
+
+### Patch Changes
+
+- [#7418](https://github.com/withastro/astro/pull/7418) [`2b34fc492`](https://github.com/withastro/astro/commit/2b34fc49282cbf5bf89de46359b51a67a5c4b8bb) Thanks [@ematipico](https://github.com/ematipico)! - Correctly type the option `server.open`
+
+- [#7429](https://github.com/withastro/astro/pull/7429) [`89a483520`](https://github.com/withastro/astro/commit/89a4835202f05d9571aeb42740dbe907a8afc28b) Thanks [@delucis](https://github.com/delucis)! - Fix telemetry reporting for integrations that return an array
+
+## 2.6.5
+
+### Patch Changes
+
+- [#7414](https://github.com/withastro/astro/pull/7414) [`bb644834e`](https://github.com/withastro/astro/commit/bb644834ef03bc00048c7381f20a1c01388438e2) Thanks [@bluwy](https://github.com/bluwy)! - Simplify telemetry Vite version detection
+
+- [#7399](https://github.com/withastro/astro/pull/7399) [`d2020c29c`](https://github.com/withastro/astro/commit/d2020c29cf285e699f92143a70ffa30a85122bb4) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix edge case where injected routes would cause builds to fail in a PNPM workspace
+
+## 2.6.4
+
+### Patch Changes
+
+- [#7366](https://github.com/withastro/astro/pull/7366) [`42baf62e7`](https://github.com/withastro/astro/commit/42baf62e7ca0351a2f2c7d06ec58086f90519bb7) Thanks [@aappaapp](https://github.com/aappaapp)! - Fixed `RedirectConfig` type definition
+
+- [#7380](https://github.com/withastro/astro/pull/7380) [`1c7b63595`](https://github.com/withastro/astro/commit/1c7b6359563f5e83325121efb2e61915d818a35a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix missing stacktraces for Zod errors
+
## 2.6.3
### Patch Changes
diff --git a/packages/astro/README.md b/packages/astro/README.md
index ebd4ca3c7767..9e3ff67c3ac9 100644
--- a/packages/astro/README.md
+++ b/packages/astro/README.md
@@ -8,10 +8,8 @@
-
## Install
-
```bash
# Recommended!
npm create astro@latest
@@ -20,7 +18,7 @@ npm create astro@latest
npm install --save-dev astro
```
-Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide.
+Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide.
Looking for quick examples? [Open a starter project](https://astro.new/) right in your browser.
@@ -31,9 +29,10 @@ Visit our [official documentation](https://docs.astro.build/).
## Support
Having trouble? Get help in the official [Astro Discord](https://astro.build/chat).
+
## Contributing
-**New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started.
+**New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started.
Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll help you get your first contribution in no time!
@@ -42,5 +41,3 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
Astro is generously supported by [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com/), and several other amazing organizations [listed here.](https://astro.build/)
[β€οΈ Sponsor Astro! β€οΈ](https://github.com/withastro/.github/blob/main/FUNDING.md)
-
-
diff --git a/packages/astro/src/content/template/virtual-mod.mjs b/packages/astro/content-module.template.mjs
similarity index 100%
rename from packages/astro/src/content/template/virtual-mod.mjs
rename to packages/astro/content-module.template.mjs
diff --git a/packages/astro/src/content/template/types.d.ts b/packages/astro/content-types.template.d.ts
similarity index 100%
rename from packages/astro/src/content/template/types.d.ts
rename to packages/astro/content-types.template.d.ts
diff --git a/packages/astro/e2e/fixtures/astro-component/package.json b/packages/astro/e2e/fixtures/astro-component/package.json
index 165b38931d70..225864913953 100644
--- a/packages/astro/e2e/fixtures/astro-component/package.json
+++ b/packages/astro/e2e/fixtures/astro-component/package.json
@@ -6,6 +6,6 @@
"@astrojs/preact": "workspace:*",
"@e2e/astro-linked-lib": "link:../_deps/astro-linked-lib",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/astro-envs/package.json b/packages/astro/e2e/fixtures/astro-envs/package.json
index e115f9c726e1..2fa703b969de 100644
--- a/packages/astro/e2e/fixtures/astro-envs/package.json
+++ b/packages/astro/e2e/fixtures/astro-envs/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
- "vue": "^3.2.40"
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/client-only/package.json b/packages/astro/e2e/fixtures/client-only/package.json
index 2a1e89ab3630..d072e8bdd801 100644
--- a/packages/astro/e2e/fixtures/client-only/package.json
+++ b/packages/astro/e2e/fixtures/client-only/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/error-cyclic/package.json b/packages/astro/e2e/fixtures/error-cyclic/package.json
index a1c170e71090..9a3fbde601cc 100644
--- a/packages/astro/e2e/fixtures/error-cyclic/package.json
+++ b/packages/astro/e2e/fixtures/error-cyclic/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/error-sass/package.json b/packages/astro/e2e/fixtures/error-sass/package.json
index f52820ad2b35..097bad23e698 100644
--- a/packages/astro/e2e/fixtures/error-sass/package.json
+++ b/packages/astro/e2e/fixtures/error-sass/package.json
@@ -4,6 +4,6 @@
"private": true,
"dependencies": {
"astro": "workspace:*",
- "sass": "^1.52.2"
+ "sass": "^1.63.4"
}
}
diff --git a/packages/astro/e2e/fixtures/errors/package.json b/packages/astro/e2e/fixtures/errors/package.json
index cbcab17d333a..c535e5001de4 100644
--- a/packages/astro/e2e/fixtures/errors/package.json
+++ b/packages/astro/e2e/fixtures/errors/package.json
@@ -9,11 +9,11 @@
"@astrojs/svelte": "workspace:*",
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.5.6",
- "svelte": "^3.50.1",
- "vue": "^3.2.39"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/hydration-race/package.json b/packages/astro/e2e/fixtures/hydration-race/package.json
index 2d2ca0673de3..f1ab746c3e95 100644
--- a/packages/astro/e2e/fixtures/hydration-race/package.json
+++ b/packages/astro/e2e/fixtures/hydration-race/package.json
@@ -9,6 +9,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/lit-component/package.json b/packages/astro/e2e/fixtures/lit-component/package.json
index 06e374a42cc5..961507fe8333 100644
--- a/packages/astro/e2e/fixtures/lit-component/package.json
+++ b/packages/astro/e2e/fixtures/lit-component/package.json
@@ -6,6 +6,6 @@
"@astrojs/lit": "workspace:*",
"@webcomponents/template-shadowroot": "^0.2.1",
"astro": "workspace:*",
- "lit": "^2.7.0"
+ "lit": "^2.7.5"
}
}
diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/package.json b/packages/astro/e2e/fixtures/multiple-frameworks/package.json
index 91f95a97a498..1037db0f7249 100644
--- a/packages/astro/e2e/fixtures/multiple-frameworks/package.json
+++ b/packages/astro/e2e/fixtures/multiple-frameworks/package.json
@@ -13,12 +13,12 @@
},
"dependencies": {
"@webcomponents/template-shadowroot": "^0.2.1",
- "lit": "^2.7.0",
- "preact": "^10.7.3",
+ "lit": "^2.7.5",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/namespaced-component/package.json b/packages/astro/e2e/fixtures/namespaced-component/package.json
index 96de360e265e..5f4fd82773c1 100644
--- a/packages/astro/e2e/fixtures/namespaced-component/package.json
+++ b/packages/astro/e2e/fixtures/namespaced-component/package.json
@@ -8,6 +8,6 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-in-preact/package.json b/packages/astro/e2e/fixtures/nested-in-preact/package.json
index 624316f913c8..2b6db13afcfa 100644
--- a/packages/astro/e2e/fixtures/nested-in-preact/package.json
+++ b/packages/astro/e2e/fixtures/nested-in-preact/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-in-react/package.json b/packages/astro/e2e/fixtures/nested-in-react/package.json
index 29ee37d2aae5..a1708a0edae4 100644
--- a/packages/astro/e2e/fixtures/nested-in-react/package.json
+++ b/packages/astro/e2e/fixtures/nested-in-react/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-in-solid/package.json b/packages/astro/e2e/fixtures/nested-in-solid/package.json
index 9a51cb0093bb..00c6cdaf777d 100644
--- a/packages/astro/e2e/fixtures/nested-in-solid/package.json
+++ b/packages/astro/e2e/fixtures/nested-in-solid/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-in-svelte/package.json b/packages/astro/e2e/fixtures/nested-in-svelte/package.json
index ea847e24b521..03a4c3e05bc9 100644
--- a/packages/astro/e2e/fixtures/nested-in-svelte/package.json
+++ b/packages/astro/e2e/fixtures/nested-in-svelte/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-in-vue/package.json b/packages/astro/e2e/fixtures/nested-in-vue/package.json
index 30a389574779..5a0d0273bd30 100644
--- a/packages/astro/e2e/fixtures/nested-in-vue/package.json
+++ b/packages/astro/e2e/fixtures/nested-in-vue/package.json
@@ -11,11 +11,11 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.37"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/e2e/fixtures/nested-recursive/package.json b/packages/astro/e2e/fixtures/nested-recursive/package.json
index 3376ef59616f..19366d54559f 100644
--- a/packages/astro/e2e/fixtures/nested-recursive/package.json
+++ b/packages/astro/e2e/fixtures/nested-recursive/package.json
@@ -11,12 +11,12 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.7.3",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "solid-js": "^1.4.3",
- "svelte": "^3.48.0",
- "vue": "^3.2.36"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
},
"scripts": {
"dev": "astro dev"
diff --git a/packages/astro/e2e/fixtures/preact-compat-component/package.json b/packages/astro/e2e/fixtures/preact-compat-component/package.json
index d83ad5292a90..c8092f549651 100644
--- a/packages/astro/e2e/fixtures/preact-compat-component/package.json
+++ b/packages/astro/e2e/fixtures/preact-compat-component/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.7.3"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/preact-component/package.json b/packages/astro/e2e/fixtures/preact-component/package.json
index 0d9b8402635f..8041f36088cc 100644
--- a/packages/astro/e2e/fixtures/preact-component/package.json
+++ b/packages/astro/e2e/fixtures/preact-component/package.json
@@ -3,9 +3,9 @@
"version": "0.0.0",
"private": true,
"dependencies": {
- "@astrojs/preact": "workspace:*",
"@astrojs/mdx": "workspace:*",
+ "@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.7.3"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/e2e/fixtures/solid-circular/package.json b/packages/astro/e2e/fixtures/solid-circular/package.json
index a354ec9ec165..7cca82635952 100644
--- a/packages/astro/e2e/fixtures/solid-circular/package.json
+++ b/packages/astro/e2e/fixtures/solid-circular/package.json
@@ -7,6 +7,6 @@
"astro": "workspace:*"
},
"devDependencies": {
- "solid-js": "^1.4.3"
+ "solid-js": "^1.7.6"
}
}
diff --git a/packages/astro/e2e/fixtures/solid-component/package.json b/packages/astro/e2e/fixtures/solid-component/package.json
index aee1bddab7e9..eaa2e84eb7e1 100644
--- a/packages/astro/e2e/fixtures/solid-component/package.json
+++ b/packages/astro/e2e/fixtures/solid-component/package.json
@@ -6,6 +6,6 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/solid-js": "workspace:*",
"astro": "workspace:*",
- "solid-js": "^1.5.5"
+ "solid-js": "^1.7.6"
}
}
diff --git a/packages/astro/e2e/fixtures/solid-recurse/package.json b/packages/astro/e2e/fixtures/solid-recurse/package.json
index 61016bf36996..c1f3f1444aad 100644
--- a/packages/astro/e2e/fixtures/solid-recurse/package.json
+++ b/packages/astro/e2e/fixtures/solid-recurse/package.json
@@ -7,6 +7,6 @@
"astro": "workspace:*"
},
"devDependencies": {
- "solid-js": "^1.4.3"
+ "solid-js": "^1.7.6"
}
}
diff --git a/packages/astro/e2e/fixtures/svelte-component/package.json b/packages/astro/e2e/fixtures/svelte-component/package.json
index 999a248c70f2..0756f3f1427b 100644
--- a/packages/astro/e2e/fixtures/svelte-component/package.json
+++ b/packages/astro/e2e/fixtures/svelte-component/package.json
@@ -3,9 +3,9 @@
"version": "0.0.0",
"private": true,
"dependencies": {
+ "@astrojs/mdx": "workspace:*",
"@astrojs/svelte": "workspace:*",
"astro": "workspace:*",
- "@astrojs/mdx": "workspace:*",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs
index 473be9666e1e..1db9d12bb664 100644
--- a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs
+++ b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs
@@ -1,9 +1,14 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
+import { fileURLToPath } from 'url';
// https://astro.build/config
export default defineConfig({
- integrations: [tailwind()],
+ integrations: [
+ tailwind({
+ configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
+ }),
+ ],
vite: {
build: {
assetsInlineLimit: 0,
diff --git a/packages/astro/e2e/fixtures/tailwindcss/package.json b/packages/astro/e2e/fixtures/tailwindcss/package.json
index 908c07915c4b..7e61c0d5c3be 100644
--- a/packages/astro/e2e/fixtures/tailwindcss/package.json
+++ b/packages/astro/e2e/fixtures/tailwindcss/package.json
@@ -6,7 +6,7 @@
"@astrojs/tailwind": "workspace:*",
"astro": "workspace:*",
"autoprefixer": "^10.4.14",
- "postcss": "^8.4.23",
+ "postcss": "^8.4.24",
"tailwindcss": "^3.3.2"
}
}
diff --git a/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js b/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js
deleted file mode 100644
index 7df5ecb39683..000000000000
--- a/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const path = require('path');
-module.exports = {
- plugins: {
- tailwindcss: {
- config: path.join(__dirname, 'tailwind.config.js'), // update this if your path differs!
- },
- autoprefixer: {}
- },
-};
diff --git a/packages/astro/e2e/fixtures/vue-component/package.json b/packages/astro/e2e/fixtures/vue-component/package.json
index 2e0c72a6b88c..81e7997830e3 100644
--- a/packages/astro/e2e/fixtures/vue-component/package.json
+++ b/packages/astro/e2e/fixtures/vue-component/package.json
@@ -6,6 +6,6 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
- "vue": "^3.2.39"
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 91bd00560873..e530f16bc4af 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -1,6 +1,6 @@
{
"name": "astro",
- "version": "2.6.3",
+ "version": "2.7.0",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module",
"author": "withastro",
@@ -91,12 +91,13 @@
"client.d.ts",
"client-base.d.ts",
"client-image.d.ts",
+ "content-types.template.d.ts",
+ "content-module.template.mjs",
"import-meta.d.ts",
"astro-jsx.d.ts",
"types.d.ts",
"README.md",
- "vendor",
- "src/content/template"
+ "vendor"
],
"scripts": {
"prebuild": "astro-scripts prebuild --to-string \"src/runtime/server/astro-island.ts\" \"src/runtime/client/{idle,load,media,only,visible}.ts\"",
@@ -112,35 +113,35 @@
"test:e2e:match": "playwright test -g"
},
"dependencies": {
- "@astrojs/compiler": "^1.4.0",
+ "@astrojs/compiler": "^1.5.0",
"@astrojs/internal-helpers": "^0.1.0",
"@astrojs/language-server": "^1.0.0",
"@astrojs/markdown-remark": "^2.2.1",
"@astrojs/telemetry": "^2.1.1",
"@astrojs/webapi": "^2.2.0",
- "@babel/core": "^7.21.8",
- "@babel/generator": "^7.18.2",
- "@babel/parser": "^7.18.4",
- "@babel/plugin-transform-react-jsx": "^7.17.12",
- "@babel/traverse": "^7.18.2",
- "@babel/types": "^7.21.5",
- "@types/babel__core": "^7.1.19",
+ "@babel/core": "^7.22.5",
+ "@babel/generator": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/plugin-transform-react-jsx": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5",
+ "@types/babel__core": "^7.20.1",
"@types/yargs-parser": "^21.0.0",
- "acorn": "^8.8.2",
+ "acorn": "^8.9.0",
"boxen": "^6.2.1",
"chokidar": "^3.5.3",
- "ci-info": "^3.3.1",
+ "ci-info": "^3.8.0",
"common-ancestor-path": "^1.0.1",
"cookie": "^0.5.0",
"debug": "^4.3.4",
- "deepmerge-ts": "^4.2.2",
+ "deepmerge-ts": "^4.3.0",
"devalue": "^4.3.2",
"diff": "^5.1.0",
- "es-module-lexer": "^1.1.0",
- "esbuild": "^0.17.18",
+ "es-module-lexer": "^1.3.0",
+ "esbuild": "^0.17.19",
"estree-walker": "3.0.0",
"execa": "^6.1.0",
- "fast-glob": "^3.2.11",
+ "fast-glob": "^3.2.12",
"github-slugger": "^2.0.0",
"gray-matter": "^4.0.3",
"html-escaper": "^3.0.3",
@@ -148,67 +149,65 @@
"kleur": "^4.1.4",
"magic-string": "^0.27.0",
"mime": "^3.0.0",
- "ora": "^6.1.0",
+ "ora": "^6.3.1",
"p-limit": "^4.0.0",
"path-to-regexp": "^6.2.1",
"preferred-pm": "^3.0.3",
"prompts": "^2.4.2",
"rehype": "^12.0.1",
- "semver": "^7.3.8",
+ "semver": "^7.5.3",
"server-destroy": "^1.0.1",
"shiki": "^0.14.1",
- "slash": "^4.0.0",
"string-width": "^5.1.2",
- "strip-ansi": "^7.0.1",
- "supports-esm": "^1.0.0",
+ "strip-ansi": "^7.1.0",
"tsconfig-resolver": "^3.0.1",
"typescript": "*",
- "unist-util-visit": "^4.1.0",
- "vfile": "^5.3.2",
- "vite": "^4.3.1",
+ "unist-util-visit": "^4.1.2",
+ "vfile": "^5.3.7",
+ "vite": "^4.3.9",
"vitefu": "^0.2.4",
- "yargs-parser": "^21.0.1",
+ "yargs-parser": "^21.1.1",
"zod": "^3.20.6"
},
"devDependencies": {
"@playwright/test": "^1.29.2",
"@types/babel__generator": "^7.6.4",
- "@types/babel__traverse": "^7.17.1",
- "@types/chai": "^4.3.1",
+ "@types/babel__traverse": "^7.20.1",
+ "@types/chai": "^4.3.5",
"@types/common-ancestor-path": "^1.0.0",
"@types/connect": "^3.4.35",
"@types/cookie": "^0.5.1",
- "@types/debug": "^4.1.7",
- "@types/diff": "^5.0.2",
+ "@types/debug": "^4.1.8",
+ "@types/diff": "^5.0.3",
"@types/estree": "^0.0.51",
"@types/hast": "^2.3.4",
"@types/html-escaper": "^3.0.0",
"@types/js-yaml": "^4.0.5",
"@types/mime": "^2.0.3",
"@types/mocha": "^9.1.1",
- "@types/prettier": "^2.6.3",
- "@types/prompts": "^2.0.14",
+ "@types/prettier": "^2.7.3",
+ "@types/prompts": "^2.4.4",
"@types/resolve": "^1.20.2",
"@types/rimraf": "^3.0.2",
"@types/send": "^0.17.1",
"@types/server-destroy": "^1.0.1",
"@types/unist": "^2.0.6",
"astro-scripts": "workspace:*",
- "chai": "^4.3.6",
- "cheerio": "^1.0.0-rc.11",
+ "chai": "^4.3.7",
+ "cheerio": "1.0.0-rc.12",
"eol": "^0.9.1",
- "memfs": "^3.4.7",
+ "memfs": "^3.5.3",
"mocha": "^9.2.2",
- "node-mocks-http": "^1.11.0",
+ "node-mocks-http": "^1.12.2",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"rehype-toc": "^3.0.2",
"remark-code-titles": "^0.1.2",
- "rollup": "^3.9.0",
- "sass": "^1.52.2",
+ "rollup": "^3.25.1",
+ "sass": "^1.63.4",
"sharp": "^0.32.1",
"srcset-parse": "^1.1.0",
- "undici": "^5.22.0",
+ "undici": "^5.22.1",
"unified": "^10.1.2"
},
"peerDependencies": {
diff --git a/packages/astro/performance/fixtures/md/package.json b/packages/astro/performance/fixtures/md/package.json
index ffc37be1e7ec..a5efef0ef295 100644
--- a/packages/astro/performance/fixtures/md/package.json
+++ b/packages/astro/performance/fixtures/md/package.json
@@ -16,8 +16,8 @@
"dependencies": {
"@astrojs/react": "workspace:*",
"@performance/utils": "workspace:*",
- "@types/react": "^18.0.21",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.13",
+ "@types/react-dom": "^18.2.6",
"astro": "workspace:*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
diff --git a/packages/astro/performance/fixtures/mdoc/package.json b/packages/astro/performance/fixtures/mdoc/package.json
index 032396900752..612bd78c2074 100644
--- a/packages/astro/performance/fixtures/mdoc/package.json
+++ b/packages/astro/performance/fixtures/mdoc/package.json
@@ -17,8 +17,8 @@
"@astrojs/markdoc": "workspace:*",
"@astrojs/react": "workspace:*",
"@performance/utils": "workspace:*",
- "@types/react": "^18.0.21",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.13",
+ "@types/react-dom": "^18.2.6",
"astro": "workspace:*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
diff --git a/packages/astro/performance/fixtures/mdx/package.json b/packages/astro/performance/fixtures/mdx/package.json
index da2045b9f27d..59d98b27f788 100644
--- a/packages/astro/performance/fixtures/mdx/package.json
+++ b/packages/astro/performance/fixtures/mdx/package.json
@@ -17,8 +17,8 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/react": "workspace:*",
"@performance/utils": "workspace:*",
- "@types/react": "^18.0.21",
- "@types/react-dom": "^18.0.6",
+ "@types/react": "^18.2.13",
+ "@types/react-dom": "^18.2.6",
"astro": "workspace:*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
diff --git a/packages/astro/performance/package.json b/packages/astro/performance/package.json
index 66193df49b4e..e09f291736c2 100644
--- a/packages/astro/performance/package.json
+++ b/packages/astro/performance/package.json
@@ -15,6 +15,6 @@
"cross-env": "^7.0.3",
"kleur": "^4.1.5",
"npm-run-all": "^4.1.5",
- "yargs-parser": "^21.0.1"
+ "yargs-parser": "^21.1.1"
}
}
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 59594446c110..43069aa1795d 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -335,6 +335,22 @@ type ServerConfig = {
* Set custom HTTP response headers to be sent in `astro dev` and `astro preview`.
*/
headers?: OutgoingHttpHeaders;
+
+ /**
+ * @name server.open
+ * @type {boolean}
+ * @default `false`
+ * @version 2.1.8
+ * @description
+ * Control whether the dev server should open in your browser window on startup.
+ *
+ * ```js
+ * {
+ * server: { open: true }
+ * }
+ * ```
+ */
+ open?: boolean;
};
export interface ViteUserConfig extends vite.UserConfig {
@@ -822,6 +838,30 @@ export interface AstroUserConfig {
* ```
*/
inlineStylesheets?: 'always' | 'auto' | 'never';
+
+ /**
+ * @docs
+ * @name build.split
+ * @type {boolean}
+ * @default {false}
+ * @version 2.7.0
+ * @description
+ * Defines how the SSR code should be bundled when built.
+ *
+ * When `split` is `true`, Astro will emit a file for each page.
+ * Each file emitted will render only one page. The pages will be emitted
+ * inside a `dist/pages/` directory, and the emitted files will keep the same file paths
+ * of the `src/pages` directory.
+ *
+ * ```js
+ * {
+ * build: {
+ * split: true
+ * }
+ * }
+ * ```
+ */
+ split?: boolean;
};
/**
@@ -843,7 +883,7 @@ export interface AstroUserConfig {
* ```js
* {
* // Example: Use the function syntax to customize based on command
- * server: (command) => ({ port: command === 'dev' ? 3000 : 4000 })
+ * server: ({ command }) => ({ port: command === 'dev' ? 3000 : 4000 })
* }
* ```
*/
@@ -878,6 +918,21 @@ export interface AstroUserConfig {
* ```
*/
+ /**
+ * @name server.open
+ * @type {boolean}
+ * @default `false`
+ * @version 2.1.8
+ * @description
+ * Control whether the dev server should open in your browser window on startup.
+ *
+ * ```js
+ * {
+ * server: { open: true }
+ * }
+ * ```
+ */
+
/**
* @docs
* @name server.headers
@@ -1238,6 +1293,7 @@ export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' |
export interface InjectedRoute {
pattern: string;
entryPoint: string;
+ prerender?: boolean;
}
export interface AstroConfig extends z.output {
// Public:
@@ -1793,7 +1849,14 @@ export interface AstroIntegration {
'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise;
'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise;
'astro:server:done'?: () => void | Promise;
- 'astro:build:ssr'?: (options: { manifest: SerializedSSRManifest }) => void | Promise;
+ 'astro:build:ssr'?: (options: {
+ manifest: SerializedSSRManifest;
+ /**
+ * This maps a {@link RouteData} to an {@link URL}, this URL represents
+ * the physical file you should import.
+ */
+ entryPoints: Map;
+ }) => void | Promise;
'astro:build:start'?: () => void | Promise;
'astro:build:setup'?: (options: {
vite: vite.InlineConfig;
diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts
index 9b8d6fc08b3c..b1e01b3e4e22 100644
--- a/packages/astro/src/assets/utils/emitAsset.ts
+++ b/packages/astro/src/assets/utils/emitAsset.ts
@@ -1,8 +1,7 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
-import slash from 'slash';
-import { prependForwardSlash } from '../../core/path.js';
+import { prependForwardSlash, slash } from '../../core/path.js';
import { imageMetadata, type Metadata } from './metadata.js';
export async function emitESMImage(
@@ -46,7 +45,6 @@ export async function emitESMImage(
}
function fileURLToNormalizedPath(filePath: URL): string {
- // Uses `slash` package instead of Vite's `normalizePath`
- // to avoid CJS bundling issues.
+ // Uses `slash` instead of Vite's `normalizePath` to avoid CJS bundling issues.
return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/');
}
diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts
index 3cee0765c293..631f30e1f19f 100644
--- a/packages/astro/src/content/utils.ts
+++ b/packages/astro/src/content/utils.ts
@@ -24,7 +24,7 @@ import { createImage } from './runtime-assets.js';
/**
* Amap from a collection + slug to the local file path.
* This is used internally to resolve entry imports when using `getEntry()`.
- * @see `src/content/virtual-mod.mjs`
+ * @see `content-module.template.mjs`
*/
export type ContentLookupMap = {
[collectionName: string]: { type: 'content' | 'data'; entries: { [lookupId: string]: string } };
@@ -432,7 +432,6 @@ export type ContentPaths = {
cacheDir: URL;
typesTemplate: URL;
virtualModTemplate: URL;
- virtualAssetsModTemplate: URL;
config: {
exists: boolean;
url: URL;
@@ -444,14 +443,13 @@ export function getContentPaths(
fs: typeof fsMod = fsMod
): ContentPaths {
const configStats = search(fs, srcDir);
- const templateDir = new URL('../../src/content/template/', import.meta.url);
+ const pkgBase = new URL('../../', import.meta.url);
return {
cacheDir: new URL('.astro/', root),
contentDir: new URL('./content/', srcDir),
assetsDir: new URL('./assets/', srcDir),
- typesTemplate: new URL('types.d.ts', templateDir),
- virtualModTemplate: new URL('virtual-mod.mjs', templateDir),
- virtualAssetsModTemplate: new URL('virtual-mod-assets.mjs', templateDir),
+ typesTemplate: new URL('content-types.template.d.ts', pkgBase),
+ virtualModTemplate: new URL('content-module.template.mjs', pkgBase),
config: configStats,
};
}
diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts
index aa2fec1797a5..98ad1ea76479 100644
--- a/packages/astro/src/content/vite-plugin-content-imports.ts
+++ b/packages/astro/src/content/vite-plugin-content-imports.ts
@@ -371,7 +371,6 @@ function stringifyEntryData(data: Record): string {
});
} else {
throw new AstroError({
- code: 99999,
message: 'Unexpected error processing content collection data.',
});
}
diff --git a/packages/astro/src/content/vite-plugin-content-virtual-mod.ts b/packages/astro/src/content/vite-plugin-content-virtual-mod.ts
index 33aae964d890..62ba612e962e 100644
--- a/packages/astro/src/content/vite-plugin-content-virtual-mod.ts
+++ b/packages/astro/src/content/vite-plugin-content-virtual-mod.ts
@@ -6,6 +6,7 @@ import pLimit from 'p-limit';
import type { Plugin } from 'vite';
import type { AstroSettings, ContentEntryType } from '../@types/astro.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
+import { appendForwardSlash } from '../core/path.js';
import { rootRelativePath } from '../core/util.js';
import { VIRTUAL_MODULE_ID } from './consts.js';
import {
@@ -94,7 +95,7 @@ export function astroContentVirtualModPlugin({
/**
* Generate a map from a collection + slug to the local file path.
* This is used internally to resolve entry imports when using `getEntry()`.
- * @see `src/content/virtual-mod.mjs`
+ * @see `content-module.template.mjs`
*/
export async function getStringifiedLookupMap({
contentPaths,
@@ -209,5 +210,10 @@ const UnexpectedLookupMapError = new AstroError({
function globWithUnderscoresIgnored(relContentDir: string, exts: string[]): string[] {
const extGlob = getExtGlob(exts);
- return [`${relContentDir}/**/*${extGlob}`, `!**/_*/**${extGlob}`, `!**/_*${extGlob}`];
+ const contentDir = appendForwardSlash(relContentDir);
+ return [
+ `${contentDir}**/*${extGlob}`,
+ `!${contentDir}_*/**${extGlob}`,
+ `!${contentDir}_*${extGlob}`,
+ ];
}
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 56d22eafcdf2..ae0c3fb00e78 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -1,13 +1,12 @@
+import mime from 'mime';
import type {
EndpointHandler,
ManifestData,
MiddlewareResponseHandler,
RouteData,
SSRElement,
+ SSRManifest,
} from '../../@types/astro';
-import type { RouteInfo, SSRManifest as Manifest } from './types';
-
-import mime from 'mime';
import type { SinglePageBuiltModule } from '../build/types';
import { attachToResponse, getSetCookiesFromResponse } from '../cookies/index.js';
import { callEndpoint, createAPIContext } from '../endpoint/index.js';
@@ -29,6 +28,7 @@ import {
createStylesheetElementSet,
} from '../render/ssr-element.js';
import { matchRoute } from '../routing/match.js';
+import type { RouteInfo } from './types';
export { deserializeManifest } from './common.js';
const clientLocalsSymbol = Symbol.for('astro.locals');
@@ -41,7 +41,7 @@ export interface MatchOptions {
export class App {
#env: Environment;
- #manifest: Manifest;
+ #manifest: SSRManifest;
#manifestData: ManifestData;
#routeDataToRouteInfo: Map;
#encoder = new TextEncoder();
@@ -52,7 +52,7 @@ export class App {
#base: string;
#baseWithoutTrailingSlash: string;
- constructor(manifest: Manifest, streaming = true) {
+ constructor(manifest: SSRManifest, streaming = true) {
this.#manifest = manifest;
this.#manifestData = {
routes: manifest.routes.map((route) => route.routeData),
@@ -115,7 +115,7 @@ export class App {
return undefined;
}
}
- async render(request: Request, routeData?: RouteData): Promise {
+ async render(request: Request, routeData?: RouteData, locals?: object): Promise {
let defaultStatus = 200;
if (!routeData) {
routeData = this.match(request);
@@ -131,7 +131,7 @@ export class App {
}
}
- Reflect.set(request, clientLocalsSymbol, {});
+ Reflect.set(request, clientLocalsSymbol, locals ?? {});
// Use the 404 status code for 404.astro components
if (routeData.route === '/404') {
@@ -175,14 +175,23 @@ export class App {
if (route.type === 'redirect') {
return RedirectSinglePageBuiltModule;
} else {
- const importComponentInstance = this.#manifest.pageMap.get(route.component);
- if (!importComponentInstance) {
+ if (this.#manifest.pageMap) {
+ const importComponentInstance = this.#manifest.pageMap.get(route.component);
+ if (!importComponentInstance) {
+ throw new Error(
+ `Unexpectedly unable to find a component instance for route ${route.route}`
+ );
+ }
+ const pageModule = await importComponentInstance();
+ return pageModule;
+ } else if (this.#manifest.pageModule) {
+ const importComponentInstance = this.#manifest.pageModule;
+ return importComponentInstance;
+ } else {
throw new Error(
- `Unexpectedly unable to find a component instance for route ${route.route}`
+ "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue."
);
}
- const built = await importComponentInstance();
- return built;
}
}
@@ -236,15 +245,14 @@ export class App {
site: this.#env.site,
adapterName: this.#env.adapterName,
});
- const onRequest = page.middleware?.onRequest;
let response;
- if (onRequest) {
+ if (page.onRequest) {
response = await callMiddleware(
this.#env.logging,
- onRequest as MiddlewareResponseHandler,
+ page.onRequest as MiddlewareResponseHandler,
apiContext,
() => {
- return renderPage({ mod, renderContext, env: this.#env, apiContext });
+ return renderPage({ mod, renderContext, env: this.#env, cookies: apiContext.cookies });
}
);
} else {
@@ -252,7 +260,7 @@ export class App {
mod,
renderContext,
env: this.#env,
- apiContext,
+ cookies: apiContext.cookies,
});
}
Reflect.set(request, responseSentSymbol, true);
@@ -287,7 +295,7 @@ export class App {
mod: handler as any,
});
- const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.middleware);
+ const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.onRequest);
if (result.type === 'response') {
if (result.response.headers.get('X-Astro-Response') === 'Not-Found') {
diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts
index 6bd2677a79e0..40b7b4e7ce6e 100644
--- a/packages/astro/src/core/app/node.ts
+++ b/packages/astro/src/core/app/node.ts
@@ -41,11 +41,12 @@ export class NodeApp extends App {
match(req: NodeIncomingMessage | Request, opts: MatchOptions = {}) {
return super.match(req instanceof Request ? req : createRequestFromNodeRequest(req), opts);
}
- render(req: NodeIncomingMessage | Request, routeData?: RouteData) {
+ render(req: NodeIncomingMessage | Request, routeData?: RouteData, locals?: object) {
if (typeof req.body === 'string' && req.body.length > 0) {
return super.render(
req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(req.body)),
- routeData
+ routeData,
+ locals
);
}
@@ -54,7 +55,8 @@ export class NodeApp extends App {
req instanceof Request
? req
: createRequestFromNodeRequest(req, Buffer.from(JSON.stringify(req.body))),
- routeData
+ routeData,
+ locals
);
}
@@ -75,13 +77,15 @@ export class NodeApp extends App {
return reqBodyComplete.then(() => {
return super.render(
req instanceof Request ? req : createRequestFromNodeRequest(req, body),
- routeData
+ routeData,
+ locals
);
});
}
return super.render(
req instanceof Request ? req : createRequestFromNodeRequest(req),
- routeData
+ routeData,
+ locals
);
}
}
diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts
index 1283f1a10f26..9af15bf50252 100644
--- a/packages/astro/src/core/app/types.ts
+++ b/packages/astro/src/core/app/types.ts
@@ -30,16 +30,16 @@ export interface RouteInfo {
export type SerializedRouteInfo = Omit & {
routeData: SerializedRouteData;
};
-type ImportComponentInstance = () => Promise;
-export interface SSRManifest {
+export type ImportComponentInstance = () => Promise;
+
+export type SSRManifest = {
adapterName: string;
routes: RouteInfo[];
site?: string;
base?: string;
assetsPrefix?: string;
markdown: MarkdownRenderingOptions;
- pageMap: Map;
renderers: SSRLoadedRenderer[];
/**
* Map of directive name (e.g. `load`) to the directive script code
@@ -48,7 +48,9 @@ export interface SSRManifest {
entryModules: Record;
assets: Set;
componentMetadata: SSRResult['componentMetadata'];
-}
+ pageModule?: SinglePageBuiltModule;
+ pageMap?: Map;
+};
export type SerializedSSRManifest = Omit<
SSRManifest,
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index c1fd34654a10..551f7afa8395 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -5,13 +5,13 @@ import type { OutputAsset, OutputChunk } from 'rollup';
import { fileURLToPath } from 'url';
import type {
AstroConfig,
- AstroMiddlewareInstance,
AstroSettings,
ComponentInstance,
EndpointHandler,
EndpointOutput,
GetStaticPathsItem,
ImageTransform,
+ MiddlewareHandler,
MiddlewareResponseHandler,
RouteData,
RouteType,
@@ -29,6 +29,7 @@ import {
type BuildInternals,
} from '../../core/build/internal.js';
import {
+ isRelativePath,
prependForwardSlash,
removeLeadingForwardSlash,
removeTrailingForwardSlash,
@@ -228,7 +229,7 @@ async function generatePage(
.reduce(mergeInlineCss, []);
const pageModulePromise = ssrEntry.page;
- const middleware = ssrEntry.middleware;
+ const onRequest = ssrEntry.onRequest;
if (!pageModulePromise) {
throw new Error(
@@ -252,14 +253,18 @@ async function generatePage(
};
const icon = pageData.route.type === 'page' ? green('βΆ') : magenta('Ξ»');
- info(opts.logging, null, `${icon} ${pageData.route.component}`);
+ if (isRelativePath(pageData.route.component)) {
+ info(opts.logging, null, `${icon} ${pageData.route.route}`);
+ } else {
+ info(opts.logging, null, `${icon} ${pageData.route.component}`);
+ }
// Get paths for the route, calling getStaticPaths if needed.
const paths = await getPathsForRoute(pageData, pageModule, opts, builtPaths);
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
- await generatePath(path, opts, generationOptions, middleware);
+ await generatePath(path, opts, generationOptions, onRequest);
const timeEnd = performance.now();
const timeChange = getTimeStat(timeStart, timeEnd);
const timeIncrease = `(+${timeChange})`;
@@ -443,7 +448,7 @@ async function generatePath(
pathname: string,
opts: StaticBuildOptions,
gopts: GeneratePathOptions,
- middleware?: AstroMiddlewareInstance
+ onRequest?: MiddlewareHandler
) {
const { settings, logging, origin, routeCache } = opts;
const {
@@ -564,7 +569,7 @@ async function generatePath(
env,
renderContext,
logging,
- middleware as AstroMiddlewareInstance
+ onRequest as MiddlewareHandler
);
if (result.type === 'response') {
@@ -588,7 +593,6 @@ async function generatePath(
adapterName: env.adapterName,
});
- const onRequest = middleware?.onRequest;
if (onRequest) {
response = await callMiddleware(
env.logging,
@@ -599,8 +603,8 @@ async function generatePath(
mod,
renderContext,
env,
- apiContext,
isCompressHTML: settings.config.compressHTML,
+ cookies: apiContext.cookies,
});
}
);
@@ -609,8 +613,8 @@ async function generatePath(
mod,
renderContext,
env,
- apiContext,
isCompressHTML: settings.config.compressHTML,
+ cookies: apiContext.cookies,
});
}
} catch (err) {
diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts
index 4cf40cb9ad83..8c7da07d4319 100644
--- a/packages/astro/src/core/build/internal.ts
+++ b/packages/astro/src/core/build/internal.ts
@@ -1,13 +1,10 @@
import type { Rollup } from 'vite';
-import type { SSRResult } from '../../@types/astro';
+import type { RouteData, SSRResult } from '../../@types/astro';
import type { PageOptions } from '../../vite-plugin-astro/types';
import { prependForwardSlash, removeFileExtension } from '../path.js';
import { viteID } from '../util.js';
-import {
- ASTRO_PAGE_EXTENSION_POST_PATTERN,
- ASTRO_PAGE_MODULE_ID,
- getVirtualModulePageIdFromPath,
-} from './plugins/plugin-pages.js';
+import { ASTRO_PAGE_MODULE_ID, getVirtualModulePageIdFromPath } from './plugins/plugin-pages.js';
+import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js';
import type { PageBuildData, StylesheetAsset, ViteID } from './types';
export interface BuildInternals {
@@ -84,6 +81,8 @@ export interface BuildInternals {
staticFiles: Set;
// The SSR entry chunk. Kept in internals to share between ssr/client build steps
ssrEntryChunk?: Rollup.OutputChunk;
+ entryPoints: Map;
+ ssrSplitEntryChunks: Map;
componentMetadata: SSRResult['componentMetadata'];
}
@@ -114,6 +113,8 @@ export function createBuildInternals(): BuildInternals {
discoveredScripts: new Set(),
staticFiles: new Set(),
componentMetadata: new Map(),
+ ssrSplitEntryChunks: new Map(),
+ entryPoints: new Map(),
};
}
diff --git a/packages/astro/src/core/build/plugins/README.md b/packages/astro/src/core/build/plugins/README.md
index 32ac8c448f6f..1451581631f1 100644
--- a/packages/astro/src/core/build/plugins/README.md
+++ b/packages/astro/src/core/build/plugins/README.md
@@ -2,12 +2,11 @@
This file serves as developer documentation to explain how the internal plugins work
-
## `plugin-middleware`
This plugin is responsible to retrieve the `src/middleware.{ts.js}` file and emit an entry point during the SSR build.
-The final file is emitted only if the user has the middleware file. The final name of the file is `middleware.mjs`.
+The final file is emitted only if the user has the middleware file. The final name of the file is `middleware.mjs`.
This is **not** a virtual module. The plugin will try to resolve the physical file.
@@ -20,7 +19,12 @@ The emitted file is called `renderers.mjs`.
The emitted file has content similar to:
```js
-const renderers = [Object.assign({"name":"astro:jsx","serverEntrypoint":"astro/jsx/server.js","jsxImportSource":"astro"}, { ssr: server_default }),];
+const renderers = [
+ Object.assign(
+ { name: 'astro:jsx', serverEntrypoint: 'astro/jsx/server.js', jsxImportSource: 'astro' },
+ { ssr: server_default }
+ ),
+];
export { renderers };
```
@@ -32,19 +36,20 @@ This plugin is responsible to collect all pages inside an Astro application, and
This plugin **will emit code** only when building a static site.
In order to achieve that, the plugin emits these pages as **virtual modules**. Doing so allows us to bypass:
+
- rollup resolution of the files
- possible plugins that get triggered when the name of the module has an extension e.g. `.astro`
The plugin does the following operations:
+
- loop through all the pages and collects their paths;
- with each path, we create a new [string](#plugin-pages-mapping-resolution) that will serve and virtual module for that particular page
- when resolving the page, we check if the `id` of the module starts with `@astro-page`
- once the module is resolved, we emit [the code of the module](#plugin-pages-code-generation)
-
### `plugin pages` mapping resolution
-The mapping is as follows:
+The mapping is as follows:
```
src/pages/index.astro => @astro-page:src/pages/index@_@astro
@@ -53,14 +58,13 @@ src/pages/index.astro => @astro-page:src/pages/index@_@astro
1. We add a fixed prefix, which is used as virtual module naming convention;
2. We replace the dot that belongs extension with an arbitrary string.
-This kind of patterns will then allow us to retrieve the path physical path of the
+This kind of patterns will then allow us to retrieve the path physical path of the
file back from that string. This is important for the [code generation](#plugin-pages-code-generation)
-
-
### `plugin pages` code generation
When generating the code of the page, we will import and export the following modules:
+
- the `renderers.mjs`
- the `middleware.mjs`
- the page, via dynamic import
@@ -79,6 +83,7 @@ export { middleware, page };
```
If we have a `pages/` folder that looks like this:
+
```
βββ blog
β βββ first.astro
@@ -89,8 +94,9 @@ If we have a `pages/` folder that looks like this:
βββ second.astro
```
-The emitted entry points will be stored inside a `pages/` folder, and they
+The emitted entry points will be stored inside a `pages/` folder, and they
will look like this:
+
```
βββ _astro
β βββ first.132e69e0.css
@@ -117,7 +123,7 @@ will look like this:
βββ renderers.mjs
```
-Of course, all these files will be deleted by Astro at the end build.
+Of course, all these files will be deleted by Astro at the end build.
## `plugin-ssr` (WIP)
@@ -130,15 +136,14 @@ The plugin will collect all the [virtual pages](#plugin-pages) and create
a JavaScript `Map`. These map will look like this:
```js
-const _page$0 = () => import("../chunks/.mjs")
-const _page$1 = () => import("../chunks/.mjs")
+const _page$0 = () => import('../chunks/.mjs');
+const _page$1 = () => import('../chunks/.mjs');
const pageMap = new Map([
- ["src/pages/index.astro", _page$0],
- ["src/pages/about.astro", _page$1],
-])
+ ['src/pages/index.astro', _page$0],
+ ['src/pages/about.astro', _page$1],
+]);
```
It will also import the [`renderers`](#plugin-renderers) virtual module
and the [`middleware`](#plugin-middleware) virtual module.
-
diff --git a/packages/astro/src/core/build/plugins/index.ts b/packages/astro/src/core/build/plugins/index.ts
index f6fcacfb1b7d..4563bb6964d7 100644
--- a/packages/astro/src/core/build/plugins/index.ts
+++ b/packages/astro/src/core/build/plugins/index.ts
@@ -11,7 +11,7 @@ import { pluginMiddleware } from './plugin-middleware.js';
import { pluginPages } from './plugin-pages.js';
import { pluginPrerender } from './plugin-prerender.js';
import { pluginRenderers } from './plugin-renderers.js';
-import { pluginSSR } from './plugin-ssr.js';
+import { pluginSSR, pluginSSRSplit } from './plugin-ssr.js';
export function registerAllPlugins({ internals, options, register }: AstroBuildPluginContainer) {
register(pluginComponentEntry(internals));
@@ -27,4 +27,5 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP
register(astroConfigBuildPlugin(options, internals));
register(pluginHoistedScripts(options, internals));
register(pluginSSR(options, internals));
+ register(pluginSSRSplit(options, internals));
}
diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts
index 6bd63b44f3a0..7e3ea8cb9d9a 100644
--- a/packages/astro/src/core/build/plugins/plugin-middleware.ts
+++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts
@@ -1,11 +1,14 @@
import type { Plugin as VitePlugin } from 'vite';
import { MIDDLEWARE_PATH_SEGMENT_NAME } from '../../constants.js';
+import { addRollupInput } from '../add-rollup-input.js';
import type { BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin';
import type { StaticBuildOptions } from '../types';
export const MIDDLEWARE_MODULE_ID = '@astro-middleware';
+const EMPTY_MIDDLEWARE = '\0empty-middleware';
+
export function vitePluginMiddleware(
opts: StaticBuildOptions,
_internals: BuildInternals
@@ -13,6 +16,10 @@ export function vitePluginMiddleware(
return {
name: '@astro/plugin-middleware',
+ options(options) {
+ return addRollupInput(options, [MIDDLEWARE_MODULE_ID]);
+ },
+
async resolveId(id) {
if (id === MIDDLEWARE_MODULE_ID) {
const middlewareId = await this.resolve(
@@ -20,8 +27,19 @@ export function vitePluginMiddleware(
);
if (middlewareId) {
return middlewareId.id;
+ } else {
+ return EMPTY_MIDDLEWARE;
}
}
+ if (id === EMPTY_MIDDLEWARE) {
+ return EMPTY_MIDDLEWARE;
+ }
+ },
+
+ load(id) {
+ if (id === EMPTY_MIDDLEWARE) {
+ return 'export const onRequest = undefined';
+ }
},
};
}
diff --git a/packages/astro/src/core/build/plugins/plugin-pages.ts b/packages/astro/src/core/build/plugins/plugin-pages.ts
index f767a9c5bd79..c40449a39e2e 100644
--- a/packages/astro/src/core/build/plugins/plugin-pages.ts
+++ b/packages/astro/src/core/build/plugins/plugin-pages.ts
@@ -7,12 +7,10 @@ import type { AstroBuildPlugin } from '../plugin';
import type { StaticBuildOptions } from '../types';
import { MIDDLEWARE_MODULE_ID } from './plugin-middleware.js';
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
+import { ASTRO_PAGE_EXTENSION_POST_PATTERN, getPathFromVirtualModulePageName } from './util.js';
export const ASTRO_PAGE_MODULE_ID = '@astro-page:';
-export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0@astro-page:';
-
-// This is an arbitrary string that we are going to replace the dot of the extension
-export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@';
+export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0' + ASTRO_PAGE_MODULE_ID;
/**
* 1. We add a fixed prefix, which is used as virtual module naming convention;
@@ -64,13 +62,8 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
if (id.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) {
const imports: string[] = [];
const exports: string[] = [];
-
- // we remove the module name prefix from id, this will result into a string that will start with "src/..."
- const pageName = id.slice(ASTRO_PAGE_RESOLVED_MODULE_ID.length);
- // We replaced the `.` of the extension with ASTRO_PAGE_EXTENSION_POST_PATTERN, let's replace it back
- const pageData = internals.pagesByComponent.get(
- `${pageName.replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.')}`
- );
+ const pageName = getPathFromVirtualModulePageName(ASTRO_PAGE_RESOLVED_MODULE_ID, id);
+ const pageData = internals.pagesByComponent.get(pageName);
if (pageData) {
const resolvedPage = await this.resolve(pageData.moduleSpecifier);
if (resolvedPage) {
@@ -82,8 +75,8 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID);
if (middlewareModule) {
- imports.push(`import * as middleware from "${middlewareModule.id}";`);
- exports.push(`export { middleware };`);
+ imports.push(`import { onRequest } from "${middlewareModule.id}";`);
+ exports.push(`export { onRequest };`);
}
return `${imports.join('\n')}${exports.join('\n')}`;
diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts
index 3c2825e4c63c..486c314340b7 100644
--- a/packages/astro/src/core/build/plugins/plugin-ssr.ts
+++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts
@@ -1,7 +1,8 @@
import glob from 'fast-glob';
-import { fileURLToPath } from 'url';
+import { join } from 'node:path';
+import { fileURLToPath, pathToFileURL } from 'node:url';
import type { Plugin as VitePlugin } from 'vite';
-import type { AstroAdapter } from '../../../@types/astro';
+import type { AstroAdapter, AstroConfig } from '../../../@types/astro';
import { runHookBuildSsr } from '../../../integrations/index.js';
import { isServerLikeOutput } from '../../../prerender/utils.js';
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js';
@@ -13,9 +14,10 @@ import { addRollupInput } from '../add-rollup-input.js';
import { getOutFile, getOutFolder } from '../common.js';
import { cssOrder, mergeInlineCss, type BuildInternals } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin';
-import type { StaticBuildOptions } from '../types';
-import { getVirtualModulePageNameFromPath } from './plugin-pages.js';
+import type { OutputChunk, StaticBuildOptions } from '../types';
+import { ASTRO_PAGE_MODULE_ID } from './plugin-pages.js';
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
+import { getPathFromVirtualModulePageName, getVirtualModulePageNameFromPath } from './util.js';
export const SSR_VIRTUAL_MODULE_ID = '@astrojs-ssr-virtual-entry';
const RESOLVED_SSR_VIRTUAL_MODULE_ID = '\0' + SSR_VIRTUAL_MODULE_ID;
@@ -28,7 +30,7 @@ function vitePluginSSR(
options: StaticBuildOptions
): VitePlugin {
return {
- name: '@astrojs/vite-plugin-astro-ssr',
+ name: '@astrojs/vite-plugin-astro-ssr-server',
enforce: 'post',
options(opts) {
return addRollupInput(opts, [SSR_VIRTUAL_MODULE_ID]);
@@ -54,7 +56,7 @@ function vitePluginSSR(
if (routeIsRedirect(pageData.route)) {
continue;
}
- const virtualModuleName = getVirtualModulePageNameFromPath(path);
+ const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
let module = await this.resolve(virtualModuleName);
if (module) {
const variable = `_page${i}`;
@@ -71,12 +73,226 @@ function vitePluginSSR(
contents.push(`const pageMap = new Map([${pageMap.join(',')}]);`);
exports.push(`export { pageMap }`);
- const content = `import * as adapter from '${adapter.serverEntrypoint}';
+ const ssrCode = generateSSRCode(options.settings.config, adapter);
+ imports.push(...ssrCode.imports);
+ contents.push(...ssrCode.contents);
+ return `${imports.join('\n')}${contents.join('\n')}${exports.join('\n')}`;
+ }
+ return void 0;
+ },
+ async generateBundle(_opts, bundle) {
+ // Add assets from this SSR chunk as well.
+ for (const [_chunkName, chunk] of Object.entries(bundle)) {
+ if (chunk.type === 'asset') {
+ internals.staticFiles.add(chunk.fileName);
+ }
+ }
+
+ for (const [chunkName, chunk] of Object.entries(bundle)) {
+ if (chunk.type === 'asset') {
+ continue;
+ }
+ if (chunk.modules[RESOLVED_SSR_VIRTUAL_MODULE_ID]) {
+ internals.ssrEntryChunk = chunk;
+ delete bundle[chunkName];
+ }
+ }
+ },
+ };
+}
+
+export function pluginSSR(
+ options: StaticBuildOptions,
+ internals: BuildInternals
+): AstroBuildPlugin {
+ const ssr = isServerLikeOutput(options.settings.config);
+ return {
+ build: 'ssr',
+ hooks: {
+ 'build:before': () => {
+ let vitePlugin =
+ ssr && !options.settings.config.build.split
+ ? vitePluginSSR(internals, options.settings.adapter!, options)
+ : undefined;
+
+ return {
+ enforce: 'after-user-plugins',
+ vitePlugin,
+ };
+ },
+ 'build:post': async ({ mutate }) => {
+ if (!ssr) {
+ return;
+ }
+
+ if (options.settings.config.build.split) {
+ return;
+ }
+
+ if (!internals.ssrEntryChunk) {
+ throw new Error(`Did not generate an entry chunk for SSR`);
+ }
+ // Mutate the filename
+ internals.ssrEntryChunk.fileName = options.settings.config.build.serverEntry;
+
+ const manifest = await createManifest(options, internals);
+ await runHookBuildSsr({
+ config: options.settings.config,
+ manifest,
+ logging: options.logging,
+ entryPoints: internals.entryPoints,
+ });
+ const code = injectManifest(manifest, internals.ssrEntryChunk);
+ mutate(internals.ssrEntryChunk, 'server', code);
+ },
+ },
+ };
+}
+
+export const SPLIT_MODULE_ID = '@astro-page-split:';
+export const RESOLVED_SPLIT_MODULE_ID = '\0@astro-page-split:';
+
+function vitePluginSSRSplit(
+ internals: BuildInternals,
+ adapter: AstroAdapter,
+ options: StaticBuildOptions
+): VitePlugin {
+ return {
+ name: '@astrojs/vite-plugin-astro-ssr-split',
+ enforce: 'post',
+ options(opts) {
+ if (options.settings.config.build.split) {
+ const inputs: Set = new Set();
+
+ for (const path of Object.keys(options.allPages)) {
+ inputs.add(getVirtualModulePageNameFromPath(SPLIT_MODULE_ID, path));
+ }
+
+ return addRollupInput(opts, Array.from(inputs));
+ }
+ },
+ resolveId(id) {
+ if (id.startsWith(SPLIT_MODULE_ID)) {
+ return '\0' + id;
+ }
+ },
+ async load(id) {
+ if (id.startsWith(RESOLVED_SPLIT_MODULE_ID)) {
+ const {
+ settings: { config },
+ allPages,
+ } = options;
+ const imports: string[] = [];
+ const contents: string[] = [];
+ const exports: string[] = [];
+
+ const path = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, id);
+ const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
+ let module = await this.resolve(virtualModuleName);
+ if (module) {
+ // we need to use the non-resolved ID in order to resolve correctly the virtual module
+ imports.push(`import * as pageModule from "${virtualModuleName}";`);
+ }
+
+ const ssrCode = generateSSRCode(options.settings.config, adapter);
+ imports.push(...ssrCode.imports);
+ contents.push(...ssrCode.contents);
+
+ return `${imports.join('\n')}${contents.join('\n')}${exports.join('\n')}`;
+ }
+ return void 0;
+ },
+ async generateBundle(_opts, bundle) {
+ // Add assets from this SSR chunk as well.
+ for (const [_chunkName, chunk] of Object.entries(bundle)) {
+ if (chunk.type === 'asset') {
+ internals.staticFiles.add(chunk.fileName);
+ }
+ }
+
+ for (const [chunkName, chunk] of Object.entries(bundle)) {
+ if (chunk.type === 'asset') {
+ continue;
+ }
+ let shouldDeleteBundle = false;
+ for (const moduleKey of Object.keys(chunk.modules)) {
+ if (moduleKey.startsWith(RESOLVED_SPLIT_MODULE_ID)) {
+ internals.ssrSplitEntryChunks.set(moduleKey, chunk);
+ storeEntryPoint(moduleKey, options, internals, chunk.fileName);
+ shouldDeleteBundle = true;
+ }
+ }
+ if (shouldDeleteBundle) {
+ delete bundle[chunkName];
+ }
+ }
+ },
+ };
+}
+
+export function pluginSSRSplit(
+ options: StaticBuildOptions,
+ internals: BuildInternals
+): AstroBuildPlugin {
+ const ssr = isServerLikeOutput(options.settings.config);
+ return {
+ build: 'ssr',
+ hooks: {
+ 'build:before': () => {
+ let vitePlugin =
+ ssr && options.settings.config.build.split
+ ? vitePluginSSRSplit(internals, options.settings.adapter!, options)
+ : undefined;
+
+ return {
+ enforce: 'after-user-plugins',
+ vitePlugin,
+ };
+ },
+ 'build:post': async ({ mutate }) => {
+ if (!ssr) {
+ return;
+ }
+ if (!options.settings.config.build.split) {
+ return;
+ }
+
+ if (internals.ssrSplitEntryChunks.size === 0) {
+ throw new Error(`Did not generate an entry chunk for SSR serverless`);
+ }
+
+ const manifest = await createManifest(options, internals);
+ await runHookBuildSsr({
+ config: options.settings.config,
+ manifest,
+ logging: options.logging,
+ entryPoints: internals.entryPoints,
+ });
+ for (const [moduleName, chunk] of internals.ssrSplitEntryChunks) {
+ const code = injectManifest(manifest, chunk);
+ mutate(chunk, 'server', code);
+ }
+ },
+ },
+ };
+}
+
+function generateSSRCode(config: AstroConfig, adapter: AstroAdapter) {
+ const imports: string[] = [];
+ const contents: string[] = [];
+ let pageMap;
+ if (config.build.split) {
+ pageMap = 'pageModule';
+ } else {
+ pageMap = 'pageMap';
+ }
+
+ contents.push(`import * as adapter from '${adapter.serverEntrypoint}';
import { renderers } from '${RENDERERS_MODULE_ID}';
import { deserializeManifest as _deserializeManifest } from 'astro/app';
import { _privateSetManifestDontUseThis } from 'astro:ssr-manifest';
const _manifest = Object.assign(_deserializeManifest('${manifestReplace}'), {
- pageMap,
+ ${pageMap},
renderers,
});
_privateSetManifestDontUseThis(_manifest);
@@ -101,41 +317,45 @@ export { _default as default };`;
const _start = 'start';
if(_start in adapter) {
adapter[_start](_manifest, _args);
-}`;
- return `${imports.join('\n')}${contents.join('\n')}${content}${exports.join('\n')}`;
- }
- return void 0;
- },
- async generateBundle(_opts, bundle) {
- // Add assets from this SSR chunk as well.
- for (const [_chunkName, chunk] of Object.entries(bundle)) {
- if (chunk.type === 'asset') {
- internals.staticFiles.add(chunk.fileName);
- }
- }
-
- for (const [chunkName, chunk] of Object.entries(bundle)) {
- if (chunk.type === 'asset') {
- continue;
- }
- if (chunk.modules[RESOLVED_SSR_VIRTUAL_MODULE_ID]) {
- internals.ssrEntryChunk = chunk;
- delete bundle[chunkName];
- }
- }
- },
+}`);
+ return {
+ imports,
+ contents,
};
}
-export async function injectManifest(buildOpts: StaticBuildOptions, internals: BuildInternals) {
- if (!internals.ssrEntryChunk) {
- throw new Error(`Did not generate an entry chunk for SSR`);
+/**
+ * It injects the manifest in the given output rollup chunk. It returns the new emitted code
+ * @param buildOpts
+ * @param internals
+ * @param chunk
+ */
+export function injectManifest(manifest: SerializedSSRManifest, chunk: Readonly) {
+ const code = chunk.code;
+
+ return code.replace(replaceExp, () => {
+ return JSON.stringify(manifest);
+ });
+}
+
+export async function createManifest(
+ buildOpts: StaticBuildOptions,
+ internals: BuildInternals
+): Promise {
+ if (buildOpts.settings.config.build.split) {
+ if (internals.ssrSplitEntryChunks.size === 0) {
+ throw new Error(`Did not generate an entry chunk for SSR in serverless mode`);
+ }
+ } else {
+ if (!internals.ssrEntryChunk) {
+ throw new Error(`Did not generate an entry chunk for SSR`);
+ }
}
// Add assets from the client build.
const clientStatics = new Set(
await glob('**/*', {
- cwd: fileURLToPath(buildOpts.buildConfig.client),
+ cwd: fileURLToPath(buildOpts.settings.config.build.client),
})
);
for (const file of clientStatics) {
@@ -143,19 +363,29 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B
}
const staticFiles = internals.staticFiles;
- const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles));
- await runHookBuildSsr({
- config: buildOpts.settings.config,
- manifest,
- logging: buildOpts.logging,
- });
-
- const chunk = internals.ssrEntryChunk;
- const code = chunk.code;
+ return buildManifest(buildOpts, internals, Array.from(staticFiles));
+}
- return code.replace(replaceExp, () => {
- return JSON.stringify(manifest);
- });
+/**
+ * Because we delete the bundle from rollup at the end of this function,
+ * we can't use `writeBundle` hook to get the final file name of the entry point written on disk.
+ * We use this hook instead.
+ *
+ * We retrieve the {@link RouteData} that belongs the current moduleKey
+ */
+function storeEntryPoint(
+ moduleKey: string,
+ options: StaticBuildOptions,
+ internals: BuildInternals,
+ fileName: string
+) {
+ const componentPath = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, moduleKey);
+ for (const [page, pageData] of Object.entries(options.allPages)) {
+ if (componentPath == page) {
+ const publicPath = fileURLToPath(options.settings.config.outDir);
+ internals.entryPoints.set(pageData.route, pathToFileURL(join(publicPath, fileName)));
+ }
+ }
}
function buildManifest(
@@ -254,7 +484,6 @@ function buildManifest(
base: settings.config.base,
assetsPrefix: settings.config.build.assetsPrefix,
markdown: settings.config.markdown,
- pageMap: null as any,
componentMetadata: Array.from(internals.componentMetadata),
renderers: [],
clientDirectives: Array.from(settings.clientDirectives),
@@ -264,39 +493,3 @@ function buildManifest(
return ssrManifest;
}
-
-export function pluginSSR(
- options: StaticBuildOptions,
- internals: BuildInternals
-): AstroBuildPlugin {
- const ssr = isServerLikeOutput(options.settings.config);
- return {
- build: 'ssr',
- hooks: {
- 'build:before': () => {
- let vitePlugin = ssr
- ? vitePluginSSR(internals, options.settings.adapter!, options)
- : undefined;
-
- return {
- enforce: 'after-user-plugins',
- vitePlugin,
- };
- },
- 'build:post': async ({ mutate }) => {
- if (!ssr) {
- return;
- }
-
- if (!internals.ssrEntryChunk) {
- throw new Error(`Did not generate an entry chunk for SSR`);
- }
- // Mutate the filename
- internals.ssrEntryChunk.fileName = options.settings.config.build.serverEntry;
-
- const code = await injectManifest(options, internals);
- mutate(internals.ssrEntryChunk, 'server', code);
- },
- },
- };
-}
diff --git a/packages/astro/src/core/build/plugins/util.ts b/packages/astro/src/core/build/plugins/util.ts
index 50f5e07059b8..fa79d72bdf3d 100644
--- a/packages/astro/src/core/build/plugins/util.ts
+++ b/packages/astro/src/core/build/plugins/util.ts
@@ -1,3 +1,4 @@
+import { extname } from 'node:path';
import type { Plugin as VitePlugin } from 'vite';
// eslint-disable-next-line @typescript-eslint/ban-types
@@ -38,3 +39,33 @@ export function extendManualChunks(outputOptions: OutputOptions, hooks: ExtendMa
return null;
};
}
+
+// This is an arbitrary string that we are going to replace the dot of the extension
+export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@';
+
+/**
+ * 1. We add a fixed prefix, which is used as virtual module naming convention;
+ * 2. We replace the dot that belongs extension with an arbitrary string.
+ *
+ * @param virtualModulePrefix
+ * @param path
+ */
+export function getVirtualModulePageNameFromPath(virtualModulePrefix: string, path: string) {
+ // we mask the extension, so this virtual file
+ // so rollup won't trigger other plugins in the process
+ const extension = extname(path);
+ return `${virtualModulePrefix}${path.replace(
+ extension,
+ extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
+ )}`;
+}
+
+/**
+ *
+ * @param virtualModulePrefix
+ * @param id
+ */
+export function getPathFromVirtualModulePageName(virtualModulePrefix: string, id: string) {
+ const pageName = id.slice(virtualModulePrefix.length);
+ return pageName.replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.');
+}
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 72bfd698836f..7d6004c0dd89 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -3,9 +3,11 @@ import * as eslexer from 'es-module-lexer';
import glob from 'fast-glob';
import fs from 'fs';
import { bgGreen, bgMagenta, black, dim } from 'kleur/colors';
+import { extname } from 'node:path';
import path from 'path';
import { fileURLToPath } from 'url';
import * as vite from 'vite';
+import type { RouteData } from '../../@types/astro';
import {
createBuildInternals,
eachPageData,
@@ -24,12 +26,11 @@ import { generatePages } from './generate.js';
import { trackPageData } from './internal.js';
import { createPluginContainer, type AstroBuildPluginContainer } from './plugin.js';
import { registerAllPlugins } from './plugins/index.js';
-import {
- ASTRO_PAGE_EXTENSION_POST_PATTERN,
- ASTRO_PAGE_RESOLVED_MODULE_ID,
-} from './plugins/plugin-pages.js';
+import { MIDDLEWARE_MODULE_ID } from './plugins/plugin-middleware.js';
+import { ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js';
import { RESOLVED_RENDERERS_MODULE_ID } from './plugins/plugin-renderers.js';
-import { SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js';
+import { RESOLVED_SPLIT_MODULE_ID, SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js';
+import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js';
import type { PageBuildData, StaticBuildOptions } from './types';
import { getTimeStat } from './util.js';
@@ -143,10 +144,10 @@ async function ssrBuild(
input: Set,
container: AstroBuildPluginContainer
) {
- const { settings, viteConfig } = opts;
+ const { allPages, settings, viteConfig } = opts;
const ssr = isServerLikeOutput(settings.config);
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir);
-
+ const routes = Object.values(allPages).map((pd) => pd.route);
const { lastVitePlugins, vitePlugins } = container.runBeforeHook('ssr', input);
const viteBuildConfig: vite.InlineConfig = {
@@ -175,13 +176,14 @@ async function ssrBuild(
...viteConfig.build?.rollupOptions?.output,
entryFileNames(chunkInfo) {
if (chunkInfo.facadeModuleId?.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) {
- return makeAstroPageEntryPointFileName(chunkInfo.facadeModuleId);
- } else if (
- // checks if the path of the module we have middleware, e.g. middleware.js / middleware/index.js
- chunkInfo.moduleIds.find((m) => m.includes('middleware')) !== undefined &&
- // checks if the file actually export the `onRequest` function
- chunkInfo.exports.includes('_middleware')
- ) {
+ return makeAstroPageEntryPointFileName(
+ ASTRO_PAGE_RESOLVED_MODULE_ID,
+ chunkInfo.facadeModuleId,
+ routes
+ );
+ } else if (chunkInfo.facadeModuleId?.startsWith(RESOLVED_SPLIT_MODULE_ID)) {
+ return makeSplitEntryPointFileName(chunkInfo.facadeModuleId, routes);
+ } else if (chunkInfo.facadeModuleId === MIDDLEWARE_MODULE_ID) {
return 'middleware.mjs';
} else if (chunkInfo.facadeModuleId === SSR_VIRTUAL_MODULE_ID) {
return opts.settings.config.build.serverEntry;
@@ -205,7 +207,7 @@ async function ssrBuild(
base: settings.config.base,
};
- await runHookBuildSetup({
+ const updatedViteBuildConfig = await runHookBuildSetup({
config: settings.config,
pages: internals.pagesByComponent,
vite: viteBuildConfig,
@@ -213,7 +215,7 @@ async function ssrBuild(
logging: opts.logging,
});
- return await vite.build(viteBuildConfig);
+ return await vite.build(updatedViteBuildConfig);
}
async function clientBuild(
@@ -418,27 +420,73 @@ async function ssrMoveAssets(opts: StaticBuildOptions) {
}
/**
- * This function takes as input the virtual module name of an astro page and transform
- * to generate an `.mjs` file:
+ * This function takes the virtual module name of any page entrypoint and
+ * transforms it to generate a final `.mjs` output file.
*
* Input: `@astro-page:src/pages/index@_@astro`
- *
* Output: `pages/index.astro.mjs`
+ * Input: `@astro-page:../node_modules/my-dep/injected@_@astro`
+ * Output: `pages/injected.mjs`
*
- * 1. We remove the module id prefix, `@astro-page:`
- * 2. We remove `src/`
- * 3. We replace square brackets with underscore, for example `[slug]`
- * 4. At last, we replace the extension pattern with a simple dot
- * 5. We append the `.mjs` string, so the file will always be a JS file
+ * 1. We clean the `facadeModuleId` by removing the `ASTRO_PAGE_MODULE_ID` prefix and `ASTRO_PAGE_EXTENSION_POST_PATTERN`.
+ * 2. We find the matching route pattern in the manifest (or fallback to the cleaned module id)
+ * 3. We replace square brackets with underscore (`[slug]` => `_slug_`) and `...` with `` (`[...slug]` => `_---slug_`).
+ * 4. We append the `.mjs` extension, so the file will always be an ESM module
+ *
+ * @param prefix string
+ * @param facadeModuleId string
+ * @param pages AllPagesData
+ */
+export function makeAstroPageEntryPointFileName(
+ prefix: string,
+ facadeModuleId: string,
+ routes: RouteData[]
+) {
+ const pageModuleId = facadeModuleId
+ .replace(prefix, '')
+ .replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.');
+ let route = routes.find((routeData) => {
+ return routeData.route === pageModuleId;
+ });
+ let name = pageModuleId;
+ if (route) {
+ name = route.route;
+ }
+ if (name.endsWith('/')) name += 'index';
+ const fileName = `${name.replaceAll('[', '_').replaceAll(']', '_').replaceAll('...', '---')}.mjs`;
+ if (name.startsWith('..')) {
+ return `pages${fileName}`;
+ }
+ return fileName;
+}
+
+/**
+ * The `facadeModuleId` has a shape like: \0@astro-serverless-page:src/pages/index@_@astro.
+ *
+ * 1. We call `makeAstroPageEntryPointFileName` which normalise its name, making it like a file path
+ * 2. We split the file path using the file system separator and attempt to retrieve the last entry
+ * 3. The last entry should be the file
+ * 4. We prepend the file name with `entry.`
+ * 5. We built the file path again, using the new entry built in the previous step
*
* @param facadeModuleId
+ * @param opts
*/
-function makeAstroPageEntryPointFileName(facadeModuleId: string) {
- return `${facadeModuleId
- .replace(ASTRO_PAGE_RESOLVED_MODULE_ID, '')
- .replace('src/', '')
- .replaceAll('[', '_')
- .replaceAll(']', '_')
- // this must be last
- .replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.')}.mjs`;
+export function makeSplitEntryPointFileName(facadeModuleId: string, routes: RouteData[]) {
+ const filePath = `${makeAstroPageEntryPointFileName(
+ RESOLVED_SPLIT_MODULE_ID,
+ facadeModuleId,
+ routes
+ )}`;
+
+ const pathComponents = filePath.split(path.sep);
+ const lastPathComponent = pathComponents.pop();
+ if (lastPathComponent) {
+ const extension = extname(lastPathComponent);
+ if (extension.length > 0) {
+ const newFileName = `entry.${lastPathComponent}`;
+ return [...pathComponents, newFileName].join(path.sep);
+ }
+ }
+ return filePath;
}
diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts
index 772235697751..5b6db5d49d9a 100644
--- a/packages/astro/src/core/build/types.ts
+++ b/packages/astro/src/core/build/types.ts
@@ -1,11 +1,11 @@
import type { default as vite, InlineConfig } from 'vite';
import type {
AstroConfig,
- AstroMiddlewareInstance,
AstroSettings,
BuildConfig,
ComponentInstance,
ManifestData,
+ MiddlewareHandler,
RouteData,
RuntimeMode,
SSRLoadedRenderer,
@@ -51,7 +51,10 @@ type ImportComponentInstance = () => Promise;
export interface SinglePageBuiltModule {
page: ImportComponentInstance;
- middleware: AstroMiddlewareInstance;
+ /**
+ * The `onRequest` hook exported by the middleware
+ */
+ onRequest?: MiddlewareHandler;
renderers: SSRLoadedRenderer[];
}
diff --git a/packages/astro/src/core/compile/compile.ts b/packages/astro/src/core/compile/compile.ts
index 4c76c4c65694..e78a761a4932 100644
--- a/packages/astro/src/core/compile/compile.ts
+++ b/packages/astro/src/core/compile/compile.ts
@@ -82,7 +82,6 @@ function handleCompileResultErrors(result: TransformResult, cssTransformErrors:
if (compilerError) {
throw new CompilerError({
- code: compilerError.code,
message: compilerError.text,
location: {
line: compilerError.location.line,
@@ -98,15 +97,11 @@ function handleCompileResultErrors(result: TransformResult, cssTransformErrors:
break;
case 1: {
const error = cssTransformErrors[0];
- if (!error.errorCode) {
- error.errorCode = AstroErrorData.UnknownCSSError.code;
- }
throw cssTransformErrors[0];
}
default: {
throw new AggregateError({
...cssTransformErrors[0],
- code: cssTransformErrors[0].errorCode,
errors: cssTransformErrors,
});
}
diff --git a/packages/astro/src/core/compile/style.ts b/packages/astro/src/core/compile/style.ts
index 951babd434de..4ac1cdc70652 100644
--- a/packages/astro/src/core/compile/style.ts
+++ b/packages/astro/src/core/compile/style.ts
@@ -88,7 +88,6 @@ function enhanceCSSError(err: any, filename: string) {
errorPosition.line += 1;
return new CSSError({
- code: AstroErrorData.UnknownCSSError.code,
message: err.message,
location: {
file: filename,
diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts
index 3edabc5d54e3..99ef653d0788 100644
--- a/packages/astro/src/core/config/schema.ts
+++ b/packages/astro/src/core/config/schema.ts
@@ -24,6 +24,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = {
serverEntry: 'entry.mjs',
redirects: true,
inlineStylesheets: 'never',
+ split: false,
},
compressHTML: false,
server: {
@@ -120,6 +121,8 @@ export const AstroConfigSchema = z.object({
.enum(['always', 'auto', 'never'])
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets),
+
+ split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split),
})
.optional()
.default({}),
@@ -279,6 +282,8 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) {
.enum(['always', 'auto', 'never'])
.optional()
.default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets),
+
+ split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split),
})
.optional()
.default({}),
diff --git a/packages/astro/src/core/config/settings.ts b/packages/astro/src/core/config/settings.ts
index 1494a5eddeb2..c5e9def8ce43 100644
--- a/packages/astro/src/core/config/settings.ts
+++ b/packages/astro/src/core/config/settings.ts
@@ -24,7 +24,7 @@ export function createBaseSettings(config: AstroConfig): AstroSettings {
adapter: undefined,
injectedRoutes:
config.experimental.assets && isServerLikeOutput(config)
- ? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint' }]
+ ? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint', prerender: false }]
: [],
pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS],
contentEntryTypes: [markdownContentEntryType],
diff --git a/packages/astro/src/core/endpoint/dev/index.ts b/packages/astro/src/core/endpoint/dev/index.ts
index b829754765ec..04e11b578007 100644
--- a/packages/astro/src/core/endpoint/dev/index.ts
+++ b/packages/astro/src/core/endpoint/dev/index.ts
@@ -21,5 +21,5 @@ export async function call(options: SSROptions, logging: LogOptions) {
mod: endpointHandler as any,
});
- return await callEndpoint(endpointHandler, env, ctx, logging, middleware);
+ return await callEndpoint(endpointHandler, env, ctx, logging, middleware?.onRequest);
}
diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts
index 5822685cf987..dde07cd9c625 100644
--- a/packages/astro/src/core/endpoint/index.ts
+++ b/packages/astro/src/core/endpoint/index.ts
@@ -1,10 +1,10 @@
import type {
APIContext,
AstroConfig,
- AstroMiddlewareInstance,
EndpointHandler,
EndpointOutput,
MiddlewareEndpointHandler,
+ MiddlewareHandler,
Params,
} from '../../@types/astro';
import type { Environment, RenderContext } from '../render/index';
@@ -78,6 +78,7 @@ export function createAPIContext({
// We define a custom property, so we can check the value passed to locals
Object.defineProperty(context, 'locals', {
+ enumerable: true,
get() {
return Reflect.get(request, clientLocalsSymbol);
},
@@ -97,7 +98,7 @@ export async function callEndpoint
env: Environment,
ctx: RenderContext,
logging: LogOptions,
- middleware?: AstroMiddlewareInstance | undefined
+ onRequest?: MiddlewareHandler | undefined
): Promise {
const context = createAPIContext({
request: ctx.request,
@@ -108,11 +109,10 @@ export async function callEndpoint
});
let response;
- if (middleware && middleware.onRequest) {
- const onRequest = middleware.onRequest as MiddlewareEndpointHandler;
+ if (onRequest) {
response = await callMiddleware(
env.logging,
- onRequest,
+ onRequest as MiddlewareEndpointHandler,
context,
async () => {
return await renderEndpoint(mod, context, env.ssr);
diff --git a/packages/astro/src/core/errors/README.md b/packages/astro/src/core/errors/README.md
index 2e6ffb3ae826..fd040d8162c1 100644
--- a/packages/astro/src/core/errors/README.md
+++ b/packages/astro/src/core/errors/README.md
@@ -9,57 +9,48 @@
**Error Format**
Name (key of the object definition):
-- As with the error code, this property is a static reference to the error. The shape should be similar to JavaScript's native errors (TypeError, ReferenceError): pascal-cased, no spaces, no special characters etc. (ex: `ClientAddressNotAvailable`)
+
+- This property is a static reference to the error. The shape should be similar to JavaScript's native errors (TypeError, ReferenceError): pascal-cased, no spaces, no special characters etc. (ex: `ClientAddressNotAvailable`)
- This is the only part of the error message that should not be written as a full, proper sentence complete with Capitalization and end punctuation.
Title:
+
- Use this property to briefly describe the error in a few words. This is the user's way to see at a glance what has happened and will be prominently displayed in the UI (ex: `{feature} is not available in static mode.`) Do not include further details such as why this error occurred or possible solutions.
Message:
+
- Begin with **what happened** and **why**. (ex: `Could not use {feature} because Serverβ -β side Rendering is not enabled.`)
- Then, **describe the action the user should take**. (ex: `Update your Astro config with `output: 'server'` to enable Serverβ -β side Rendering.`)
- Although this does not need to be as brief as the `title`, try to keep sentences short, clear and direct to give the reader all the necessary information quickly as possible.
- Instead of writing a longer message, consider using a `hint`.
Hint:
+
- A `hint` can be used for any additional info that might help the user. (ex: a link to the documentation, or a common cause)
**Writing Style**
+
- Write in proper sentences. Include periods at the end of sentences. Avoid using exclamation marks! (Leave them to Houston!)
- Technical jargon is mostly okay! But, most abbreviations should be avoided. If a developer is unfamiliar with a technical term, spelling it out in full allows them to look it up on the web more easily.
-- Describe the _what_, _why_ and _action to take_ from the user's perspective. Assume they don't know Astro internals, and care only about how Astro is _used_. (ex: `You are missing...` vs `Astro/file cannot find...`)
+- Describe the _what_, _why_ and _action to take_ from the user's perspective. Assume they don't know Astro internals, and care only about how Astro is _used_. (ex: `You are missing...` vs `Astro/file cannot find...`)
- Avoid using cutesy language. (ex: Oops!) This tone minimizes the significance of the error, which _is_ important to the developer. The developer may be frustrated and your error message shouldn't be making jokes about their struggles. Only include words and phrases that help the developer **interpret the error** and **fix the problem**.
-**Choosing an Error Code**
-
-Choose any available error code in the appropriate range:
-- 01xxx and 02xxx are reserved for compiler errors and warnings respectively
-- 03xxx: Astro errors (your error most likely goes here!)
-- 04xxx: Vite errors
-- 05xxx: CSS errors
-- 06xxx: Markdown errors
-- 07xxx: Configuration errors
-- 07xxx-98xxx <- Need to add a category? Add it here!
-- 99xxx: Catch-alls for unknown errors
-
-As long as it is unique, the exact error code used is unimportant. For example, error 5005 and error 5006 don't necessarily have to be related, or follow any logical pattern.
-
-Users are not reading codes sequentially. They're much more likely to directly land on the error or search for a specific code.
-
-If you are unsure about which error code to choose, ask [Erika](https://github.com/Princesseuh)!
+If you are unsure about anything, ask [Erika](https://github.com/Princesseuh)!
### CLI specifics tips:
+
- If the error happened **during an action that changes the state of the project** (ex: editing configuration, creating files), the error should **reassure the user** about the state of their project (ex: "Failed to update configuration. Your project has been restored to its previous state.")
- If an "error" happened because of a conscious user action (ex: pressing CTRL+C during a choice), it is okay to add more personality (ex: "Operation cancelled. See you later, astronaut!"). Do keep in mind the previous point however (ex: "Operation cancelled. No worries, your project folder has already been created")
### Shape
-- **Error codes and names are permanent**, and should never be changed, nor deleted. Users should always be able to find an error by searching, and this ensures a matching result. When an error is no longer relevant, it should be deprecated, not removed.
+
+- **Names are permanent**, and should never be changed, nor deleted. Users should always be able to find an error by searching, and this ensures a matching result. When an error is no longer relevant, it should be deprecated, not removed.
- Contextual information may be used to enhance the message or the hint. However, the code that caused the error or the position of the error should not be included in the message as they will already be shown as part of the error.
- Do not prefix `title`, `message` and `hint` with descriptive words such as "Error:" or "Hint:" as it may lead to duplicated labels in the UI / CLI.
- Dynamic error messages must use the following shape:
```js
-message: (arguments) => `text ${substitute}`
+message: (arguments) => `text ${substitute}`;
```
Please avoid including too much logic inside the errors if you can. The last thing you want is for a bug to happen inside what's already an error!
@@ -70,28 +61,30 @@ Using light logic to add / remove different parts of the message is okay, howeve
### Documentation support through JSDoc
-Using JSDoc comments, [a reference for every error message](https://docs.astro.build/en/reference/error-reference/) is built automatically on our docs. Users can then search for a error code to find more information on how to fix the error they encountered.
+Using JSDoc comments, [a reference for every error message](https://docs.astro.build/en/reference/error-reference/) is built automatically on our docs.
Here's how to create and format the comments:
```js
/**
- * @docs <- Needed for the comment to be used for docs
- * @message <- (Optional) Clearer error message to show in cases where the original one is too complex (ex: because of conditional messages)
- * @see <- List of additional references users can look at
- * @description <- Description of the error
- */
+ * @docs <- Needed for the comment to be used for docs
+ * @message <- (Optional) Clearer error message to show in cases where the original one is too complex (ex: because of conditional messages)
+ * @see <- List of additional references users can look at
+ * @description <- Description of the error
+ */
```
+
Example:
+
```js
/**
- * @docs
- * @message Route returned a `returnedValue`. Only a Response can be returned from Astro files.
- * @see
- * - [Response](https://docs.astro.build/en/guides/server-side-rendering/#response)
- * @description
- * Only instances of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned inside Astro files.
- */
+ * @docs
+ * @message Route returned a `returnedValue`. Only a Response can be returned from Astro files.
+ * @see
+ * - [Response](https://docs.astro.build/en/guides/server-side-rendering/#response)
+ * @description
+ * Only instances of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned inside Astro files.
+ */
```
The `@message` property is intended to provide slightly more context when it is helpful: a more descriptive error message or a collection of common messages if there are multiple possible error messages. Try to avoid making substantial changes to existing messages so that they are easy to find for users who copy and search the exact content of an error message.
diff --git a/packages/astro/src/core/errors/dev/utils.ts b/packages/astro/src/core/errors/dev/utils.ts
index 28445ba32385..29468c7fd8d2 100644
--- a/packages/astro/src/core/errors/dev/utils.ts
+++ b/packages/astro/src/core/errors/dev/utils.ts
@@ -24,9 +24,13 @@ export function collectErrorMetadata(e: any, rootFolder?: URL | undefined): Erro
? (e.errors as SSRError[])
: [e as SSRError];
- err.forEach((error) => {
- if (error.stack) {
- error = collectInfoFromStacktrace(e);
+ err.forEach((error, idx) => {
+ if (e.stack) {
+ const stackInfo = collectInfoFromStacktrace(e);
+ error.stack = stackInfo.stack;
+ error.loc = stackInfo.loc;
+ error.plugin = stackInfo.plugin;
+ error.pluginCode = stackInfo.pluginCode;
}
// Make sure the file location is absolute, otherwise:
@@ -141,15 +145,22 @@ See https://docs.astro.build/en/guides/troubleshooting/#document-or-window-is-no
return err.hint;
}
-function collectInfoFromStacktrace(error: SSRError): SSRError {
- if (!error.stack) return error;
+type StackInfo = Pick;
+
+function collectInfoFromStacktrace(error: SSRError & { stack: string }): StackInfo {
+ let stackInfo: StackInfo = {
+ stack: error.stack,
+ plugin: error.plugin,
+ pluginCode: error.pluginCode,
+ loc: error.loc,
+ };
// normalize error stack line-endings to \n
- error.stack = normalizeLF(error.stack);
+ stackInfo.stack = normalizeLF(error.stack);
const stackText = stripAnsi(error.stack);
// Try to find possible location from stack if we don't have one
- if (!error.loc || (!error.loc.column && !error.loc.line)) {
+ if (!stackInfo.loc || (!stackInfo.loc.column && !stackInfo.loc.line)) {
const possibleFilePath =
error.loc?.file ||
error.pluginCode ||
@@ -168,7 +179,7 @@ function collectInfoFromStacktrace(error: SSRError): SSRError {
file = fileURLToPath(file);
} catch {}
- error.loc = {
+ stackInfo.loc = {
file,
line: Number.parseInt(line),
column: Number.parseInt(column),
@@ -177,17 +188,17 @@ function collectInfoFromStacktrace(error: SSRError): SSRError {
}
// Derive plugin from stack (if possible)
- if (!error.plugin) {
- error.plugin =
+ if (!stackInfo.plugin) {
+ stackInfo.plugin =
/withastro\/astro\/packages\/integrations\/([\w-]+)/gim.exec(stackText)?.at(1) ||
/(@astrojs\/[\w-]+)\/(server|client|index)/gim.exec(stackText)?.at(1) ||
undefined;
}
// Normalize stack (remove `/@fs/` urls, etc)
- error.stack = cleanErrorStack(error.stack);
+ stackInfo.stack = cleanErrorStack(error.stack);
- return error;
+ return stackInfo;
}
function cleanErrorStack(stack: string) {
diff --git a/packages/astro/src/core/errors/dev/vite.ts b/packages/astro/src/core/errors/dev/vite.ts
index 9bc2e8c25f26..cb19ca8f6bff 100644
--- a/packages/astro/src/core/errors/dev/vite.ts
+++ b/packages/astro/src/core/errors/dev/vite.ts
@@ -45,7 +45,6 @@ export function enhanceViteSSRError({
safeError.name = 'FailedToLoadModuleSSR';
safeError.message = AstroErrorData.FailedToLoadModuleSSR.message(importName);
safeError.hint = AstroErrorData.FailedToLoadModuleSSR.hint;
- safeError.code = AstroErrorData.FailedToLoadModuleSSR.code;
const line = lns.findIndex((ln) => ln.includes(importName!));
if (line !== -1) {
@@ -84,7 +83,6 @@ export function enhanceViteSSRError({
safeError.message = AstroErrorData.InvalidGlob.message(globPattern);
safeError.name = 'InvalidGlob';
safeError.hint = AstroErrorData.InvalidGlob.hint;
- safeError.code = AstroErrorData.InvalidGlob.code;
safeError.title = AstroErrorData.InvalidGlob.title;
const line = lns.findIndex((ln) => ln.includes(globPattern));
@@ -139,17 +137,7 @@ export async function getViteErrorPayload(err: ErrorWithMetadata): Promise string);
hint?: string | ((...params: any) => string);
@@ -30,7 +29,6 @@ export const AstroErrorData = {
*/
UnknownCompilerError: {
title: 'Unknown compiler error.',
- code: 1000,
hint: 'This is almost always a problem with the Astro compiler, not your code. Please open an issue at https://astro.build/issues/compiler.',
},
// 1xxx and 2xxx codes are reserved for compiler errors and warnings respectively
@@ -47,7 +45,6 @@ export const AstroErrorData = {
*/
StaticRedirectNotAvailable: {
title: '`Astro.redirect` is not available in static mode.',
- code: 3001,
message:
"Redirects are only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.",
hint: 'See https://docs.astro.build/en/guides/server-side-rendering/#enabling-ssr-in-your-project for more information on how to enable SSR.',
@@ -62,7 +59,6 @@ export const AstroErrorData = {
*/
ClientAddressNotAvailable: {
title: '`Astro.clientAddress` is not available in current adapter.',
- code: 3002,
message: (adapterName: string) =>
`\`Astro.clientAddress\` is not available in the \`${adapterName}\` adapter. File an issue with the adapter to add support.`,
},
@@ -78,7 +74,6 @@ export const AstroErrorData = {
*/
StaticClientAddressNotAvailable: {
title: '`Astro.clientAddress` is not available in static mode.',
- code: 3003,
message:
"`Astro.clientAddress` is only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.",
hint: 'See https://docs.astro.build/en/guides/server-side-rendering/#enabling-ssr-in-your-project for more information on how to enable SSR.',
@@ -92,7 +87,6 @@ export const AstroErrorData = {
*/
NoMatchingStaticPathFound: {
title: 'No static path found for requested path.',
- code: 3004,
message: (pathName: string) =>
`A \`getStaticPaths()\` route pattern was matched, but no matching static path was found for requested path \`${pathName}\`.`,
hint: (possibleRoutes: string[]) =>
@@ -120,7 +114,6 @@ export const AstroErrorData = {
*/
OnlyResponseCanBeReturned: {
title: 'Invalid type returned by Astro page.',
- code: 3005,
message: (route: string | undefined, returnedValue: string) =>
`Route \`${
route ? route : ''
@@ -140,7 +133,6 @@ export const AstroErrorData = {
*/
MissingMediaQueryDirective: {
title: 'Missing value for `client:media` directive.',
- code: 3006,
message:
'Media query not provided for `client:media` directive. A media query similar to `client:media="(max-width: 600px)"` must be provided',
},
@@ -157,7 +149,6 @@ export const AstroErrorData = {
*/
NoMatchingRenderer: {
title: 'No matching renderer found.',
- code: 3007,
message: (
componentName: string,
componentExtension: string | undefined,
@@ -192,7 +183,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
NoClientEntrypoint: {
title: 'No client entrypoint specified in renderer.',
- code: 3008,
message: (componentName: string, clientDirective: string, rendererName: string) =>
`\`${componentName}\` component has a \`client:${clientDirective}\` directive, but no client entrypoint was provided by \`${rendererName}\`.`,
hint: 'See https://docs.astro.build/en/reference/integrations-reference/#addrenderer-option for more information on how to configure your renderer.',
@@ -211,7 +201,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
NoClientOnlyHint: {
title: 'Missing hint on client:only directive.',
- code: 3009,
message: (componentName: string) =>
`Unable to render \`${componentName}\`. When using the \`client:only\` hydration strategy, Astro needs a hint to use the correct renderer.`,
hint: (probableRenderers: string) =>
@@ -238,7 +227,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
InvalidGetStaticPathParam: {
title: 'Invalid value returned by a `getStaticPaths` path.',
- code: 3010,
message: (paramType) =>
`Invalid params given to \`getStaticPaths\` path. Expected an \`object\`, got \`${paramType}\``,
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
@@ -262,7 +250,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
InvalidGetStaticPathsReturn: {
title: 'Invalid value returned by getStaticPaths.',
- code: 3011,
message: (returnType) =>
`Invalid type returned by \`getStaticPaths\`. Expected an \`array\`, got \`${returnType}\``,
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
@@ -276,7 +263,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
GetStaticPathsRemovedRSSHelper: {
title: 'getStaticPaths RSS helper is not available anymore.',
- code: 3012,
message:
'The RSS helper has been removed from `getStaticPaths`. Try the new @astrojs/rss package instead.',
hint: 'See https://docs.astro.build/en/guides/rss/ for more information.',
@@ -303,7 +289,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
GetStaticPathsExpectedParams: {
title: 'Missing params property on `getStaticPaths` route.',
- code: 3013,
message: 'Missing or empty required `params` property on `getStaticPaths` route.',
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
},
@@ -343,7 +328,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
GetStaticPathsInvalidRouteParam: {
title: 'Invalid value for `getStaticPaths` route parameter.',
- code: 3014,
message: (key: string, value: any, valueType: any) =>
`Invalid getStaticPaths route parameter for \`${key}\`. Expected undefined, a string or a number, received \`${valueType}\` (\`${value}\`)`,
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
@@ -359,7 +343,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
*/
GetStaticPathsRequired: {
title: '`getStaticPaths()` function required for dynamic routes.',
- code: 3015,
message:
'`getStaticPaths()` function is required for dynamic routes. Make sure that you `export` a `getStaticPaths` function from your dynamic route.',
hint: `See https://docs.astro.build/en/core-concepts/routing/#dynamic-routes for more information on dynamic routes.
@@ -376,7 +359,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ReservedSlotName: {
title: 'Invalid slot name.',
- code: 3016,
message: (slotName: string) =>
`Unable to create a slot named \`${slotName}\`. \`${slotName}\` is a reserved slot name. Please update the name of this slot.`,
},
@@ -390,7 +372,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
NoAdapterInstalled: {
title: 'Cannot use Server-side Rendering without an adapter.',
- code: 3017,
message: `Cannot use \`output: 'server'\` or \`output: 'hybrid'\` without an adapter. Please install and configure the appropriate server adapter for your final deployment.`,
hint: 'See https://docs.astro.build/en/guides/server-side-rendering/ for more information.',
},
@@ -401,7 +382,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
NoMatchingImport: {
title: 'No import found for component.',
- code: 3018,
message: (componentName: string) =>
`Could not render \`${componentName}\`. No matching import has been found for \`${componentName}\`.`,
hint: 'Please make sure the component is properly imported.',
@@ -416,7 +396,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidPrerenderExport: {
title: 'Invalid prerender export.',
- code: 3019,
message: (prefix: string, suffix: string, isHydridOuput: boolean) => {
const defaultExpectedValue = isHydridOuput ? 'false' : 'true';
let msg = `A \`prerender\` export has been detected, but its value cannot be statically analyzed.`;
@@ -437,7 +416,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidComponentArgs: {
title: 'Invalid component arguments.',
- code: 3020,
message: (name: string) => `Invalid arguments passed to${name ? ` <${name}>` : ''} component.`,
hint: 'Astro components cannot be rendered directly via function call, such as `Component()` or `{items.map(Component)}`.',
},
@@ -450,7 +428,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
PageNumberParamNotFound: {
title: 'Page number param not found.',
- code: 3021,
message: (paramName: string) =>
`[paginate()] page number param \`${paramName}\` not found in your filepath.`,
hint: 'Rename your file to `[page].astro` or `[...page].astro`.',
@@ -468,7 +445,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ImageMissingAlt: {
title: 'Missing alt property.',
- code: 3022,
message: 'The alt property is required.',
hint: "The `alt` property is important for the purpose of accessibility, without it users using screen readers or other assistive technologies won't be able to understand what your image is supposed to represent. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt for more information.",
},
@@ -483,7 +459,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidImageService: {
title: 'Error while loading image service.',
- code: 3023,
message:
'There was an error loading the configured image service. Please see the stack trace for more information.',
},
@@ -501,7 +476,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MissingImageDimension: {
title: 'Missing image dimensions',
- code: 3024,
message: (missingDimension: 'width' | 'height' | 'both', imageURL: string) =>
`Missing ${
missingDimension === 'both'
@@ -526,7 +500,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnsupportedImageFormat: {
title: 'Unsupported image format',
- code: 3025,
message: (format: string, imagePath: string, supportedFormats: readonly string[]) =>
`Received unsupported format \`${format}\` from \`${imagePath}\`. Currently only ${supportedFormats.join(
', '
@@ -545,11 +518,8 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
PrerenderDynamicEndpointPathCollide: {
title: 'Prerendered dynamic endpoint has path collision.',
- code: 3026,
message: (pathname: string) =>
- `Could not render \`${pathname}\` with an \`undefined\` param as the generated path will collide during prerendering. ` +
- `Prevent passing \`undefined\` as \`params\` for the endpoint's \`getStaticPaths()\` function, ` +
- `or add an additional extension to the endpoint's filename.`,
+ `Could not render \`${pathname}\` with an \`undefined\` param as the generated path will collide during prerendering. Prevent passing \`undefined\` as \`params\` for the endpoint's \`getStaticPaths()\` function, or add an additional extension to the endpoint's filename.`,
hint: (filename: string) =>
`Rename \`${filename}\` to \`${filename.replace(/\.(js|ts)/, (m) => `.json` + m)}\``,
},
@@ -574,7 +544,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ExpectedImage: {
title: 'Expected src to be an image.',
- code: 3027,
message: (options: string) =>
`Expected \`src\` property to be either an ESM imported image or a string with the path of a remote image. Received \`${options}\`.`,
hint: 'This error can often happen because of a wrong path. Make sure the path to your image is correct.',
@@ -597,7 +566,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ExpectedImageOptions: {
title: 'Expected image options.',
- code: 3028,
message: (options: string) =>
`Expected getImage() parameter to be an object. Received \`${options}\`.`,
},
@@ -614,7 +582,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MarkdownImageNotFound: {
title: 'Image not found.',
- code: 3029,
message: (imagePath: string, fullImagePath: string | undefined) =>
`Could not find requested image \`${imagePath}\`${
fullImagePath ? ` at \`${fullImagePath}\`.` : '.'
@@ -628,7 +595,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ResponseSentError: {
title: 'Unable to set response.',
- code: 3030,
message: 'The response has already been sent to the browser and cannot be altered.',
},
@@ -648,7 +614,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MiddlewareNoDataOrNextCalled: {
title: "The middleware didn't return a response or call `next`.",
- code: 3031,
message:
'The middleware needs to either return a `Response` object or call the `next` function.',
},
@@ -668,7 +633,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MiddlewareNotAResponse: {
title: 'The middleware returned something that is not a `Response` object.',
- code: 3032,
message: 'Any data returned from middleware must be a valid `Response` object.',
},
@@ -689,12 +653,11 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
LocalsNotAnObject: {
title: 'Value assigned to `locals` is not accepted.',
- code: 3033,
message:
'`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.',
hint: 'If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`.',
},
- /*
+ /**
* @docs
* @see
* - [Assets (Experimental)](https://docs.astro.build/en/guides/assets/)
@@ -716,7 +679,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
LocalImageUsedWrongly: {
title: 'ESM imported images must be passed as-is.',
- code: 3034,
message: (imageFilePath: string) =>
`\`Image\`'s and \`getImage\`'s \`src\` parameter must be an imported image or an URL, it cannot be a filepath. Received \`${imageFilePath}\`.`,
},
@@ -730,7 +692,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
AstroGlobUsedOutside: {
title: 'Astro.glob() used outside of an Astro file.',
- code: 3035,
message: (globStr: string) =>
`\`Astro.glob(${globStr})\` can only be used in \`.astro\` files. \`import.meta.glob(${globStr})\` can be used instead to achieve a similar result.`,
hint: "See Vite's documentation on `import.meta.glob` for more information: https://vitejs.dev/guide/features.html#glob-import",
@@ -745,7 +706,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
AstroGlobNoMatch: {
title: 'Astro.glob() did not match any files.',
- code: 3036,
message: (globStr: string) =>
`\`Astro.glob(${globStr})\` did not return any matching files. Check the pattern for typos.`,
},
@@ -758,7 +718,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
RedirectWithNoLocation: {
title: 'A redirect must be given a location with the `Location` header.',
- code: 3037,
},
/**
* @docs
@@ -769,7 +728,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidDynamicRoute: {
title: 'Invalid dynamic route.',
- code: 3038,
message: (route: string, invalidParam: string, received: string) =>
`The ${invalidParam} param for route ${route} is invalid. Received **${received}**.`,
},
@@ -786,7 +744,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownViteError: {
title: 'Unknown Vite Error.',
- code: 4000,
},
/**
* @docs
@@ -799,7 +756,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
FailedToLoadModuleSSR: {
title: 'Could not import file.',
- code: 4001,
message: (importName: string) => `Could not import \`${importName}\`.`,
hint: 'This is often caused by a typo in the import path. Please make sure the file exists.',
},
@@ -812,11 +768,20 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidGlob: {
title: 'Invalid glob pattern.',
- code: 4002,
message: (globPattern: string) =>
`Invalid glob pattern: \`${globPattern}\`. Glob patterns must start with './', '../' or '/'.`,
hint: 'See https://docs.astro.build/en/guides/imports/#glob-patterns for more information on supported glob patterns.',
},
+ /**
+ * @docs
+ * @description
+ * Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error.
+ */
+ FailedToFindPageMapSSR: {
+ title: "Astro couldn't find the correct page to render",
+ message:
+ "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error. Please file an issue.",
+ },
/**
* @docs
* @kind heading
@@ -832,7 +797,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownCSSError: {
title: 'Unknown CSS Error.',
- code: 5000,
},
/**
* @docs
@@ -845,7 +809,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
CSSSyntaxError: {
title: 'CSS Syntax Error.',
- code: 5001,
},
/**
* @docs
@@ -860,7 +823,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownMarkdownError: {
title: 'Unknown Markdown Error.',
- code: 6000,
},
/**
* @docs
@@ -875,7 +837,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MarkdownFrontmatterParseError: {
title: 'Failed to parse Markdown frontmatter.',
- code: 6001,
},
/**
* @docs
@@ -886,7 +847,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidFrontmatterInjectionError: {
title: 'Invalid frontmatter injection.',
- code: 6003,
message:
'A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.',
hint: 'See the frontmatter injection docs https://docs.astro.build/en/guides/markdown-content/#modifying-frontmatter-programmatically for more information.',
@@ -900,7 +860,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MdxIntegrationMissingError: {
title: 'MDX integration missing.',
- code: 6004,
message: (file: string) =>
`Unable to render ${file}. Ensure that the \`@astrojs/mdx\` integration is installed.`,
hint: 'See the MDX integration docs for installation and usage instructions: https://docs.astro.build/en/guides/integrations-guide/mdx/',
@@ -918,7 +877,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownConfigError: {
title: 'Unknown configuration error.',
- code: 7000,
},
/**
* @docs
@@ -929,7 +887,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ConfigNotFound: {
title: 'Specified configuration file not found.',
- code: 7001,
message: (configFile: string) =>
`Unable to resolve \`--config "${configFile}"\`. Does the file exist?`,
},
@@ -942,7 +899,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ConfigLegacyKey: {
title: 'Legacy configuration detected.',
- code: 7002,
message: (legacyConfigKey: string) => `Legacy configuration detected: \`${legacyConfigKey}\`.`,
hint: 'Please update your configuration to the new format.\nSee https://astro.build/config for more information.',
},
@@ -961,7 +917,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownCLIError: {
title: 'Unknown CLI Error.',
- code: 8000,
},
/**
* @docs
@@ -972,7 +927,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
GenerateContentTypesError: {
title: 'Failed to generate content types.',
- code: 8001,
message: (errorMessage: string) =>
`\`astro sync\` command failed to generate content collection types: ${errorMessage}`,
hint: 'Check your `src/content/config.*` file for typos.',
@@ -993,7 +947,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnknownContentCollectionError: {
title: 'Unknown Content Collection Error.',
- code: 9000,
},
/**
* @docs
@@ -1010,7 +963,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidContentEntryFrontmatterError: {
title: 'Content entry frontmatter does not match schema.',
- code: 9001,
message: (collection: string, entryId: string, error: ZodError) => {
return [
`**${String(collection)} β ${String(
@@ -1031,7 +983,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
InvalidContentEntrySlugError: {
title: 'Invalid content entry slug.',
- code: 9002,
message: (collection: string, entryId: string) => {
return `${String(collection)} β ${String(
entryId
@@ -1042,13 +993,12 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
/**
* @docs
* @see
- * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/)
+ * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/#defining-custom-slugs)
* @description
- * A content collection schema should not contain the `slug` field. This is reserved by Astro for generating entry slugs. Remove the `slug` field from your schema, or choose a different name.
+ * A content collection schema should not contain the `slug` field. This is reserved by Astro for generating entry slugs. Remove `slug` from your schema. You can still use custom slugs in your frontmatter.
*/
ContentSchemaContainsSlugError: {
title: 'Content Schema should not contain `slug`.',
- code: 9003,
message: (collectionName: string) =>
`A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collectionName} collection schema.`,
hint: 'See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field.',
@@ -1062,7 +1012,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
CollectionDoesNotExistError: {
title: 'Collection does not exist',
- code: 9004,
message: (collectionName: string) =>
`The collection **${collectionName}** does not exist. Ensure a collection directory with this name exists.`,
hint: 'See https://docs.astro.build/en/guides/content-collections/ for more on creating collections.',
@@ -1077,7 +1026,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
MixedContentDataCollectionError: {
title: 'Content and data cannot be in same collection.',
- code: 9005,
message: (collection: string) => {
return `**${collection}** contains a mix of content and data entries. All entries must be of the same type.`;
},
@@ -1093,7 +1041,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
ContentCollectionTypeMismatchError: {
title: 'Collection contains entries of a different type.',
- code: 9006,
message: (collection: string, expectedType: string, actualType: string) => {
return `${collection} contains ${expectedType} entries, but is configured as a ${actualType} collection.`;
},
@@ -1106,7 +1053,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
DataCollectionEntryParseError: {
title: 'Data collection entry failed to parse.',
- code: 9007,
message: (entryId: string, errorMessage: string) => {
return `**${entryId}** failed to parse: ${errorMessage}`;
},
@@ -1114,12 +1060,12 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
},
/**
* @docs
+ * @message `COLLECTION_NAME` contains multiple entries with the same slug: `SLUG`. Slugs must be unique.
* @description
* Content collection entries must have unique slugs. Duplicates are often caused by the `slug` frontmatter property.
*/
DuplicateContentEntrySlugError: {
title: 'Duplicate content entry slug.',
- code: 9008,
message: (collection: string, slug: string) => {
return `**${collection}** contains multiple entries with the same slug: \`${slug}\`. Slugs must be unique.`;
},
@@ -1134,7 +1080,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
*/
UnsupportedConfigTransformError: {
title: 'Unsupported transform in content config.',
- code: 9008,
message: (parseError: string) =>
`\`transform()\` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).\nFull error: ${parseError}`,
hint: 'See the devalue library for all supported types: https://github.com/rich-harris/devalue',
@@ -1143,11 +1088,5 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
// Generic catch-all - Only use this in extreme cases, like if there was a cosmic ray bit flip
UnknownError: {
title: 'Unknown Error.',
- code: 99999,
},
} as const satisfies Record;
-
-type ValueOf = T[keyof T];
-export type AstroErrorCodes = ValueOf<{
- [T in keyof typeof AstroErrorData]: (typeof AstroErrorData)[T]['code'];
-}>;
diff --git a/packages/astro/src/core/errors/errors.ts b/packages/astro/src/core/errors/errors.ts
index 995f401ef27d..cda4f328af5a 100644
--- a/packages/astro/src/core/errors/errors.ts
+++ b/packages/astro/src/core/errors/errors.ts
@@ -1,10 +1,7 @@
-import type { DiagnosticCode } from '@astrojs/compiler/shared/diagnostics.js';
-import type { AstroErrorCodes } from './errors-data.js';
import { codeFrame } from './printer.js';
-import { getErrorDataByCode } from './utils.js';
+import { getErrorDataByTitle } from './utils.js';
interface ErrorProperties {
- code: AstroErrorCodes | DiagnosticCode;
title?: string;
name?: string;
message?: string;
@@ -33,10 +30,6 @@ export function isAstroError(e: unknown): e is AstroError {
}
export class AstroError extends Error {
- // NOTE: If this property is named `code`, Rollup will use it to fill the `pluginCode` property downstream
- // This cause issues since we expect `pluginCode` to be a string containing code
- // @see https://github.com/rollup/rollup/blob/9a741639f69f204ded8ea404675f725b8d56adca/src/utils/error.ts#L725
- public errorCode: AstroErrorCodes | DiagnosticCode;
public loc: ErrorLocation | undefined;
public title: string | undefined;
public hint: string | undefined;
@@ -47,16 +40,19 @@ export class AstroError extends Error {
constructor(props: ErrorProperties, ...params: any) {
super(...params);
- const { code, name, title, message, stack, location, hint, frame } = props;
+ const { name, title, message, stack, location, hint, frame } = props;
+ this.title = title;
- this.errorCode = code;
if (name && name !== 'Error') {
this.name = name;
- } else {
- // If we don't have a name, let's generate one from the code
- this.name = getErrorDataByCode(this.errorCode)?.name ?? 'UnknownError';
+ } else if (this.title) {
+ const errorData = getErrorDataByTitle(this.title)?.name;
+
+ if (errorData) {
+ this.name = errorData;
+ }
}
- this.title = title;
+
if (message) this.message = message;
// Only set this if we actually have a stack passed, otherwise uses Error's
this.stack = stack ? stack : this.stack;
@@ -65,10 +61,6 @@ export class AstroError extends Error {
this.frame = frame;
}
- public setErrorCode(errorCode: AstroErrorCodes) {
- this.errorCode = errorCode;
- }
-
public setLocation(location: ErrorLocation): void {
this.loc = location;
}
@@ -97,7 +89,7 @@ export class AstroError extends Error {
export class CompilerError extends AstroError {
type: ErrorTypes = 'CompilerError';
- constructor(props: Omit & { code: DiagnosticCode }, ...params: any) {
+ constructor(props: ErrorProperties, ...params: any) {
super(props, ...params);
this.name = 'CompilerError';
@@ -160,7 +152,6 @@ export interface ErrorWithMetadata {
type?: ErrorTypes;
message: string;
stack: string;
- errorCode?: number;
hint?: string;
id?: string;
frame?: string;
diff --git a/packages/astro/src/core/errors/index.ts b/packages/astro/src/core/errors/index.ts
index 56a6af8c2cf5..b3ef91e28b5e 100644
--- a/packages/astro/src/core/errors/index.ts
+++ b/packages/astro/src/core/errors/index.ts
@@ -1,5 +1,5 @@
export type { ErrorLocation, ErrorWithMetadata } from './errors';
-export { AstroErrorData, type AstroErrorCodes } from './errors-data.js';
+export { AstroErrorData } from './errors-data.js';
export {
AggregateError,
AstroError,
diff --git a/packages/astro/src/core/errors/utils.ts b/packages/astro/src/core/errors/utils.ts
index f4408c305947..99cdde028e52 100644
--- a/packages/astro/src/core/errors/utils.ts
+++ b/packages/astro/src/core/errors/utils.ts
@@ -1,8 +1,7 @@
-import type { DiagnosticCode } from '@astrojs/compiler/shared/diagnostics.js';
import type { YAMLException } from 'js-yaml';
import type { ErrorPayload as ViteErrorPayload } from 'vite';
import type { SSRError } from '../../@types/astro.js';
-import { AstroErrorData, type AstroErrorCodes, type ErrorData } from './errors-data.js';
+import { AstroErrorData, type ErrorData } from './errors-data.js';
/**
* Get the line and character based on the offset
@@ -107,8 +106,8 @@ export function normalizeLF(code: string) {
return code.replace(/\r\n|\r(?!\n)|\n/g, '\n');
}
-export function getErrorDataByCode(code: AstroErrorCodes | DiagnosticCode) {
- const entry = Object.entries(AstroErrorData).find((data) => data[1].code === code);
+export function getErrorDataByTitle(title: string) {
+ const entry = Object.entries(AstroErrorData).find((data) => data[1].title === title);
if (entry) {
return {
diff --git a/packages/astro/src/core/module-loader/loader.ts b/packages/astro/src/core/module-loader/loader.ts
index 84bb862d0fa4..39c24253ed26 100644
--- a/packages/astro/src/core/module-loader/loader.ts
+++ b/packages/astro/src/core/module-loader/loader.ts
@@ -42,6 +42,10 @@ export interface ModuleNode {
id: string | null;
url: string;
ssrModule: Record | null;
+ ssrTransformResult: {
+ deps?: string[];
+ dynamicDeps?: string[];
+ } | null;
ssrError: Error | null;
importedModules: Set;
}
diff --git a/packages/astro/src/core/redirects/component.ts b/packages/astro/src/core/redirects/component.ts
index f76b82517887..d10cae4feed5 100644
--- a/packages/astro/src/core/redirects/component.ts
+++ b/packages/astro/src/core/redirects/component.ts
@@ -1,4 +1,4 @@
-import type { AstroMiddlewareInstance, ComponentInstance } from '../../@types/astro';
+import type { ComponentInstance } from '../../@types/astro';
import type { SinglePageBuiltModule } from '../build/types';
// A stub of a component instance for a given route
@@ -10,12 +10,8 @@ export const RedirectComponentInstance: ComponentInstance = {
},
};
-const StaticMiddlewareInstance: AstroMiddlewareInstance = {
- onRequest: (ctx, next) => next(),
-};
-
export const RedirectSinglePageBuiltModule: SinglePageBuiltModule = {
page: () => Promise.resolve(RedirectComponentInstance),
- middleware: StaticMiddlewareInstance,
+ onRequest: (ctx, next) => next(),
renderers: [],
};
diff --git a/packages/astro/src/core/render/context.ts b/packages/astro/src/core/render/context.ts
index 90aaae0d2029..a43650a556cb 100644
--- a/packages/astro/src/core/render/context.ts
+++ b/packages/astro/src/core/render/context.ts
@@ -7,9 +7,12 @@ import type {
SSRElement,
SSRResult,
} from '../../@types/astro';
+import { AstroError, AstroErrorData } from '../errors/index.js';
import { getParamsAndPropsOrThrow } from './core.js';
import type { Environment } from './environment';
+const clientLocalsSymbol = Symbol.for('astro.locals');
+
/**
* The RenderContext represents the parts of rendering that are specific to one request.
*/
@@ -27,6 +30,7 @@ export interface RenderContext {
cookies?: AstroCookies;
params: Params;
props: Props;
+ locals?: object;
}
export type CreateRenderContextArgs = Partial & {
@@ -51,7 +55,8 @@ export async function createRenderContext(
logging: options.env.logging,
ssr: options.env.ssr,
});
- return {
+
+ let context = {
...options,
origin,
pathname,
@@ -59,4 +64,21 @@ export async function createRenderContext(
params,
props,
};
+
+ // We define a custom property, so we can check the value passed to locals
+ Object.defineProperty(context, 'locals', {
+ enumerable: true,
+ get() {
+ return Reflect.get(request, clientLocalsSymbol);
+ },
+ set(val) {
+ if (typeof val !== 'object') {
+ throw new AstroError(AstroErrorData.LocalsNotAnObject);
+ } else {
+ Reflect.set(request, clientLocalsSymbol, val);
+ }
+ },
+ });
+
+ return context;
}
diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts
index 282c78f2b903..91b668479b0a 100644
--- a/packages/astro/src/core/render/core.ts
+++ b/packages/astro/src/core/render/core.ts
@@ -1,4 +1,4 @@
-import type { APIContext, ComponentInstance, Params, Props, RouteData } from '../../@types/astro';
+import type { AstroCookies, ComponentInstance, Params, Props, RouteData } from '../../@types/astro';
import { renderPage as runtimeRenderPage } from '../../runtime/server/index.js';
import { attachToResponse } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
@@ -108,15 +108,15 @@ export type RenderPage = {
mod: ComponentInstance;
renderContext: RenderContext;
env: Environment;
- apiContext?: APIContext;
isCompressHTML?: boolean;
+ cookies: AstroCookies;
};
export async function renderPage({
mod,
renderContext,
env,
- apiContext,
+ cookies,
isCompressHTML = false,
}: RenderPage) {
if (routeIsRedirect(renderContext.route)) {
@@ -133,8 +133,6 @@ export async function renderPage({
if (!Component)
throw new Error(`Expected an exported Astro component but received typeof ${typeof Component}`);
- let locals = apiContext?.locals ?? {};
-
const result = createResult({
adapterName: env.adapterName,
links: renderContext.links,
@@ -155,8 +153,8 @@ export async function renderPage({
scripts: renderContext.scripts,
ssr: env.ssr,
status: renderContext.status ?? 200,
- cookies: apiContext?.cookies,
- locals,
+ cookies,
+ locals: renderContext.locals ?? {},
});
// Support `export const components` for `MDX` pages
diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts
index c0113739285a..67d0b0581266 100644
--- a/packages/astro/src/core/render/dev/index.ts
+++ b/packages/astro/src/core/render/dev/index.ts
@@ -180,22 +180,31 @@ export async function renderPage(options: SSROptions): Promise {
mod,
env,
});
+ const apiContext = createAPIContext({
+ request: options.request,
+ params: renderContext.params,
+ props: renderContext.props,
+ adapterName: options.env.adapterName,
+ });
if (options.middleware) {
if (options.middleware && options.middleware.onRequest) {
- const apiContext = createAPIContext({
- request: options.request,
- params: renderContext.params,
- props: renderContext.props,
- adapterName: options.env.adapterName,
- });
-
const onRequest = options.middleware.onRequest as MiddlewareResponseHandler;
const response = await callMiddleware(env.logging, onRequest, apiContext, () => {
- return coreRenderPage({ mod, renderContext, env: options.env, apiContext });
+ return coreRenderPage({
+ mod,
+ renderContext,
+ env: options.env,
+ cookies: apiContext.cookies,
+ });
});
return response;
}
}
- return await coreRenderPage({ mod, renderContext, env: options.env }); // NOTE: without "await", errors wonβt get caught below
+ return await coreRenderPage({
+ mod,
+ renderContext,
+ env: options.env,
+ cookies: apiContext.cookies,
+ }); // NOTE: without "await", errors wonβt get caught below
}
diff --git a/packages/astro/src/core/render/dev/vite.ts b/packages/astro/src/core/render/dev/vite.ts
index fe4d3f7916b2..39df7d269c93 100644
--- a/packages/astro/src/core/render/dev/vite.ts
+++ b/packages/astro/src/core/render/dev/vite.ts
@@ -41,48 +41,50 @@ export async function* crawlGraph(
continue;
}
if (id === entry.id) {
+ const urlDeps = getDepsFromEntry(entry);
scanned.add(id);
const entryIsStyle = isCSSRequest(id);
for (const importedModule of entry.importedModules) {
- // A propagation stopping point is a module with the ?astroPropagatedAssets flag.
- // When we encounter one of these modules we don't want to continue traversing.
- let isPropagationStoppingPoint = false;
+ if (!importedModule.id) continue;
+
// some dynamically imported modules are *not* server rendered in time
// to only SSR modules that we can safely transform, we check against
// a list of file extensions based on our built-in vite plugins
- if (importedModule.id) {
- // Strip special query params like "?content".
- // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths.
- // For example, `virtual:image-loader` if you don't have the plugin installed.
- const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, '');
- // If the entry is a style, skip any modules that are not also styles.
- // Tools like Tailwind might add HMR dependencies as `importedModules`
- // but we should skip them--they aren't really imported. Without this,
- // every hoisted script in the project is added to every page!
- if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
- continue;
- }
- const isFileTypeNeedingSSR = fileExtensionsToSSR.has(
- npath.extname(importedModulePathname)
- );
- isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id);
- if (
- isFileTypeNeedingSSR &&
- // Should not SSR a module with ?astroPropagatedAssets
- !isPropagationStoppingPoint
- ) {
- const mod = loader.getModuleById(importedModule.id);
- if (!mod?.ssrModule) {
- try {
- await loader.import(importedModule.id);
- } catch {
- /** Likely an out-of-date module entry! Silently continue. */
- }
+
+ // Strip special query params like "?content".
+ // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths.
+ // For example, `virtual:image-loader` if you don't have the plugin installed.
+ const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, '');
+ // If the entry is a style, skip any modules that are not also styles.
+ // Tools like Tailwind might add HMR dependencies as `importedModules`
+ // but we should skip them--they aren't really imported. Without this,
+ // every hoisted script in the project is added to every page!
+ if (entryIsStyle && !isCSSRequest(importedModulePathname)) {
+ continue;
+ }
+
+ const isFileTypeNeedingSSR = fileExtensionsToSSR.has(npath.extname(importedModulePathname));
+ // A propagation stopping point is a module with the ?astroPropagatedAssets flag.
+ // When we encounter one of these modules we don't want to continue traversing.
+ const isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id);
+ if (
+ isFileTypeNeedingSSR &&
+ // Should not SSR a module with ?astroPropagatedAssets
+ !isPropagationStoppingPoint
+ ) {
+ const mod = loader.getModuleById(importedModule.id);
+ if (!mod?.ssrModule) {
+ try {
+ await loader.import(importedModule.id);
+ } catch {
+ /** Likely an out-of-date module entry! Silently continue. */
}
}
}
- if (!isPropagationStoppingPoint) {
+
+ // Make sure the `importedModule` traversed is explicitly imported by the user, and not by HMR
+ if (urlDeps.includes(importedModule.url) && !isPropagationStoppingPoint) {
importedModules.add(importedModule);
}
}
@@ -100,3 +102,11 @@ export async function* crawlGraph(
yield* crawlGraph(loader, importedModule.id, false, scanned);
}
}
+
+function getDepsFromEntry(entry: ModuleNode) {
+ let deps = entry.ssrTransformResult?.deps ?? [];
+ if (entry.ssrTransformResult?.dynamicDeps) {
+ deps = deps.concat(entry.ssrTransformResult.dynamicDeps);
+ }
+ return deps.map((dep) => unwrapId(dep));
+}
diff --git a/packages/astro/src/core/render/ssr-element.ts b/packages/astro/src/core/render/ssr-element.ts
index 84b0ab531293..2d9bf9ae8d59 100644
--- a/packages/astro/src/core/render/ssr-element.ts
+++ b/packages/astro/src/core/render/ssr-element.ts
@@ -1,13 +1,12 @@
-import slashify from 'slash';
import type { SSRElement } from '../../@types/astro';
-import { joinPaths, prependForwardSlash } from '../../core/path.js';
+import { joinPaths, prependForwardSlash, slash } from '../../core/path.js';
import type { StylesheetAsset } from '../app/types';
export function createAssetLink(href: string, base?: string, assetsPrefix?: string): string {
if (assetsPrefix) {
- return joinPaths(assetsPrefix, slashify(href));
+ return joinPaths(assetsPrefix, slash(href));
} else if (base) {
- return prependForwardSlash(joinPaths(base, slashify(href)));
+ return prependForwardSlash(joinPaths(base, slash(href)));
} else {
return href;
}
diff --git a/packages/astro/src/core/request.ts b/packages/astro/src/core/request.ts
index d8ac9033db1a..d229ceaa4c84 100644
--- a/packages/astro/src/core/request.ts
+++ b/packages/astro/src/core/request.ts
@@ -13,6 +13,7 @@ export interface CreateRequestOptions {
body?: RequestBody | undefined;
logging: LogOptions;
ssr: boolean;
+ locals?: object | undefined;
}
const clientAddressSymbol = Symbol.for('astro.clientAddress');
@@ -26,6 +27,7 @@ export function createRequest({
body = undefined,
logging,
ssr,
+ locals,
}: CreateRequestOptions): Request {
let headersObj =
headers instanceof Headers
@@ -66,7 +68,7 @@ export function createRequest({
Reflect.set(request, clientAddressSymbol, clientAddress);
}
- Reflect.set(request, clientLocalsSymbol, {});
+ Reflect.set(request, clientLocalsSymbol, locals ?? {});
return request;
}
diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts
index 4a998fee930c..b5a6831643a5 100644
--- a/packages/astro/src/core/routing/manifest/create.ts
+++ b/packages/astro/src/core/routing/manifest/create.ts
@@ -11,12 +11,11 @@ import type { LogOptions } from '../../logger/core';
import nodeFs from 'fs';
import { createRequire } from 'module';
import path from 'path';
-import slash from 'slash';
import { fileURLToPath } from 'url';
import { getPrerenderDefault } from '../../../prerender/utils.js';
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js';
import { warn } from '../../logger/core.js';
-import { removeLeadingForwardSlash } from '../../path.js';
+import { removeLeadingForwardSlash, slash } from '../../path.js';
import { resolvePages } from '../../util.js';
import { getRouteGenerator } from './generator.js';
const require = createRequire(import.meta.url);
@@ -387,7 +386,7 @@ export function createRouteManifest(
comparator(injectedRouteToItem({ config, cwd }, a), injectedRouteToItem({ config, cwd }, b))
)
.reverse() // prepend to the routes array from lowest to highest priority
- .forEach(({ pattern: name, entryPoint }) => {
+ .forEach(({ pattern: name, entryPoint, prerender: prerenderInjected }) => {
let resolved: string;
try {
resolved = require.resolve(entryPoint, { paths: [cwd || fileURLToPath(config.root)] });
@@ -440,7 +439,7 @@ export function createRouteManifest(
component,
generate,
pathname: pathname || void 0,
- prerender,
+ prerender: prerenderInjected ?? prerender,
});
});
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 403d41527626..2529e89c2439 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -1,13 +1,12 @@
import fs from 'fs';
import path from 'path';
-import slash from 'slash';
import { fileURLToPath } from 'url';
import { normalizePath } from 'vite';
import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro';
import { isServerLikeOutput } from '../prerender/utils.js';
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js';
import type { ModuleLoader } from './module-loader';
-import { prependForwardSlash, removeTrailingForwardSlash } from './path.js';
+import { prependForwardSlash, removeTrailingForwardSlash, slash } from './path.js';
/** Returns true if argument is an object of any prototype/class (but not null). */
export function isObject(value: unknown): value is Record {
@@ -90,15 +89,18 @@ export function parseNpmName(
* Windows: C:/Users/astro/code/my-project/src/pages/index.astro
*/
export function viteID(filePath: URL): string {
- return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/');
+ return slash(fileURLToPath(filePath) + filePath.search);
}
export const VALID_ID_PREFIX = `/@id/`;
+export const NULL_BYTE_PLACEHOLDER = `__x00__`;
-// Strip valid id prefix. This is prepended to resolved Ids that are
-// not valid browser import specifiers by the importAnalysis plugin.
+// Strip valid id prefix and replace null byte placeholder. Both are prepended to resolved ids
+// as they are not valid browser import specifiers (by the Vite's importAnalysis plugin)
export function unwrapId(id: string): string {
- return id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length) : id;
+ return id.startsWith(VALID_ID_PREFIX)
+ ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\0')
+ : id;
}
export function resolvePages(config: AstroConfig) {
diff --git a/packages/astro/src/events/error.ts b/packages/astro/src/events/error.ts
index 2c2c857b37f6..73ac2b5e410e 100644
--- a/packages/astro/src/events/error.ts
+++ b/packages/astro/src/events/error.ts
@@ -1,11 +1,10 @@
import type { ZodError } from 'zod';
+import type { ErrorData } from '../core/errors/errors-data.js';
import { AstroError, AstroErrorData, type ErrorWithMetadata } from '../core/errors/index.js';
-import { getErrorDataByCode } from '../core/errors/utils.js';
const EVENT_ERROR = 'ASTRO_CLI_ERROR';
interface ErrorEventPayload {
- code: number | undefined;
name: string;
isFatal: boolean;
plugin?: string | undefined;
@@ -46,7 +45,6 @@ export function eventConfigError({
isFatal: boolean;
}): { eventName: string; payload: ConfigErrorEventPayload }[] {
const payload: ConfigErrorEventPayload = {
- code: AstroErrorData.UnknownConfigError.code,
name: 'ZodError',
isFatal,
isConfig: true,
@@ -66,10 +64,9 @@ export function eventError({
isFatal: boolean;
}): { eventName: string; payload: ErrorEventPayload }[] {
const errorData =
- AstroError.is(err) && err.errorCode ? getErrorDataByCode(err.errorCode)?.data : undefined;
+ AstroError.is(err) && (AstroErrorData[err.name as keyof typeof AstroErrorData] as ErrorData);
const payload: ErrorEventPayload = {
- code: err.code || err.errorCode || AstroErrorData.UnknownError.code,
name: err.name,
plugin: err.plugin,
cliCommand: cmd,
diff --git a/packages/astro/src/events/index.ts b/packages/astro/src/events/index.ts
index 31e549ad7bdd..7af647d449e5 100644
--- a/packages/astro/src/events/index.ts
+++ b/packages/astro/src/events/index.ts
@@ -1,19 +1,10 @@
import { AstroTelemetry } from '@astrojs/telemetry';
-import { createRequire } from 'module';
+import { version as viteVersion } from 'vite';
import { ASTRO_VERSION } from '../core/constants.js';
-const require = createRequire(import.meta.url);
-
-function getViteVersion() {
- try {
- const { version } = require('vite/package.json');
- return version;
- } catch (e) {}
- return undefined;
-}
export const telemetry = new AstroTelemetry({
astroVersion: ASTRO_VERSION,
- viteVersion: getViteVersion(),
+ viteVersion,
});
export * from './error.js';
diff --git a/packages/astro/src/events/session.ts b/packages/astro/src/events/session.ts
index f2c26d980750..706779d4b8c2 100644
--- a/packages/astro/src/events/session.ts
+++ b/packages/astro/src/events/session.ts
@@ -83,7 +83,10 @@ export function eventCliSession(
) ?? []),
] as string[],
adapter: userConfig?.adapter?.name ?? null,
- integrations: (userConfig?.integrations ?? []).filter(Boolean).map((i: any) => i?.name),
+ integrations: (userConfig?.integrations ?? [])
+ .filter(Boolean)
+ .flat()
+ .map((i: any) => i?.name),
trailingSlash: userConfig?.trailingSlash,
build: userConfig?.build
? {
diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts
index 53a75fbea1ad..f0abd1576263 100644
--- a/packages/astro/src/integrations/index.ts
+++ b/packages/astro/src/integrations/index.ts
@@ -19,7 +19,6 @@ import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.j
import { mergeConfig } from '../core/config/config.js';
import { info, type LogOptions } from '../core/logger/core.js';
import { isServerLikeOutput } from '../prerender/utils.js';
-import { mdxContentEntryType } from '../vite-plugin-markdown/content-entry-type.js';
async function withTakingALongTimeMsg({
name,
@@ -150,15 +149,6 @@ export async function runHookConfigSetup({
logging,
});
- // Add MDX content entry type to support older `@astrojs/mdx` versions
- // TODO: remove in next Astro minor release
- if (
- integration.name === '@astrojs/mdx' &&
- !updatedSettings.contentEntryTypes.find((c) => c.extensions.includes('.mdx'))
- ) {
- addContentEntryType(mdxContentEntryType);
- }
-
// Add custom client directives to settings, waiting for compiled code by esbuild
for (const [name, compiled] of addedClientDirectives) {
updatedSettings.clientDirectives.set(name, await compiled);
@@ -286,7 +276,9 @@ export async function runHookBuildSetup({
pages: Map;
target: 'server' | 'client';
logging: LogOptions;
-}) {
+}): Promise {
+ let updatedConfig = vite;
+
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:setup']) {
await withTakingALongTimeMsg({
@@ -296,29 +288,33 @@ export async function runHookBuildSetup({
pages,
target,
updateConfig: (newConfig) => {
- mergeConfig(vite, newConfig);
+ updatedConfig = mergeConfig(updatedConfig, newConfig);
},
}),
logging,
});
}
}
+
+ return updatedConfig;
}
export async function runHookBuildSsr({
config,
manifest,
logging,
+ entryPoints,
}: {
config: AstroConfig;
manifest: SerializedSSRManifest;
logging: LogOptions;
+ entryPoints: Map;
}) {
for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:ssr']) {
await withTakingALongTimeMsg({
name: integration.name,
- hookResult: integration.hooks['astro:build:ssr']({ manifest }),
+ hookResult: integration.hooks['astro:build:ssr']({ manifest, entryPoints }),
logging,
});
}
diff --git a/packages/astro/src/jsx/babel.ts b/packages/astro/src/jsx/babel.ts
index 9caf42aaf33a..1ccd05fbc4ca 100644
--- a/packages/astro/src/jsx/babel.ts
+++ b/packages/astro/src/jsx/babel.ts
@@ -192,7 +192,7 @@ export default function astroJSX(): PluginObj {
) {
return;
}
- const parent = path.findParent((n) => t.isJSXElement(n))!;
+ const parent = path.findParent((n) => t.isJSXElement(n.node))!;
const parentNode = parent.node as t.JSXElement;
const tagName = getTagName(parentNode);
if (!isComponent(tagName)) return;
@@ -249,9 +249,9 @@ export default function astroJSX(): PluginObj {
}
},
JSXIdentifier(path, state) {
- const isAttr = path.findParent((n) => t.isJSXAttribute(n));
+ const isAttr = path.findParent((n) => t.isJSXAttribute(n.node));
if (isAttr) return;
- const parent = path.findParent((n) => t.isJSXElement(n))!;
+ const parent = path.findParent((n) => t.isJSXElement(n.node))!;
const parentNode = parent.node as t.JSXElement;
const tagName = getTagName(parentNode);
if (!isComponent(tagName)) return;
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index 9be1c81afc05..a610b4b743da 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -21,6 +21,8 @@ import { isServerLikeOutput } from '../prerender/utils.js';
import { log404 } from './common.js';
import { handle404Response, writeSSRResult, writeWebResponse } from './response.js';
+const clientLocalsSymbol = Symbol.for('astro.locals');
+
type AsyncReturnType Promise> = T extends (
...args: any
) => Promise
@@ -153,6 +155,7 @@ export async function handleRoute(
logging,
ssr: buildingToSSR,
clientAddress: buildingToSSR ? req.socket.remoteAddress : undefined,
+ locals: Reflect.get(req, clientLocalsSymbol), // Allows adapters to pass in locals in dev mode.
});
// Set user specified headers to response object.
diff --git a/packages/astro/src/vite-plugin-astro/compile.ts b/packages/astro/src/vite-plugin-astro/compile.ts
index 799e09e8e565..6bee4f672ae0 100644
--- a/packages/astro/src/vite-plugin-astro/compile.ts
+++ b/packages/astro/src/vite-plugin-astro/compile.ts
@@ -41,6 +41,8 @@ export async function cachedFullCompilation({
tsconfigRaw: {
compilerOptions: {
// Ensure client:only imports are treeshaken
+ // @ts-expect-error anticipate esbuild 0.18 feature
+ verbatimModuleSyntax: false,
importsNotUsedAsValues: 'remove',
},
},
diff --git a/packages/astro/src/vite-plugin-config-alias/README.md b/packages/astro/src/vite-plugin-config-alias/README.md
index 85971c90aa0a..3b470adeda33 100644
--- a/packages/astro/src/vite-plugin-config-alias/README.md
+++ b/packages/astro/src/vite-plugin-config-alias/README.md
@@ -18,9 +18,9 @@ Consider the following example configuration:
With this configuration, the following imports would map to the same location.
```js
-import Test from '../components/Test.astro'
+import Test from '../components/Test.astro';
-import Test from 'components/Test.astro'
+import Test from 'components/Test.astro';
-import Test from 'components:Test'
+import Test from 'components:Test';
```
diff --git a/packages/astro/src/vite-plugin-jsx/index.ts b/packages/astro/src/vite-plugin-jsx/index.ts
index 91aa63909d2d..9364a4e0b77a 100644
--- a/packages/astro/src/vite-plugin-jsx/index.ts
+++ b/packages/astro/src/vite-plugin-jsx/index.ts
@@ -160,6 +160,8 @@ export default function jsx({ settings, logging }: AstroPluginJSXOptions): Plugi
tsconfigRaw: {
compilerOptions: {
// Ensure client:only imports are treeshaken
+ // @ts-expect-error anticipate esbuild 0.18 feature
+ verbatimModuleSyntax: false,
importsNotUsedAsValues: 'remove',
},
},
diff --git a/packages/astro/src/vite-plugin-load-fallback/index.ts b/packages/astro/src/vite-plugin-load-fallback/index.ts
index 7c853245be34..084cb885f7ef 100644
--- a/packages/astro/src/vite-plugin-load-fallback/index.ts
+++ b/packages/astro/src/vite-plugin-load-fallback/index.ts
@@ -1,7 +1,7 @@
import nodeFs from 'fs';
import npath from 'path';
-import slashify from 'slash';
import type * as vite from 'vite';
+import { slash } from '../core/path.js';
type NodeFileSystemModule = typeof nodeFs;
@@ -47,7 +47,7 @@ export default function loadFallbackPlugin({
async resolveId(id, parent) {
// See if this can be loaded from our fs
if (parent) {
- const candidateId = npath.posix.join(npath.posix.dirname(slashify(parent)), id);
+ const candidateId = npath.posix.join(npath.posix.dirname(slash(parent)), id);
try {
// Check to see if this file exists and is not a directory.
const stats = await fs.promises.stat(candidateId);
diff --git a/packages/astro/src/vite-plugin-markdown/content-entry-type.ts b/packages/astro/src/vite-plugin-markdown/content-entry-type.ts
index a3489c940132..92bb118d43a7 100644
--- a/packages/astro/src/vite-plugin-markdown/content-entry-type.ts
+++ b/packages/astro/src/vite-plugin-markdown/content-entry-type.ts
@@ -16,32 +16,3 @@ export const markdownContentEntryType: ContentEntryType = {
// We need to handle propagation for Markdown because they support layouts which will bring in styles.
handlePropagation: true,
};
-
-/**
- * MDX content type for compatibility with older `@astrojs/mdx` versions
- * TODO: remove in next Astro minor release
- */
-export const mdxContentEntryType: ContentEntryType = {
- extensions: ['.mdx'],
- async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) {
- const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl));
- return {
- data: parsed.data,
- body: parsed.content,
- slug: parsed.data.slug,
- rawData: parsed.matter,
- };
- },
- // MDX can import scripts and styles,
- // so wrap all MDX files with script / style propagation checks
- handlePropagation: true,
- contentModuleTypes: `declare module 'astro:content' {
- interface Render {
- '.mdx': Promise<{
- Content: import('astro').MarkdownInstance<{}>['Content'];
- headings: import('astro').MarkdownHeading[];
- remarkPluginFrontmatter: Record;
- }>;
- }
-}`,
-};
diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts
index c3f08f2c4e15..fcdaf04ea147 100644
--- a/packages/astro/src/vite-plugin-markdown/index.ts
+++ b/packages/astro/src/vite-plugin-markdown/index.ts
@@ -27,7 +27,6 @@ function safeMatter(source: string, id: string) {
return matter(source);
} catch (err: any) {
const markdownError = new MarkdownError({
- code: AstroErrorData.UnknownMarkdownError.code,
message: err.message,
stack: err.stack,
location: {
@@ -36,7 +35,6 @@ function safeMatter(source: string, id: string) {
});
if (err.name === 'YAMLException') {
- markdownError.setErrorCode(AstroErrorData.MarkdownFrontmatterParseError.code);
markdownError.setLocation({
file: id,
line: err.mark.line,
diff --git a/packages/astro/test/astro-scripts.test.js b/packages/astro/test/astro-scripts.test.js
index da3fc7c6660d..ae2268d8097f 100644
--- a/packages/astro/test/astro-scripts.test.js
+++ b/packages/astro/test/astro-scripts.test.js
@@ -1,7 +1,6 @@
import { expect } from 'chai';
import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
-import { tailwind } from './fixtures/astro-scripts/deps.mjs';
describe('Scripts (hoisted and not)', () => {
describe('Build', () => {
@@ -141,7 +140,6 @@ describe('Scripts (hoisted and not)', () => {
fixture = await loadFixture({
root: './fixtures/astro-scripts/',
integrations: [
- tailwind(),
{
name: 'test-script-injection-with-injected-route',
hooks: {
diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js
index f7a537e9809a..0edc26426343 100644
--- a/packages/astro/test/core-image.test.js
+++ b/packages/astro/test/core-image.test.js
@@ -4,8 +4,8 @@ import { basename } from 'node:path';
import { Writable } from 'node:stream';
import { removeDir } from '../dist/core/fs/index.js';
import testAdapter from './test-adapter.js';
-import { loadFixture } from './test-utils.js';
import { testImageService } from './test-image-service.js';
+import { loadFixture } from './test-utils.js';
describe('astro:image', () => {
/** @type {import('./test-utils').Fixture} */
@@ -118,7 +118,7 @@ describe('astro:image', () => {
expect(logs[0].message).to.contain('Received unsupported format');
});
- it("errors when an ESM imported image's src is passed to Image/getImage instead of the full import ssss", async () => {
+ it("errors when an ESM imported image's src is passed to Image/getImage instead of the full import", async () => {
logs.length = 0;
let res = await fixture.fetch('/error-image-src-passed');
await res.text();
diff --git a/packages/astro/test/custom-404-injected-from-dep.test.js b/packages/astro/test/custom-404-injected-from-dep.test.js
new file mode 100644
index 000000000000..d9a822f4ed61
--- /dev/null
+++ b/packages/astro/test/custom-404-injected-from-dep.test.js
@@ -0,0 +1,22 @@
+import { expect } from 'chai';
+import { loadFixture } from './test-utils.js';
+
+describe('Custom 404 with injectRoute from dependency', () => {
+ describe('build', () => {
+ /** @type {import('./test-utils.js').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/custom-404-injected-from-dep/',
+ site: 'http://example.com',
+ });
+ await fixture.build();
+ });
+
+ it('Build succeeds', async () => {
+ const html = await fixture.readFile('/404.html');
+ expect(html).to.contain('');
+ });
+ });
+});
diff --git a/packages/astro/test/dynamic-endpoint-collision.test.js b/packages/astro/test/dynamic-endpoint-collision.test.js
index e1f4b2f03ea7..c0a11b5f8372 100644
--- a/packages/astro/test/dynamic-endpoint-collision.test.js
+++ b/packages/astro/test/dynamic-endpoint-collision.test.js
@@ -18,7 +18,7 @@ describe('Dynamic endpoint collision', () => {
});
it('throw error when dynamic endpoint has path collision', async () => {
- expect(errorMsg.errorCode).to.eq(3026);
+ expect(errorMsg.name).to.eq('PrerenderDynamicEndpointPathCollide');
});
});
diff --git a/packages/astro/test/events.test.js b/packages/astro/test/events.test.js
index 98eaa2d54097..47f37b645e9a 100644
--- a/packages/astro/test/events.test.js
+++ b/packages/astro/test/events.test.js
@@ -385,6 +385,14 @@ describe('Events', () => {
expect(payload.config.integrations.length).to.equal(0);
});
+ it('finds names for integration arrays', () => {
+ const config = {
+ integrations: [{ name: 'foo' }, [{ name: 'bar' }, { name: 'baz' }]],
+ };
+ const [{ payload }] = events.eventCliSession({ cliCommand: 'dev' }, config);
+ expect(payload.config.integrations).to.deep.equal(['foo', 'bar', 'baz']);
+ });
+
it('includes cli flags in payload', () => {
const config = {};
const flags = {
@@ -427,7 +435,6 @@ describe('Events', () => {
expect(event).to.deep.equal({
eventName: 'ASTRO_CLI_ERROR',
payload: {
- code: AstroErrorData.UnknownConfigError.code,
name: 'ZodError',
isFatal: true,
isConfig: true,
@@ -451,7 +458,6 @@ describe('Events', () => {
expect(event).to.deep.equal({
eventName: 'ASTRO_CLI_ERROR',
payload: {
- code: 1234,
plugin: 'TEST PLUGIN',
name: 'Error',
isFatal: true,
@@ -477,7 +483,6 @@ describe('Events', () => {
anonymousMessageHint:
'`Astro.clientAddress` is not available in the `ADAPTER_NAME` adapter. File an issue with the adapter to add support.',
cliCommand: 'COMMAND_NAME',
- code: 3002,
isFatal: false,
name: 'ClientAddressNotAvailable',
plugin: undefined,
@@ -494,7 +499,6 @@ describe('Events', () => {
expect(event).to.deep.equal({
eventName: 'ASTRO_CLI_ERROR',
payload: {
- code: AstroErrorData.UnknownError.code,
name: 'Error',
plugin: undefined,
isFatal: false,
diff --git a/packages/astro/test/fixtures/0-css/package.json b/packages/astro/test/fixtures/0-css/package.json
index bec81c0fb616..4a5d7734367c 100644
--- a/packages/astro/test/fixtures/0-css/package.json
+++ b/packages/astro/test/fixtures/0-css/package.json
@@ -9,7 +9,7 @@
"astro": "workspace:*",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "svelte": "^3.48.0",
- "vue": "^3.2.39"
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json
index 6fcb9106ce3a..d4113b4fc8ff 100644
--- a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json
+++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/svelte": "workspace:*",
"astro": "workspace:*",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/alias-tsconfig/package.json b/packages/astro/test/fixtures/alias-tsconfig/package.json
index dc4b7e7b9ea2..4abb4367fe02 100644
--- a/packages/astro/test/fixtures/alias-tsconfig/package.json
+++ b/packages/astro/test/fixtures/alias-tsconfig/package.json
@@ -6,6 +6,6 @@
"@astrojs/svelte": "workspace:*",
"@test/namespace-package": "workspace:*",
"astro": "workspace:*",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/alias/package.json b/packages/astro/test/fixtures/alias/package.json
index c3f6f56d83a3..e543a6967bc9 100644
--- a/packages/astro/test/fixtures/alias/package.json
+++ b/packages/astro/test/fixtures/alias/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/svelte": "workspace:*",
"astro": "workspace:*",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs b/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs
index 869cf811b06d..7393b72b8aff 100644
--- a/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs
+++ b/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs
@@ -1,15 +1,19 @@
import { defineConfig } from 'astro/config';
-import react from '@astrojs/react'
+import react from '@astrojs/react';
+import { testImageService } from '../../test-image-service.js';
// https://astro.build/config
export default defineConfig({
- // test custom base to make sure things work
- base: '/custom-base',
- integrations: [react()],
- build: {
- assetsPrefix: 'http://localhost:4321'
- },
- experimental: {
- assets: true
- }
+ // test custom base to make sure things work
+ base: '/custom-base',
+ integrations: [react()],
+ build: {
+ assetsPrefix: 'http://localhost:4321',
+ },
+ experimental: {
+ assets: true,
+ },
+ image: {
+ service: testImageService(),
+ },
});
diff --git a/packages/astro/test/fixtures/astro-basic/package.json b/packages/astro/test/fixtures/astro-basic/package.json
index a6312565805d..c30c850dc7f0 100644
--- a/packages/astro/test/fixtures/astro-basic/package.json
+++ b/packages/astro/test/fixtures/astro-basic/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-children/package.json b/packages/astro/test/fixtures/astro-children/package.json
index 0ba89d0a9782..1f40029857dd 100644
--- a/packages/astro/test/fixtures/astro-children/package.json
+++ b/packages/astro/test/fixtures/astro-children/package.json
@@ -7,8 +7,8 @@
"@astrojs/svelte": "workspace:*",
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0",
- "svelte": "^3.48.0",
- "vue": "^3.2.39"
+ "preact": "^10.15.1",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/test/fixtures/astro-client-only/package.json b/packages/astro/test/fixtures/astro-client-only/package.json
index 219a1a6a7380..4ac537e042a8 100644
--- a/packages/astro/test/fixtures/astro-client-only/package.json
+++ b/packages/astro/test/fixtures/astro-client-only/package.json
@@ -9,6 +9,6 @@
"astro": "workspace:*",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-dynamic/package.json b/packages/astro/test/fixtures/astro-dynamic/package.json
index 844513ebfc42..1499fa7f35fe 100644
--- a/packages/astro/test/fixtures/astro-dynamic/package.json
+++ b/packages/astro/test/fixtures/astro-dynamic/package.json
@@ -8,6 +8,6 @@
"astro": "workspace:*",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "svelte": "^3.48.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-envs/package.json b/packages/astro/test/fixtures/astro-envs/package.json
index a90a9c01c0a2..c46f4d6814ac 100644
--- a/packages/astro/test/fixtures/astro-envs/package.json
+++ b/packages/astro/test/fixtures/astro-envs/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/vue": "workspace:*",
"astro": "workspace:*",
- "vue": "^3.2.39"
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/test/fixtures/astro-expr/package.json b/packages/astro/test/fixtures/astro-expr/package.json
index 31ecdeb13360..b9fc5565ec35 100644
--- a/packages/astro/test/fixtures/astro-expr/package.json
+++ b/packages/astro/test/fixtures/astro-expr/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-fallback/package.json b/packages/astro/test/fixtures/astro-fallback/package.json
index 31e7941edc4f..52d3f6731576 100644
--- a/packages/astro/test/fixtures/astro-fallback/package.json
+++ b/packages/astro/test/fixtures/astro-fallback/package.json
@@ -5,6 +5,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json b/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json
index 1b7fcc25b7a3..fd7f414c2f68 100644
--- a/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json
+++ b/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json
@@ -4,8 +4,8 @@
"private": true,
"dependencies": {
"astro": "workspace:*",
- "mdast-util-to-string": "^3.1.0",
+ "mdast-util-to-string": "^3.2.0",
"reading-time": "^1.5.0",
- "unist-util-visit": "^4.1.0"
+ "unist-util-visit": "^4.1.2"
}
}
diff --git a/packages/astro/test/fixtures/astro-scripts/astro.config.mjs b/packages/astro/test/fixtures/astro-scripts/astro.config.mjs
index e841c915cfed..f34407295d8a 100644
--- a/packages/astro/test/fixtures/astro-scripts/astro.config.mjs
+++ b/packages/astro/test/fixtures/astro-scripts/astro.config.mjs
@@ -1,8 +1,11 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
+import { fileURLToPath } from 'url';
export default defineConfig({
integrations: [
- tailwind()
- ]
-})
+ tailwind({
+ configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)),
+ }),
+ ],
+});
diff --git a/packages/astro/test/fixtures/astro-scripts/deps.mjs b/packages/astro/test/fixtures/astro-scripts/deps.mjs
deleted file mode 100644
index e6a090e7ba97..000000000000
--- a/packages/astro/test/fixtures/astro-scripts/deps.mjs
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default as tailwind } from '@astrojs/tailwind';
-
diff --git a/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs b/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs
new file mode 100644
index 000000000000..f5368a76ab04
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
diff --git a/packages/astro/test/fixtures/astro-slot-with-client/package.json b/packages/astro/test/fixtures/astro-slot-with-client/package.json
index 141bf165d008..9427f65ab3d4 100644
--- a/packages/astro/test/fixtures/astro-slot-with-client/package.json
+++ b/packages/astro/test/fixtures/astro-slot-with-client/package.json
@@ -2,8 +2,8 @@
"name": "@test/astro-slot-with-client",
"private": true,
"dependencies": {
- "astro": "workspace:*",
"@astrojs/preact": "workspace:*",
- "preact": "^10.11.0"
+ "astro": "workspace:*",
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/astro-slots-nested/package.json b/packages/astro/test/fixtures/astro-slots-nested/package.json
index 7e57372ec3bb..e0d74ee802ef 100644
--- a/packages/astro/test/fixtures/astro-slots-nested/package.json
+++ b/packages/astro/test/fixtures/astro-slots-nested/package.json
@@ -5,15 +5,15 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"@astrojs/react": "workspace:*",
- "@astrojs/vue": "workspace:*",
"@astrojs/solid-js": "workspace:*",
"@astrojs/svelte": "workspace:*",
+ "@astrojs/vue": "workspace:*",
"astro": "workspace:*",
+ "preact": "^10.15.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "solid-js": "^1.7.4",
- "svelte": "^3.58.0",
- "vue": "^3.2.47",
- "preact": "^10.13.2"
+ "solid-js": "^1.7.6",
+ "svelte": "^3.59.1",
+ "vue": "^3.3.4"
}
}
diff --git a/packages/astro/test/fixtures/before-hydration/package.json b/packages/astro/test/fixtures/before-hydration/package.json
index f04a39ae0944..0eaf3d77ae8f 100644
--- a/packages/astro/test/fixtures/before-hydration/package.json
+++ b/packages/astro/test/fixtures/before-hydration/package.json
@@ -4,6 +4,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/build-assets/package.json b/packages/astro/test/fixtures/build-assets/package.json
index 6dd278c2bcea..feb883935782 100644
--- a/packages/astro/test/fixtures/build-assets/package.json
+++ b/packages/astro/test/fixtures/build-assets/package.json
@@ -4,6 +4,6 @@
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.11.0"
+ "preact": "^10.15.1"
}
}
diff --git a/packages/astro/test/fixtures/component-library-shared/package.json b/packages/astro/test/fixtures/component-library-shared/package.json
index f5c344316685..5d87d1941de6 100644
--- a/packages/astro/test/fixtures/component-library-shared/package.json
+++ b/packages/astro/test/fixtures/component-library-shared/package.json
@@ -18,7 +18,7 @@
"astro": "workspace:*"
},
"dependencies": {
- "preact": "^10.11.0",
+ "preact": "^10.15.1",
"react": "^18.2.0"
}
}
diff --git a/packages/astro/test/fixtures/component-library/package.json b/packages/astro/test/fixtures/component-library/package.json
index 0a677ced2c1d..90b3cdf47554 100644
--- a/packages/astro/test/fixtures/component-library/package.json
+++ b/packages/astro/test/fixtures/component-library/package.json
@@ -8,9 +8,9 @@
"@astrojs/svelte": "workspace:*",
"@test/component-library-shared": "workspace:*",
"astro": "workspace:*",
- "preact": "^10.13.2",
+ "preact": "^10.15.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
- "svelte": "^3.58.0"
+ "svelte": "^3.59.1"
}
}
diff --git a/packages/astro/test/fixtures/content-collection-references/astro.config.mjs b/packages/astro/test/fixtures/content-collection-references/astro.config.mjs
index 913ddc87651f..7287a125921a 100644
--- a/packages/astro/test/fixtures/content-collection-references/astro.config.mjs
+++ b/packages/astro/test/fixtures/content-collection-references/astro.config.mjs
@@ -1,8 +1,12 @@
import { defineConfig } from 'astro/config';
+import { testImageService } from '../../test-image-service.js';
// https://astro.build/config
export default defineConfig({
- experimental: {
- assets: true
- },
+ experimental: {
+ assets: true,
+ },
+ image: {
+ service: testImageService(),
+ },
});
diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs b/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs
new file mode 100644
index 000000000000..840a9524cbdb
--- /dev/null
+++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs
@@ -0,0 +1,18 @@
+import { defineConfig } from 'astro/config';
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [
+ {
+ name: '404-integration',
+ hooks: {
+ 'astro:config:setup': ({ injectRoute }) => {
+ injectRoute({
+ pattern: '404',
+ entryPoint: '@test/custom-404-pkg/404.astro',
+ });
+ },
+ },
+ },
+ ],
+});
diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json b/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json
new file mode 100644
index 000000000000..6af83260253a
--- /dev/null
+++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/custom-404-injected-from-dep",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*",
+ "@test/custom-404-pkg": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro b/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro
new file mode 100644
index 000000000000..cf5ef9b586c6
--- /dev/null
+++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro
@@ -0,0 +1,11 @@
+---
+---
+
+
+
+ Custom 404
+
+
+
Home
+
+
diff --git a/packages/astro/test/fixtures/custom-404-pkg/404.astro b/packages/astro/test/fixtures/custom-404-pkg/404.astro
new file mode 100644
index 000000000000..63d560b0fb91
--- /dev/null
+++ b/packages/astro/test/fixtures/custom-404-pkg/404.astro
@@ -0,0 +1,13 @@
+---
+const canonicalURL = new URL(Astro.url.pathname, Astro.site);
+---
+
+
+
+ Not Found - Custom 404
+
+
+