mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
[ci] format
This commit is contained in:
parent
d495df5361
commit
b46a78e1c9
26 changed files with 1602 additions and 1319 deletions
File diff suppressed because it is too large
Load diff
|
@ -1 +1,11 @@
|
||||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{ "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
|
||||||
|
{ "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap");
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
body {
|
body {
|
||||||
@apply font-poppins;
|
@apply font-poppins;
|
||||||
}
|
}
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
@apply font-roboto;
|
@apply font-roboto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
.size-selector input:checked + label {
|
.size-selector input:checked + label {
|
||||||
@apply bg-primary text-white;
|
@apply bg-primary text-white;
|
||||||
}
|
}
|
||||||
.color-selector input:checked + label {
|
.color-selector input:checked + label {
|
||||||
@apply ring-2 ring-primary;
|
@apply ring-2 ring-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-box {
|
.input-box {
|
||||||
@apply block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0;
|
@apply block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,32 @@ const { placeholder } = Astro.props;
|
||||||
let wishlist = 0;
|
let wishlist = 0;
|
||||||
let cart = 0;
|
let cart = 0;
|
||||||
|
|
||||||
if(!placeholder) {
|
if (!placeholder) {
|
||||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
||||||
<div class="text-2xl">
|
<div class="text-2xl">
|
||||||
<i class="fa-regular fa-heart"></i>
|
<i class="fa-regular fa-heart"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs leading-3">Wishlist</div>
|
<div class="text-xs leading-3">Wishlist</div>
|
||||||
<div
|
<div
|
||||||
class="absolute right-0 -top-1 w-5 h-5 rounded-full flex items-center justify-center bg-primary text-white text-xs">{ wishlist }</div>
|
class="absolute right-0 -top-1 w-5 h-5 rounded-full flex items-center justify-center bg-primary text-white text-xs"
|
||||||
|
>
|
||||||
|
{wishlist}
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
||||||
<div class="text-2xl">
|
<div class="text-2xl">
|
||||||
<i class="fa-solid fa-bag-shopping"></i>
|
<i class="fa-solid fa-bag-shopping"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs leading-3">Cart</div>
|
<div class="text-xs leading-3">Cart</div>
|
||||||
<CartCount client:load count={cart} />
|
<CartCount client:load count={cart} />
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
<a href="#" class="text-center text-gray-700 hover:text-primary transition relative">
|
||||||
<div class="text-2xl">
|
<div class="text-2xl">
|
||||||
<i class="fa-regular fa-user"></i>
|
<i class="fa-regular fa-user"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs leading-3">Account</div>
|
<div class="text-xs leading-3">Account</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2254,7 +2254,7 @@ export interface AstroUserConfig {
|
||||||
* #### Server island fallback content
|
* #### Server island fallback content
|
||||||
*
|
*
|
||||||
* Since your component will not render with the rest of the page, you may want to add generic content (e.g. a loading message) to temporarily show in its place. This content will be displayed when the page first renders but before the island has loaded.
|
* Since your component will not render with the rest of the page, you may want to add generic content (e.g. a loading message) to temporarily show in its place. This content will be displayed when the page first renders but before the island has loaded.
|
||||||
*
|
*
|
||||||
* Add placeholder content as a child of your Astro component with the `slot="fallback:` attribute. When your island content is available, the fallback content will be replaced.
|
* Add placeholder content as a child of your Astro component with the `slot="fallback:` attribute. When your island content is available, the fallback content will be replaced.
|
||||||
*
|
*
|
||||||
* The example below displays a generic avatar as fallback content, then animates into a personalized avatar using view transitions:
|
* The example below displays a generic avatar as fallback content, then animates into a personalized avatar using view transitions:
|
||||||
|
@ -3377,7 +3377,6 @@ export interface SSRMetadata {
|
||||||
headInTree: boolean;
|
headInTree: boolean;
|
||||||
extraHead: string[];
|
extraHead: string[];
|
||||||
propagators: Set<AstroComponentInstance>;
|
propagators: Set<AstroComponentInstance>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preview server stuff */
|
/* Preview server stuff */
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { appendForwardSlash, removeFileExtension } from '../core/path.js';
|
||||||
import { isServerLikeOutput } from '../core/util.js';
|
import { isServerLikeOutput } from '../core/util.js';
|
||||||
import { rootRelativePath } from '../core/viteUtils.js';
|
import { rootRelativePath } from '../core/viteUtils.js';
|
||||||
import type { AstroPluginMetadata } from '../vite-plugin-astro/index.js';
|
import type { AstroPluginMetadata } from '../vite-plugin-astro/index.js';
|
||||||
|
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
||||||
import {
|
import {
|
||||||
CONTENT_FLAG,
|
CONTENT_FLAG,
|
||||||
CONTENT_RENDER_FLAG,
|
CONTENT_RENDER_FLAG,
|
||||||
|
@ -30,7 +31,6 @@ import {
|
||||||
getEntryType,
|
getEntryType,
|
||||||
getExtGlob,
|
getExtGlob,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
|
||||||
|
|
||||||
interface AstroContentVirtualModPluginParams {
|
interface AstroContentVirtualModPluginParams {
|
||||||
settings: AstroSettings;
|
settings: AstroSettings;
|
||||||
|
|
|
@ -99,11 +99,11 @@ export class AppPipeline extends Pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getModuleForRoute(route: RouteData): Promise<SinglePageBuiltModule> {
|
async getModuleForRoute(route: RouteData): Promise<SinglePageBuiltModule> {
|
||||||
for(const defaultRoute of this.defaultRoutes) {
|
for (const defaultRoute of this.defaultRoutes) {
|
||||||
if(route.component === defaultRoute.component) {
|
if (route.component === defaultRoute.component) {
|
||||||
return {
|
return {
|
||||||
page: () => Promise.resolve(defaultRoute.instance),
|
page: () => Promise.resolve(defaultRoute.instance),
|
||||||
renderers: []
|
renderers: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type {
|
import type {
|
||||||
ComponentInstance,
|
ComponentInstance,
|
||||||
Locales,
|
Locales,
|
||||||
MiddlewareHandler,
|
MiddlewareHandler,
|
||||||
RouteData,
|
RouteData,
|
||||||
|
@ -84,7 +84,13 @@ export type SSRManifestI18n = {
|
||||||
|
|
||||||
export type SerializedSSRManifest = Omit<
|
export type SerializedSSRManifest = Omit<
|
||||||
SSRManifest,
|
SSRManifest,
|
||||||
'middleware' | 'routes' | 'assets' | 'componentMetadata' | 'inlinedScripts' | 'clientDirectives' | 'serverIslandNameMap'
|
| 'middleware'
|
||||||
|
| 'routes'
|
||||||
|
| 'assets'
|
||||||
|
| 'componentMetadata'
|
||||||
|
| 'inlinedScripts'
|
||||||
|
| 'clientDirectives'
|
||||||
|
| 'serverIslandNameMap'
|
||||||
> & {
|
> & {
|
||||||
routes: SerializedRouteInfo[];
|
routes: SerializedRouteInfo[];
|
||||||
assets: string[];
|
assets: string[];
|
||||||
|
|
|
@ -272,8 +272,8 @@ export class BuildPipeline extends Pipeline {
|
||||||
return await entry.page();
|
return await entry.page();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const route of this.defaultRoutes) {
|
for (const route of this.defaultRoutes) {
|
||||||
if(route.component === routeData.component) {
|
if (route.component === routeData.component) {
|
||||||
return route.instance;
|
return route.instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type { Plugin as VitePlugin } from 'vite';
|
||||||
import type { AstroAdapter, AstroSettings } from '../../../@types/astro.js';
|
import type { AstroAdapter, AstroSettings } from '../../../@types/astro.js';
|
||||||
import { isFunctionPerRouteEnabled } from '../../../integrations/hooks.js';
|
import { isFunctionPerRouteEnabled } from '../../../integrations/hooks.js';
|
||||||
import { routeIsRedirect } from '../../redirects/index.js';
|
import { routeIsRedirect } from '../../redirects/index.js';
|
||||||
|
import { VIRTUAL_ISLAND_MAP_ID } from '../../server-islands/vite-plugin-server-islands.js';
|
||||||
import { isServerLikeOutput } from '../../util.js';
|
import { isServerLikeOutput } from '../../util.js';
|
||||||
import { addRollupInput } from '../add-rollup-input.js';
|
import { addRollupInput } from '../add-rollup-input.js';
|
||||||
import type { BuildInternals } from '../internal.js';
|
import type { BuildInternals } from '../internal.js';
|
||||||
|
@ -13,7 +14,6 @@ import { SSR_MANIFEST_VIRTUAL_MODULE_ID } from './plugin-manifest.js';
|
||||||
import { MIDDLEWARE_MODULE_ID } from './plugin-middleware.js';
|
import { MIDDLEWARE_MODULE_ID } from './plugin-middleware.js';
|
||||||
import { ASTRO_PAGE_MODULE_ID } from './plugin-pages.js';
|
import { ASTRO_PAGE_MODULE_ID } from './plugin-pages.js';
|
||||||
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
|
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
|
||||||
import { VIRTUAL_ISLAND_MAP_ID } from '../../server-islands/vite-plugin-server-islands.js';
|
|
||||||
import { getComponentFromVirtualModulePageName, getVirtualModulePageName } from './util.js';
|
import { getComponentFromVirtualModulePageName, getVirtualModulePageName } from './util.js';
|
||||||
|
|
||||||
export const SSR_VIRTUAL_MODULE_ID = '@astrojs-ssr-virtual-entry';
|
export const SSR_VIRTUAL_MODULE_ID = '@astrojs-ssr-virtual-entry';
|
||||||
|
@ -250,7 +250,9 @@ function generateSSRCode(settings: AstroSettings, adapter: AstroAdapter, middlew
|
||||||
`import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
|
`import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
|
||||||
`import * as serverEntrypointModule from '${adapter.serverEntrypoint}';`,
|
`import * as serverEntrypointModule from '${adapter.serverEntrypoint}';`,
|
||||||
edgeMiddleware ? `` : `import { onRequest as middleware } from '${middlewareId}';`,
|
edgeMiddleware ? `` : `import { onRequest as middleware } from '${middlewareId}';`,
|
||||||
settings.config.experimental.serverIslands ? `import { serverIslandMap } from '${VIRTUAL_ISLAND_MAP_ID}';` : ''
|
settings.config.experimental.serverIslands
|
||||||
|
? `import { serverIslandMap } from '${VIRTUAL_ISLAND_MAP_ID}';`
|
||||||
|
: '',
|
||||||
];
|
];
|
||||||
|
|
||||||
const contents = [
|
const contents = [
|
||||||
|
|
|
@ -540,7 +540,10 @@ export const AstroConfigSchema = z.object({
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.optional(),
|
.optional(),
|
||||||
serverIslands: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.serverIslands),
|
serverIslands: z
|
||||||
|
.boolean()
|
||||||
|
.optional()
|
||||||
|
.default(ASTRO_CONFIG_DEFAULTS.experimental.serverIslands),
|
||||||
})
|
})
|
||||||
.strict(
|
.strict(
|
||||||
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`
|
`Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`
|
||||||
|
|
|
@ -36,8 +36,8 @@ import { vitePluginSSRManifest } from '../vite-plugin-ssr-manifest/index.js';
|
||||||
import type { Logger } from './logger/core.js';
|
import type { Logger } from './logger/core.js';
|
||||||
import { createViteLogger } from './logger/vite.js';
|
import { createViteLogger } from './logger/vite.js';
|
||||||
import { vitePluginMiddleware } from './middleware/vite-plugin.js';
|
import { vitePluginMiddleware } from './middleware/vite-plugin.js';
|
||||||
import { vitePluginServerIslands } from './server-islands/vite-plugin-server-islands.js';
|
|
||||||
import { joinPaths } from './path.js';
|
import { joinPaths } from './path.js';
|
||||||
|
import { vitePluginServerIslands } from './server-islands/vite-plugin-server-islands.js';
|
||||||
import { isObject } from './util.js';
|
import { isObject } from './util.js';
|
||||||
|
|
||||||
interface CreateViteOptions {
|
interface CreateViteOptions {
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import type { ComponentInstance, ManifestData, SSRManifest, } from "../../@types/astro.js";
|
import type { ComponentInstance, ManifestData, SSRManifest } from '../../@types/astro.js';
|
||||||
import { DEFAULT_404_COMPONENT } from "../constants.js";
|
import { DEFAULT_404_COMPONENT } from '../constants.js';
|
||||||
import { ensureServerIslandRoute, createEndpoint as createServerIslandEndpoint, SERVER_ISLAND_ROUTE, SERVER_ISLAND_COMPONENT } from "../server-islands/endpoint.js";
|
import {
|
||||||
import { ensure404Route, default404Instance, DEFAULT_404_ROUTE } from './astro-designed-error-pages.js';
|
SERVER_ISLAND_COMPONENT,
|
||||||
|
SERVER_ISLAND_ROUTE,
|
||||||
|
createEndpoint as createServerIslandEndpoint,
|
||||||
|
ensureServerIslandRoute,
|
||||||
|
} from '../server-islands/endpoint.js';
|
||||||
|
import {
|
||||||
|
DEFAULT_404_ROUTE,
|
||||||
|
default404Instance,
|
||||||
|
ensure404Route,
|
||||||
|
} from './astro-designed-error-pages.js';
|
||||||
|
|
||||||
export function injectDefaultRoutes(manifest: ManifestData) {
|
export function injectDefaultRoutes(manifest: ManifestData) {
|
||||||
ensure404Route(manifest);
|
ensure404Route(manifest);
|
||||||
|
@ -14,7 +23,7 @@ type DefaultRouteParams = {
|
||||||
matchesComponent(filePath: URL): boolean;
|
matchesComponent(filePath: URL): boolean;
|
||||||
route: string;
|
route: string;
|
||||||
component: string;
|
component: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function createDefaultRoutes(manifest: SSRManifest, root: URL): DefaultRouteParams[] {
|
export function createDefaultRoutes(manifest: SSRManifest, root: URL): DefaultRouteParams[] {
|
||||||
return [
|
return [
|
||||||
|
@ -29,6 +38,6 @@ export function createDefaultRoutes(manifest: SSRManifest, root: URL): DefaultRo
|
||||||
matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
|
matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
|
||||||
route: SERVER_ISLAND_ROUTE,
|
route: SERVER_ISLAND_ROUTE,
|
||||||
component: SERVER_ISLAND_COMPONENT,
|
component: SERVER_ISLAND_COMPONENT,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
import { renderComponent, renderTemplate, type AstroComponentFactory, type ComponentSlots } from '../../runtime/server/index.js';
|
import type {
|
||||||
import type { ComponentInstance, ManifestData, RouteData, SSRManifest } from '../../@types/astro.js';
|
ComponentInstance,
|
||||||
|
ManifestData,
|
||||||
|
RouteData,
|
||||||
|
SSRManifest,
|
||||||
|
} from '../../@types/astro.js';
|
||||||
|
import {
|
||||||
|
type AstroComponentFactory,
|
||||||
|
type ComponentSlots,
|
||||||
|
renderComponent,
|
||||||
|
renderTemplate,
|
||||||
|
} from '../../runtime/server/index.js';
|
||||||
import { createSlotValueFromString } from '../../runtime/server/render/slot.js';
|
import { createSlotValueFromString } from '../../runtime/server/render/slot.js';
|
||||||
|
|
||||||
export const SERVER_ISLAND_ROUTE = '/_server-islands/[name]';
|
export const SERVER_ISLAND_ROUTE = '/_server-islands/[name]';
|
||||||
|
@ -17,7 +27,7 @@ export function ensureServerIslandRoute(manifest: ManifestData) {
|
||||||
params: ['name'],
|
params: ['name'],
|
||||||
segments: [
|
segments: [
|
||||||
[{ content: '_server-islands', dynamic: false, spread: false }],
|
[{ content: '_server-islands', dynamic: false, spread: false }],
|
||||||
[{ content: 'name', dynamic: true, spread: false }]
|
[{ content: 'name', dynamic: true, spread: false }],
|
||||||
],
|
],
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
pattern: /^\/_server-islands\/([^/]+?)$/,
|
pattern: /^\/_server-islands\/([^/]+?)$/,
|
||||||
|
@ -25,7 +35,7 @@ export function ensureServerIslandRoute(manifest: ManifestData) {
|
||||||
isIndex: false,
|
isIndex: false,
|
||||||
fallbackRoutes: [],
|
fallbackRoutes: [],
|
||||||
route: SERVER_ISLAND_ROUTE,
|
route: SERVER_ISLAND_ROUTE,
|
||||||
}
|
};
|
||||||
|
|
||||||
manifest.routes.push(route);
|
manifest.routes.push(route);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +44,7 @@ type RenderOptions = {
|
||||||
componentExport: string;
|
componentExport: string;
|
||||||
props: Record<string, any>;
|
props: Record<string, any>;
|
||||||
slots: Record<string, string>;
|
slots: Record<string, string>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function createEndpoint(manifest: SSRManifest) {
|
export function createEndpoint(manifest: SSRManifest) {
|
||||||
const page: AstroComponentFactory = async (result) => {
|
const page: AstroComponentFactory = async (result) => {
|
||||||
|
@ -42,19 +52,19 @@ export function createEndpoint(manifest: SSRManifest) {
|
||||||
const request = result.request;
|
const request = result.request;
|
||||||
const raw = await request.text();
|
const raw = await request.text();
|
||||||
const data = JSON.parse(raw) as RenderOptions;
|
const data = JSON.parse(raw) as RenderOptions;
|
||||||
if(!params.name) {
|
if (!params.name) {
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 400,
|
status: 400,
|
||||||
statusText: 'Bad request'
|
statusText: 'Bad request',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const componentId = params.name;
|
const componentId = params.name;
|
||||||
|
|
||||||
const imp = manifest.serverIslandMap?.get(componentId);
|
const imp = manifest.serverIslandMap?.get(componentId);
|
||||||
if(!imp) {
|
if (!imp) {
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 404,
|
status: 404,
|
||||||
statusText: 'Not found'
|
statusText: 'Not found',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,15 +73,15 @@ export function createEndpoint(manifest: SSRManifest) {
|
||||||
const Component = (componentModule as any)[data.componentExport];
|
const Component = (componentModule as any)[data.componentExport];
|
||||||
|
|
||||||
const slots: ComponentSlots = {};
|
const slots: ComponentSlots = {};
|
||||||
for(const prop in data.slots) {
|
for (const prop in data.slots) {
|
||||||
slots[prop] = createSlotValueFromString(data.slots[prop]);
|
slots[prop] = createSlotValueFromString(data.slots[prop]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderTemplate`${renderComponent(result, 'Component', Component, props, slots)}`;
|
return renderTemplate`${renderComponent(result, 'Component', Component, props, slots)}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
page.isAstroComponentFactory = true;
|
page.isAstroComponentFactory = true;
|
||||||
|
|
||||||
const instance: ComponentInstance = {
|
const instance: ComponentInstance = {
|
||||||
default: page,
|
default: page,
|
||||||
partial: true,
|
partial: true,
|
||||||
|
@ -79,4 +89,3 @@ export function createEndpoint(manifest: SSRManifest) {
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import type { AstroPluginMetadata } from '../../vite-plugin-astro/index.js';
|
|
||||||
import type { AstroSettings } from '../../@types/astro.js';
|
|
||||||
import type { ConfigEnv, ViteDevServer, Plugin as VitePlugin } from 'vite';
|
import type { ConfigEnv, ViteDevServer, Plugin as VitePlugin } from 'vite';
|
||||||
|
import type { AstroSettings } from '../../@types/astro.js';
|
||||||
|
import type { AstroPluginMetadata } from '../../vite-plugin-astro/index.js';
|
||||||
|
|
||||||
export const VIRTUAL_ISLAND_MAP_ID = '@astro-server-islands';
|
export const VIRTUAL_ISLAND_MAP_ID = '@astro-server-islands';
|
||||||
export const RESOLVED_VIRTUAL_ISLAND_MAP_ID = '\0' + VIRTUAL_ISLAND_MAP_ID;
|
export const RESOLVED_VIRTUAL_ISLAND_MAP_ID = '\0' + VIRTUAL_ISLAND_MAP_ID;
|
||||||
const serverIslandPlaceholder = '\'$$server-islands$$\'';
|
const serverIslandPlaceholder = "'$$server-islands$$'";
|
||||||
|
|
||||||
export function vitePluginServerIslands({ settings }: { settings: AstroSettings }): VitePlugin {
|
export function vitePluginServerIslands({ settings }: { settings: AstroSettings }): VitePlugin {
|
||||||
let command: ConfigEnv['command'] = 'serve';
|
let command: ConfigEnv['command'] = 'serve';
|
||||||
|
@ -20,29 +20,29 @@ export function vitePluginServerIslands({ settings }: { settings: AstroSettings
|
||||||
viteServer = _server;
|
viteServer = _server;
|
||||||
},
|
},
|
||||||
resolveId(name) {
|
resolveId(name) {
|
||||||
if(name === VIRTUAL_ISLAND_MAP_ID) {
|
if (name === VIRTUAL_ISLAND_MAP_ID) {
|
||||||
return RESOLVED_VIRTUAL_ISLAND_MAP_ID;
|
return RESOLVED_VIRTUAL_ISLAND_MAP_ID;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
load(id) {
|
load(id) {
|
||||||
if(id === RESOLVED_VIRTUAL_ISLAND_MAP_ID) {
|
if (id === RESOLVED_VIRTUAL_ISLAND_MAP_ID) {
|
||||||
return `export const serverIslandMap = ${serverIslandPlaceholder};`;
|
return `export const serverIslandMap = ${serverIslandPlaceholder};`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
transform(_code, id) {
|
transform(_code, id) {
|
||||||
if(id.endsWith('.astro')) {
|
if (id.endsWith('.astro')) {
|
||||||
const info = this.getModuleInfo(id);
|
const info = this.getModuleInfo(id);
|
||||||
if(info?.meta) {
|
if (info?.meta) {
|
||||||
const astro = info.meta.astro as AstroPluginMetadata['astro'] | undefined;
|
const astro = info.meta.astro as AstroPluginMetadata['astro'] | undefined;
|
||||||
if(astro?.serverComponents.length) {
|
if (astro?.serverComponents.length) {
|
||||||
for(const comp of astro.serverComponents) {
|
for (const comp of astro.serverComponents) {
|
||||||
if(!settings.serverIslandNameMap.has(comp.resolvedPath)) {
|
if (!settings.serverIslandNameMap.has(comp.resolvedPath)) {
|
||||||
let name = comp.localName;
|
let name = comp.localName;
|
||||||
let idx = 1;
|
let idx = 1;
|
||||||
|
|
||||||
while(true) {
|
while (true) {
|
||||||
// Name not taken, let's use it.
|
// Name not taken, let's use it.
|
||||||
if(!settings.serverIslandMap.has(name)) {
|
if (!settings.serverIslandMap.has(name)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Increment a number onto the name: Avatar -> Avatar1
|
// Increment a number onto the name: Avatar -> Avatar1
|
||||||
|
@ -57,12 +57,12 @@ export function vitePluginServerIslands({ settings }: { settings: AstroSettings
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build mode
|
// Build mode
|
||||||
if(command === 'build') {
|
if (command === 'build') {
|
||||||
let referenceId = this.emitFile({
|
let referenceId = this.emitFile({
|
||||||
type: 'chunk',
|
type: 'chunk',
|
||||||
id: comp.specifier,
|
id: comp.specifier,
|
||||||
importer: id,
|
importer: id,
|
||||||
name: comp.localName
|
name: comp.localName,
|
||||||
});
|
});
|
||||||
|
|
||||||
referenceIdMap.set(comp.resolvedPath, referenceId);
|
referenceIdMap.set(comp.resolvedPath, referenceId);
|
||||||
|
@ -74,17 +74,17 @@ export function vitePluginServerIslands({ settings }: { settings: AstroSettings
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderChunk(code) {
|
renderChunk(code) {
|
||||||
if(code.includes(serverIslandPlaceholder)) {
|
if (code.includes(serverIslandPlaceholder)) {
|
||||||
let mapSource = 'new Map([';
|
let mapSource = 'new Map([';
|
||||||
for(let [resolvedPath, referenceId] of referenceIdMap) {
|
for (let [resolvedPath, referenceId] of referenceIdMap) {
|
||||||
const fileName = this.getFileName(referenceId);
|
const fileName = this.getFileName(referenceId);
|
||||||
const islandName = settings.serverIslandNameMap.get(resolvedPath)!;
|
const islandName = settings.serverIslandNameMap.get(resolvedPath)!;
|
||||||
mapSource += `\n\t['${islandName}', () => import('./${fileName}')],`
|
mapSource += `\n\t['${islandName}', () => import('./${fileName}')],`;
|
||||||
}
|
}
|
||||||
mapSource += '\n]);';
|
mapSource += '\n]);';
|
||||||
referenceIdMap.clear();
|
referenceIdMap.clear();
|
||||||
return code.replace(serverIslandPlaceholder, mapSource);
|
return code.replace(serverIslandPlaceholder, mapSource);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import * as t from '@babel/types';
|
||||||
import { AstroError } from '../core/errors/errors.js';
|
import { AstroError } from '../core/errors/errors.js';
|
||||||
import { AstroErrorData } from '../core/errors/index.js';
|
import { AstroErrorData } from '../core/errors/index.js';
|
||||||
import { resolvePath } from '../core/viteUtils.js';
|
import { resolvePath } from '../core/viteUtils.js';
|
||||||
import type { PluginMetadata } from '../vite-plugin-astro/types.js';
|
|
||||||
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
||||||
|
import type { PluginMetadata } from '../vite-plugin-astro/types.js';
|
||||||
|
|
||||||
const ClientOnlyPlaceholder = 'astro-client-only';
|
const ClientOnlyPlaceholder = 'astro-client-only';
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ export async function renderEndpoint(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (handler === undefined) {
|
if (handler === undefined) {
|
||||||
|
|
||||||
logger.warn(
|
logger.warn(
|
||||||
'router',
|
'router',
|
||||||
`No API Route handler exists for the method "${method}" for the route "${url.pathname}".\n` +
|
`No API Route handler exists for the method "${method}" for the route "${url.pathname}".\n` +
|
||||||
|
|
|
@ -6,7 +6,11 @@ export type AstroFactoryReturnValue = RenderTemplateResult | Response | HeadAndC
|
||||||
|
|
||||||
// The callback passed to to $$createComponent
|
// The callback passed to to $$createComponent
|
||||||
export interface AstroComponentFactory {
|
export interface AstroComponentFactory {
|
||||||
(result: SSRResult, props: any, slots: any): AstroFactoryReturnValue | Promise<AstroFactoryReturnValue>;
|
(
|
||||||
|
result: SSRResult,
|
||||||
|
props: any,
|
||||||
|
slots: any
|
||||||
|
): AstroFactoryReturnValue | Promise<AstroFactoryReturnValue>;
|
||||||
isAstroComponentFactory?: boolean;
|
isAstroComponentFactory?: boolean;
|
||||||
moduleId?: string | undefined;
|
moduleId?: string | undefined;
|
||||||
propagation?: PropagationHint;
|
propagation?: PropagationHint;
|
||||||
|
|
|
@ -27,9 +27,9 @@ import {
|
||||||
} from './common.js';
|
} from './common.js';
|
||||||
import { componentIsHTMLElement, renderHTMLElement } from './dom.js';
|
import { componentIsHTMLElement, renderHTMLElement } from './dom.js';
|
||||||
import { maybeRenderHead } from './head.js';
|
import { maybeRenderHead } from './head.js';
|
||||||
|
import { containsServerDirective, renderServerIsland } from './server-islands.js';
|
||||||
import { type ComponentSlots, renderSlotToString, renderSlots } from './slot.js';
|
import { type ComponentSlots, renderSlotToString, renderSlots } from './slot.js';
|
||||||
import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js';
|
import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from './util.js';
|
||||||
import { containsServerDirective, renderServerIsland } from './server-islands.js';
|
|
||||||
|
|
||||||
const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering');
|
const needsHeadRenderingSymbol = Symbol.for('astro.needsHeadRendering');
|
||||||
const rendererAliases = new Map([['solid', 'solid-js']]);
|
const rendererAliases = new Map([['solid', 'solid-js']]);
|
||||||
|
@ -474,10 +474,10 @@ function renderAstroComponent(
|
||||||
props: Record<string | number, any>,
|
props: Record<string | number, any>,
|
||||||
slots: any = {}
|
slots: any = {}
|
||||||
): RenderInstance {
|
): RenderInstance {
|
||||||
if(containsServerDirective(props)) {
|
if (containsServerDirective(props)) {
|
||||||
return renderServerIsland(result, displayName, props, slots);
|
return renderServerIsland(result, displayName, props, slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = createAstroComponentInstance(result, displayName, Component, props, slots);
|
const instance = createAstroComponentInstance(result, displayName, Component, props, slots);
|
||||||
return {
|
return {
|
||||||
async render(destination) {
|
async render(destination) {
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
import type {
|
import type { SSRResult } from '../../../@types/astro.js';
|
||||||
SSRResult,
|
import { renderChild } from './any.js';
|
||||||
} from '../../../@types/astro.js';
|
import type { RenderInstance } from './common.js';
|
||||||
import { renderChild } from "./any.js";
|
import { type ComponentSlots, renderSlotToString } from './slot.js';
|
||||||
import type { RenderInstance } from "./common.js";
|
|
||||||
import { renderSlotToString, type ComponentSlots } from "./slot.js";
|
|
||||||
|
|
||||||
const internalProps = new Set([
|
const internalProps = new Set([
|
||||||
'server:component-path',
|
'server:component-path',
|
||||||
'server:component-export',
|
'server:component-export',
|
||||||
'server:component-directive',
|
'server:component-directive',
|
||||||
'server:defer'
|
'server:defer',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export function containsServerDirective(props: Record<string | number, any>,) {
|
export function containsServerDirective(props: Record<string | number, any>) {
|
||||||
return 'server:component-directive' in props;
|
return 'server:component-directive' in props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +18,7 @@ export function renderServerIsland(
|
||||||
result: SSRResult,
|
result: SSRResult,
|
||||||
_displayName: string,
|
_displayName: string,
|
||||||
props: Record<string | number, any>,
|
props: Record<string | number, any>,
|
||||||
slots: ComponentSlots,
|
slots: ComponentSlots
|
||||||
): RenderInstance {
|
): RenderInstance {
|
||||||
return {
|
return {
|
||||||
async render(destination) {
|
async render(destination) {
|
||||||
|
@ -28,23 +26,23 @@ export function renderServerIsland(
|
||||||
const componentExport = props['server:component-export'];
|
const componentExport = props['server:component-export'];
|
||||||
const componentId = result.serverIslandNameMap.get(componentPath);
|
const componentId = result.serverIslandNameMap.get(componentPath);
|
||||||
|
|
||||||
if(!componentId) {
|
if (!componentId) {
|
||||||
throw new Error(`Could not find server component name`);
|
throw new Error(`Could not find server component name`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove internal props
|
// Remove internal props
|
||||||
for(const key of Object.keys(props)) {
|
for (const key of Object.keys(props)) {
|
||||||
if(internalProps.has(key)) {
|
if (internalProps.has(key)) {
|
||||||
delete props[key];
|
delete props[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destination.write('<!--server-island-start-->')
|
destination.write('<!--server-island-start-->');
|
||||||
|
|
||||||
// Render the slots
|
// Render the slots
|
||||||
const renderedSlots: Record<string, string> = {};
|
const renderedSlots: Record<string, string> = {};
|
||||||
for(const name in slots) {
|
for (const name in slots) {
|
||||||
if(name !== 'fallback') {
|
if (name !== 'fallback') {
|
||||||
const content = await renderSlotToString(result, slots[name]);
|
const content = await renderSlotToString(result, slots[name]);
|
||||||
renderedSlots[name] = content.toString();
|
renderedSlots[name] = content.toString();
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +81,7 @@ if(response.status === 200 && response.headers.get('content-type') === 'text/htm
|
||||||
script.before(frag);
|
script.before(frag);
|
||||||
}
|
}
|
||||||
script.remove();
|
script.remove();
|
||||||
</script>`)
|
</script>`);
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ export async function renderSlots(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSlotValueFromString(content: string): ComponentSlotValue {
|
export function createSlotValueFromString(content: string): ComponentSlotValue {
|
||||||
return function() {
|
return function () {
|
||||||
return renderTemplate`${unescapeHTML(content)}`;
|
return renderTemplate`${unescapeHTML(content)}`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,8 +158,8 @@ export class DevPipeline extends Pipeline {
|
||||||
const { loader } = this;
|
const { loader } = this;
|
||||||
|
|
||||||
// First check built-in routes
|
// First check built-in routes
|
||||||
for(const route of this.defaultRoutes) {
|
for (const route of this.defaultRoutes) {
|
||||||
if(route.matchesComponent(filePath)) {
|
if (route.matchesComponent(filePath)) {
|
||||||
return route.instance;
|
return route.instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,8 +226,8 @@ export class DevPipeline extends Pipeline {
|
||||||
|
|
||||||
rewriteKnownRoute(route: string, sourceRoute: RouteData): ComponentInstance {
|
rewriteKnownRoute(route: string, sourceRoute: RouteData): ComponentInstance {
|
||||||
if (isServerLikeOutput(this.config) && sourceRoute.prerender) {
|
if (isServerLikeOutput(this.config) && sourceRoute.prerender) {
|
||||||
for(let def of this.defaultRoutes) {
|
for (let def of this.defaultRoutes) {
|
||||||
if(route === def.route) {
|
if (route === def.route) {
|
||||||
return def.instance;
|
return def.instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||||
import { patchOverlay } from '../core/errors/overlay.js';
|
import { patchOverlay } from '../core/errors/overlay.js';
|
||||||
import type { Logger } from '../core/logger/core.js';
|
import type { Logger } from '../core/logger/core.js';
|
||||||
import { createViteLoader } from '../core/module-loader/index.js';
|
import { createViteLoader } from '../core/module-loader/index.js';
|
||||||
import { createRouteManifest } from '../core/routing/index.js';
|
|
||||||
import { injectDefaultRoutes } from '../core/routing/default.js';
|
import { injectDefaultRoutes } from '../core/routing/default.js';
|
||||||
|
import { createRouteManifest } from '../core/routing/index.js';
|
||||||
import { toRoutingStrategy } from '../i18n/utils.js';
|
import { toRoutingStrategy } from '../i18n/utils.js';
|
||||||
import { baseMiddleware } from './base.js';
|
import { baseMiddleware } from './base.js';
|
||||||
import { createController } from './controller.js';
|
import { createController } from './controller.js';
|
||||||
|
@ -36,7 +36,7 @@ export default function createVitePluginAstroServer({
|
||||||
const loader = createViteLoader(viteServer);
|
const loader = createViteLoader(viteServer);
|
||||||
const manifest = createDevelopmentManifest(settings);
|
const manifest = createDevelopmentManifest(settings);
|
||||||
let manifestData: ManifestData = injectDefaultRoutes(
|
let manifestData: ManifestData = injectDefaultRoutes(
|
||||||
createRouteManifest({ settings, fsMod }, logger),
|
createRouteManifest({ settings, fsMod }, logger)
|
||||||
);
|
);
|
||||||
const pipeline = DevPipeline.create(manifestData, { loader, logger, manifest, settings });
|
const pipeline = DevPipeline.create(manifestData, { loader, logger, manifest, settings });
|
||||||
const controller = createController({ loader });
|
const controller = createController({ loader });
|
||||||
|
@ -46,9 +46,7 @@ export default function createVitePluginAstroServer({
|
||||||
function rebuildManifest(needsManifestRebuild: boolean) {
|
function rebuildManifest(needsManifestRebuild: boolean) {
|
||||||
pipeline.clearRouteCache();
|
pipeline.clearRouteCache();
|
||||||
if (needsManifestRebuild) {
|
if (needsManifestRebuild) {
|
||||||
manifestData = injectDefaultRoutes(
|
manifestData = injectDefaultRoutes(createRouteManifest({ settings }, logger));
|
||||||
createRouteManifest({ settings }, logger),
|
|
||||||
);
|
|
||||||
pipeline.setManifestData(manifestData);
|
pipeline.setManifestData(manifestData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||||
import type { Logger } from '../core/logger/core.js';
|
import type { Logger } from '../core/logger/core.js';
|
||||||
import { isMarkdownFile } from '../core/util.js';
|
import { isMarkdownFile } from '../core/util.js';
|
||||||
import { shorthash } from '../runtime/server/shorthash.js';
|
import { shorthash } from '../runtime/server/shorthash.js';
|
||||||
|
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
||||||
import { getFileInfo } from '../vite-plugin-utils/index.js';
|
import { getFileInfo } from '../vite-plugin-utils/index.js';
|
||||||
import { type MarkdownImagePath, getMarkdownCodeForImages } from './images.js';
|
import { type MarkdownImagePath, getMarkdownCodeForImages } from './images.js';
|
||||||
import { createDefaultAstroMetadata } from '../vite-plugin-astro/metadata.js';
|
|
||||||
|
|
||||||
interface AstroPluginOptions {
|
interface AstroPluginOptions {
|
||||||
settings: AstroSettings;
|
settings: AstroSettings;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { after, before, describe, it } from 'node:test';
|
import { after, before, describe, it } from 'node:test';
|
||||||
import * as cheerio from 'cheerio';
|
import * as cheerio from 'cheerio';
|
||||||
|
@ -27,22 +26,22 @@ describe('Server islands', () => {
|
||||||
await devServer.stop();
|
await devServer.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('omits the islands HTML', async () => {
|
it('omits the islands HTML', async () => {
|
||||||
const res = await fixture.fetch('/');
|
const res = await fixture.fetch('/');
|
||||||
assert.equal(res.status, 200);
|
assert.equal(res.status, 200);
|
||||||
const html = await res.text();
|
const html = await res.text();
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
const serverIslandEl = $('h2#island');
|
const serverIslandEl = $('h2#island');
|
||||||
assert.equal(serverIslandEl.length, 0);
|
assert.equal(serverIslandEl.length, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('prod', () => {
|
describe('prod', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('omits the islands HTML', async () => {
|
it('omits the islands HTML', async () => {
|
||||||
const app = await fixture.loadTestAdapterApp();
|
const app = await fixture.loadTestAdapterApp();
|
||||||
const request = new Request('http://example.com/');
|
const request = new Request('http://example.com/');
|
||||||
const response = await app.render(request);
|
const response = await app.render(request);
|
||||||
|
@ -54,8 +53,8 @@ describe('Server islands', () => {
|
||||||
|
|
||||||
const serverIslandScript = $('script[data-island-id]');
|
const serverIslandScript = $('script[data-island-id]');
|
||||||
assert.equal(serverIslandScript.length, 1, 'has the island script');
|
assert.equal(serverIslandScript.length, 1, 'has the island script');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Hybrid mode', () => {
|
describe('Hybrid mode', () => {
|
||||||
|
@ -93,11 +92,11 @@ describe('Server islands', () => {
|
||||||
componentExport: 'default',
|
componentExport: 'default',
|
||||||
props: {},
|
props: {},
|
||||||
slots: {},
|
slots: {},
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
return app.render(request);
|
return app.render(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Island returns its HTML', async () => {
|
it('Island returns its HTML', async () => {
|
||||||
const response = await fetchIsland();
|
const response = await fetchIsland();
|
||||||
const html = await response.text();
|
const html = await response.text();
|
||||||
|
|
Loading…
Reference in a new issue