summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/dull-carpets-breathe.md22
-rw-r--r--packages/astro/src/@types/astro.ts7
-rw-r--r--packages/astro/src/container/index.ts45
-rw-r--r--packages/astro/src/jsx/server.ts6
-rw-r--r--packages/astro/test/container.test.js12
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/astro.config.mjs (renamed from packages/astro/test/fixtures/container-react/astro.config.mjs)3
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/package.json (renamed from packages/astro/test/fixtures/container-react/package.json)4
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/src/components/button.jsx (renamed from packages/astro/test/fixtures/container-react/src/components/button.jsx)0
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/src/components/button.vue3
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/src/pages/react.ts (renamed from packages/astro/test/fixtures/container-react/src/pages/api.ts)4
-rw-r--r--packages/astro/test/fixtures/container-custom-renderers/src/pages/vue.ts10
-rw-r--r--packages/integrations/lit/package.json6
-rw-r--r--packages/integrations/lit/server.d.ts2
-rw-r--r--packages/integrations/lit/server.js1
-rw-r--r--packages/integrations/preact/src/server.ts7
-rw-r--r--packages/integrations/react/package.json12
-rw-r--r--packages/integrations/react/server-v17.js1
-rw-r--r--packages/integrations/react/server.d.ts2
-rw-r--r--packages/integrations/react/server.js1
-rw-r--r--packages/integrations/react/server17.d.ts2
-rw-r--r--packages/integrations/solid/src/server.ts6
-rw-r--r--packages/integrations/svelte/package.json14
-rw-r--r--packages/integrations/svelte/server-v5.d.ts2
-rw-r--r--packages/integrations/svelte/server.d.ts2
-rw-r--r--packages/integrations/vue/package.json6
-rw-r--r--packages/integrations/vue/server.d.ts2
-rw-r--r--packages/integrations/vue/server.js1
-rw-r--r--pnpm-lock.yaml8
28 files changed, 160 insertions, 31 deletions
diff --git a/.changeset/dull-carpets-breathe.md b/.changeset/dull-carpets-breathe.md
index 63aca3cef..b009e5ccf 100644
--- a/.changeset/dull-carpets-breathe.md
+++ b/.changeset/dull-carpets-breathe.md
@@ -1,5 +1,11 @@
---
'astro': patch
+'@astrojs/preact': minor
+'@astrojs/svelte': minor
+'@astrojs/react': minor
+'@astrojs/solid-js': minor
+'@astrojs/lit': minor
+'@astrojs/vue': minor
---
Adds a new function called `addServerRenderer` to the Container API. Use this function to manually store renderers inside the instance of your container.
@@ -14,10 +20,22 @@ import vueRenderer from '@astrojs/vue/server.js';
import ReactComponent from "../components/button.jsx"
import VueComponent from "../components/button.vue"
+// MDX runtime is contained inside the Astro
+import mdxRenderer from "@astrojs/jsx/serverr.js"
+
+// In case you need to import a custom renderer
+import customRenderer from "../renderers/custoRender.js";
+
export const GET: APIRoute = async (ctx) => {
const container = await experimental_AstroContainer.create();
- container.addServerRenderer("@astrojs/react", reactRenderer);
- container.addServerRenderer("@astrojs/vue", vueRenderer);
+ container.addServerRenderer({ renderer: reactRenderer });
+ container.addServerRenderer({ renderer: vueRenderer });
+ container.addServerRenderer({ renderer: customRenderer });
+ // You can pass a custom name too
+ container.addServerRenderer({
+ name: "customRenderer",
+ renderer: customRenderer
+ })
const vueComponent = await container.renderToString(VueComponent)
return await container.renderToResponse(Component);
}
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index 1fbb1c4dc..e0cc4dcad 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -2977,7 +2977,12 @@ export interface AstroRenderer {
jsxTransformOptions?: JSXTransformFn;
}
-export type SSRLoadedRendererValue = {
+export interface NamedSSRLoadedRendererValue extends SSRLoadedRendererValue {
+ name: string;
+}
+
+export interface SSRLoadedRendererValue {
+ name?: string;
check: AsyncRendererComponentFn<boolean>;
renderToStaticMarkup: AsyncRendererComponentFn<{
html: string;
diff --git a/packages/astro/src/container/index.ts b/packages/astro/src/container/index.ts
index 452f97738..97b922653 100644
--- a/packages/astro/src/container/index.ts
+++ b/packages/astro/src/container/index.ts
@@ -5,6 +5,7 @@ import type {
ComponentInstance,
ContainerImportRendererFn,
MiddlewareHandler,
+ NamedSSRLoadedRendererValue,
Props,
RouteData,
RouteType,
@@ -84,6 +85,16 @@ export type ContainerRenderOptions = {
props?: Props;
};
+export type AddServerRenderer =
+ | {
+ renderer: NamedSSRLoadedRendererValue;
+ name: never;
+ }
+ | {
+ renderer: SSRLoadedRendererValue;
+ name: string;
+ };
+
function createManifest(
manifest?: AstroContainerManifest,
renderers?: SSRLoadedRenderer[],
@@ -279,28 +290,38 @@ export class experimental_AstroContainer {
* ```js
* import reactRenderer from "@astrojs/react/server.js";
* import vueRenderer from "@astrojs/vue/server.js";
+ * import customRenderer from "../renderer/customRenderer.js";
* import { experimental_AstroContainer as AstroContainer } from "astro/container"
*
* const container = await AstroContainer.create();
- * container.addServerRenderer("@astrojs/react", reactRenderer);
- * container.addServerRenderer("@astrojs/vue", vueRenderer);
+ * container.addServerRenderer(reactRenderer);
+ * container.addServerRenderer(vueRenderer);
+ * container.addServerRenderer("customRenderer", customRenderer);
* ```
*
- * @param name The name of the renderer. The name **isn't** arbitrary, and it should match the name of the package.
- * @param renderer The server renderer exported by integration.
+ * @param options {object}
+ * @param options.name The name of the renderer. The name **isn't** arbitrary, and it should match the name of the package.
+ * @param options.renderer The server renderer exported by integration.
*/
- public addServerRenderer(name: string, renderer: SSRLoadedRendererValue) {
+ public addServerRenderer(options: AddServerRenderer): void {
+ const { renderer, name } = options;
if (!renderer.check || !renderer.renderToStaticMarkup) {
throw new Error(
"The renderer you passed isn't valid. A renderer is usually an object that exposes the `check` and `renderToStaticMarkup` functions.\n" +
"Usually, the renderer is exported by a /server.js entrypoint e.g. `import renderer from '@astrojs/react/server.js'`"
);
}
-
- this.#pipeline.manifest.renderers.push({
- name,
- ssr: renderer,
- });
+ if (isNamedRenderer(renderer)) {
+ this.#pipeline.manifest.renderers.push({
+ name: renderer.name,
+ ssr: renderer,
+ });
+ } else {
+ this.#pipeline.manifest.renderers.push({
+ name,
+ ssr: renderer,
+ });
+ }
}
// NOTE: we keep this private via TS instead via `#` so it's still available on the surface, so we can play with it.
@@ -473,3 +494,7 @@ export class experimental_AstroContainer {
return { default: componentFactory };
}
}
+
+function isNamedRenderer(renderer: any): renderer is NamedSSRLoadedRendererValue {
+ return !!renderer?.name;
+}
diff --git a/packages/astro/src/jsx/server.ts b/packages/astro/src/jsx/server.ts
index be55b0194..74857c490 100644
--- a/packages/astro/src/jsx/server.ts
+++ b/packages/astro/src/jsx/server.ts
@@ -1,6 +1,7 @@
import { AstroError, AstroUserError } from '../core/errors/errors.js';
import { AstroJSX, jsx } from '../jsx-runtime/index.js';
import { renderJSX } from '../runtime/server/jsx.js';
+import type { NamedSSRLoadedRendererValue } from '../@types/astro.js';
const slotName = (str: string) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
@@ -64,7 +65,10 @@ function throwEnhancedErrorIfMdxComponent(error: Error, Component: any) {
}
}
-export default {
+const renderer: NamedSSRLoadedRendererValue = {
+ name: 'astro:jsx',
check,
renderToStaticMarkup,
};
+
+export default renderer;
diff --git a/packages/astro/test/container.test.js b/packages/astro/test/container.test.js
index dd17cc565..72d233ce4 100644
--- a/packages/astro/test/container.test.js
+++ b/packages/astro/test/container.test.js
@@ -238,7 +238,7 @@ describe('Container with renderers', () => {
let app;
before(async () => {
fixture = await loadFixture({
- root: new URL('./fixtures/container-react/', import.meta.url),
+ root: new URL('./fixtures/container-custom-renderers/', import.meta.url),
output: 'server',
adapter: testAdapter(),
});
@@ -247,10 +247,18 @@ describe('Container with renderers', () => {
});
it('the endpoint should return the HTML of the React component', async () => {
- const request = new Request('https://example.com/api');
+ const request = new Request('https://example.com/react');
const response = await app.render(request);
const html = await response.text();
assert.match(html, /I am a react button/);
});
+
+ it('the endpoint should return the HTML of the Vue component', async () => {
+ const request = new Request('https://example.com/vue');
+ const response = await app.render(request);
+ const html = await response.text();
+
+ assert.match(html, /I am a vue button/);
+ });
});
diff --git a/packages/astro/test/fixtures/container-react/astro.config.mjs b/packages/astro/test/fixtures/container-custom-renderers/astro.config.mjs
index e7ce274c0..d85e1d6f4 100644
--- a/packages/astro/test/fixtures/container-react/astro.config.mjs
+++ b/packages/astro/test/fixtures/container-custom-renderers/astro.config.mjs
@@ -1,7 +1,8 @@
import react from '@astrojs/react';
+import vue from '@astrojs/vue';
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({
- integrations: [react()],
+ integrations: [react(), vue()],
});
diff --git a/packages/astro/test/fixtures/container-react/package.json b/packages/astro/test/fixtures/container-custom-renderers/package.json
index 43d164ce8..0824a724c 100644
--- a/packages/astro/test/fixtures/container-react/package.json
+++ b/packages/astro/test/fixtures/container-custom-renderers/package.json
@@ -5,8 +5,10 @@
"type": "module",
"dependencies": {
"@astrojs/react": "workspace:*",
+ "@astrojs/vue": "workspace:*",
"astro": "workspace:*",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "vue": "^3.4.27"
}
}
diff --git a/packages/astro/test/fixtures/container-react/src/components/button.jsx b/packages/astro/test/fixtures/container-custom-renderers/src/components/button.jsx
index 2eeffc334..2eeffc334 100644
--- a/packages/astro/test/fixtures/container-react/src/components/button.jsx
+++ b/packages/astro/test/fixtures/container-custom-renderers/src/components/button.jsx
diff --git a/packages/astro/test/fixtures/container-custom-renderers/src/components/button.vue b/packages/astro/test/fixtures/container-custom-renderers/src/components/button.vue
new file mode 100644
index 000000000..5a55a61d9
--- /dev/null
+++ b/packages/astro/test/fixtures/container-custom-renderers/src/components/button.vue
@@ -0,0 +1,3 @@
+<template>
+ <button id="arrow-fn-component">I am a vue button</button>
+</template>
diff --git a/packages/astro/test/fixtures/container-react/src/pages/api.ts b/packages/astro/test/fixtures/container-custom-renderers/src/pages/react.ts
index 7fae87247..d77eaead1 100644
--- a/packages/astro/test/fixtures/container-react/src/pages/api.ts
+++ b/packages/astro/test/fixtures/container-custom-renderers/src/pages/react.ts
@@ -1,10 +1,10 @@
import type {APIRoute, SSRLoadedRenderer} from "astro";
import { experimental_AstroContainer } from "astro/container";
-import server from '@astrojs/react/server.js';
+import renderer from '@astrojs/react/server.js';
import Component from "../components/button.jsx"
export const GET: APIRoute = async (ctx) => {
const container = await experimental_AstroContainer.create();
- container.addServerRenderer("@astrojs/react", server);
+ container.addServerRenderer({ renderer });
return await container.renderToResponse(Component);
}
diff --git a/packages/astro/test/fixtures/container-custom-renderers/src/pages/vue.ts b/packages/astro/test/fixtures/container-custom-renderers/src/pages/vue.ts
new file mode 100644
index 000000000..9ea75d802
--- /dev/null
+++ b/packages/astro/test/fixtures/container-custom-renderers/src/pages/vue.ts
@@ -0,0 +1,10 @@
+import type {APIRoute, SSRLoadedRenderer} from "astro";
+import { experimental_AstroContainer } from "astro/container";
+import renderer from '@astrojs/vue/server.js';
+import Component from "../components/button.vue"
+
+export const GET: APIRoute = async (ctx) => {
+ const container = await experimental_AstroContainer.create();
+ container.addServerRenderer({ renderer });
+ return await container.renderToResponse(Component);
+}
diff --git a/packages/integrations/lit/package.json b/packages/integrations/lit/package.json
index 7bf9d81e1..947cb67fa 100644
--- a/packages/integrations/lit/package.json
+++ b/packages/integrations/lit/package.json
@@ -21,7 +21,10 @@
"homepage": "https://docs.astro.build/en/guides/integrations-guide/lit/",
"exports": {
".": "./dist/index.js",
- "./server.js": "./server.js",
+ "./server.js": {
+ "default": "./server.js",
+ "types": "./server.d.ts"
+ },
"./client-shim.js": "./client-shim.js",
"./dist/client.js": "./dist/client.js",
"./hydration-support.js": "./hydration-support.js",
@@ -33,6 +36,7 @@
"client-shim.min.js",
"hydration-support.js",
"server.js",
+ "server.d.ts",
"server-shim.js"
],
"scripts": {
diff --git a/packages/integrations/lit/server.d.ts b/packages/integrations/lit/server.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/lit/server.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/lit/server.js b/packages/integrations/lit/server.js
index e3f1c0340..e9873a051 100644
--- a/packages/integrations/lit/server.js
+++ b/packages/integrations/lit/server.js
@@ -112,6 +112,7 @@ async function renderToStaticMarkup(Component, props, slots) {
}
export default {
+ name: '@astrojs/lit',
check,
renderToStaticMarkup,
};
diff --git a/packages/integrations/preact/src/server.ts b/packages/integrations/preact/src/server.ts
index c502e68db..c10c01c0e 100644
--- a/packages/integrations/preact/src/server.ts
+++ b/packages/integrations/preact/src/server.ts
@@ -1,4 +1,4 @@
-import type { AstroComponentMetadata } from 'astro';
+import type { AstroComponentMetadata, NamedSSRLoadedRendererValue } from 'astro';
import { Component as BaseComponent, type VNode, h } from 'preact';
import { render } from 'preact-render-to-string';
import prepass from 'preact-ssr-prepass';
@@ -147,8 +147,11 @@ function filteredConsoleError(msg: string, ...rest: any[]) {
originalConsoleError(msg, ...rest);
}
-export default {
+const renderer: NamedSSRLoadedRendererValue = {
+ name: '@astrojs/preact',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: true,
};
+
+export default renderer;
diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json
index 5ea15729b..d35210710 100644
--- a/packages/integrations/react/package.json
+++ b/packages/integrations/react/package.json
@@ -24,8 +24,14 @@
"./actions": "./dist/actions.js",
"./client.js": "./client.js",
"./client-v17.js": "./client-v17.js",
- "./server.js": "./server.js",
- "./server-v17.js": "./server-v17.js",
+ "./server.js": {
+ "default": "./server.js",
+ "types": "./server.d.ts"
+ },
+ "./server-v17.js": {
+ "default": "./server-v17.js",
+ "types": "./server-v17.d.ts"
+ },
"./package.json": "./package.json",
"./jsx-runtime": "./jsx-runtime.js"
},
@@ -36,7 +42,9 @@
"context.js",
"jsx-runtime.js",
"server.js",
+ "server.d.ts",
"server-v17.js",
+ "server-v17.d.ts",
"static-html.js",
"vnode-children.js"
],
diff --git a/packages/integrations/react/server-v17.js b/packages/integrations/react/server-v17.js
index ad0c99622..16f6fcdcd 100644
--- a/packages/integrations/react/server-v17.js
+++ b/packages/integrations/react/server-v17.js
@@ -82,6 +82,7 @@ function renderToStaticMarkup(Component, props, { default: children, ...slotted
}
export default {
+ name: '@astrojs/react',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: true,
diff --git a/packages/integrations/react/server.d.ts b/packages/integrations/react/server.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/react/server.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js
index c2b255853..59134a699 100644
--- a/packages/integrations/react/server.js
+++ b/packages/integrations/react/server.js
@@ -226,6 +226,7 @@ function isFormRequest(contentType) {
}
export default {
+ name: '@astrojs/react',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: true,
diff --git a/packages/integrations/react/server17.d.ts b/packages/integrations/react/server17.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/react/server17.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/solid/src/server.ts b/packages/integrations/solid/src/server.ts
index a91658ea3..79a911fb1 100644
--- a/packages/integrations/solid/src/server.ts
+++ b/packages/integrations/solid/src/server.ts
@@ -9,6 +9,7 @@ import {
} from 'solid-js/web';
import { getContext, incrementId } from './context.js';
import type { RendererContext } from './types.js';
+import type { NamedSSRLoadedRendererValue } from 'astro';
const slotName = (str: string) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
@@ -123,9 +124,12 @@ async function renderToStaticMarkup(
};
}
-export default {
+const renderer: NamedSSRLoadedRendererValue = {
+ name: '@astrojs/solid',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: true,
renderHydrationScript: () => generateHydrationScript(),
};
+
+export default renderer;
diff --git a/packages/integrations/svelte/package.json b/packages/integrations/svelte/package.json
index 75925bf3c..b9ab20e3c 100644
--- a/packages/integrations/svelte/package.json
+++ b/packages/integrations/svelte/package.json
@@ -25,8 +25,14 @@
"./*": "./*",
"./client.js": "./client.js",
"./client-v5.js": "./client-v5.js",
- "./server.js": "./server.js",
- "./server-v5.js": "./server-v5.js",
+ "./server.js": {
+ "default": "./server.js",
+ "types": "./server.d.ts"
+ },
+ "./server-v5.js": {
+ "default": "./server-v5.js",
+ "types": "./server-v5.d.ts"
+ },
"./package.json": "./package.json"
},
"files": [
@@ -34,7 +40,9 @@
"client.js",
"client-v5.js",
"server.js",
- "server-v5.js"
+ "server.d.ts",
+ "server-v5.js",
+ "server-v5.d.ts"
],
"scripts": {
"build": "astro-scripts build \"src/index.ts\" && astro-scripts build \"src/editor.cts\" --force-cjs --no-clean-dist && tsc",
diff --git a/packages/integrations/svelte/server-v5.d.ts b/packages/integrations/svelte/server-v5.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/svelte/server-v5.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/svelte/server.d.ts b/packages/integrations/svelte/server.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/svelte/server.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/vue/package.json b/packages/integrations/vue/package.json
index 5267cf918..245347f12 100644
--- a/packages/integrations/vue/package.json
+++ b/packages/integrations/vue/package.json
@@ -24,13 +24,17 @@
"./editor": "./dist/editor.cjs",
"./*": "./*",
"./client.js": "./client.js",
- "./server.js": "./server.js",
+ "./server.js": {
+ "default": "./server.js",
+ "types": "./server.d.ts"
+ },
"./package.json": "./package.json"
},
"files": [
"dist",
"client.js",
"server.js",
+ "server.d.ts",
"static-html.js"
],
"scripts": {
diff --git a/packages/integrations/vue/server.d.ts b/packages/integrations/vue/server.d.ts
new file mode 100644
index 000000000..bb2f29556
--- /dev/null
+++ b/packages/integrations/vue/server.d.ts
@@ -0,0 +1,2 @@
+import type { NamedSSRLoadedRendererValue } from 'astro';
+export default NamedSSRLoadedRendererValue;
diff --git a/packages/integrations/vue/server.js b/packages/integrations/vue/server.js
index be57dd43a..afdc9e8a2 100644
--- a/packages/integrations/vue/server.js
+++ b/packages/integrations/vue/server.js
@@ -27,6 +27,7 @@ async function renderToStaticMarkup(Component, inputProps, slotted, metadata) {
}
export default {
+ name: '@astrojs/vue',
check,
renderToStaticMarkup,
supportsAstroStaticSlot: true,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ae9663178..f4e3889b2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2539,11 +2539,14 @@ importers:
specifier: workspace:*
version: link:../../..
- packages/astro/test/fixtures/container-react:
+ packages/astro/test/fixtures/container-custom-renderers:
dependencies:
'@astrojs/react':
specifier: workspace:*
version: link:../../../../integrations/react
+ '@astrojs/vue':
+ specifier: workspace:*
+ version: link:../../../../integrations/vue
astro:
specifier: workspace:*
version: link:../../..
@@ -2553,6 +2556,9 @@ importers:
react-dom:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
+ vue:
+ specifier: ^3.4.27
+ version: 3.4.27(typescript@5.4.5)
packages/astro/test/fixtures/content:
dependencies: