Node.js adapter for Astro framework enabling server-side rendering and standalone server deployments
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Development preview server functionality for testing built applications locally with configurable host and port options.
Creates a preview server for testing built Astro applications in development with automatic server management and networking features.
/**
* Creates preview server for development testing of built applications
* @param preview - Preview configuration including server entrypoint and networking
* @returns Promise resolving to PreviewServer instance with control methods
* @throws AstroError if server entrypoint is missing or invalid
*/
function createPreviewServer(preview: PreviewParams): Promise<PreviewServer>;
interface PreviewParams {
/** Path to built server entrypoint module */
serverEntrypoint: URL;
/** Host to bind server to - defaults based on CLI arguments */
host?: string;
/** Port to bind server to - defaults to 4321 */
port?: number;
/** Custom headers to add to responses */
headers?: Record<string, string>;
/** Astro logger instance for output */
logger: AstroIntegrationLogger;
}
interface PreviewServer {
/** Resolved host server is bound to */
host: string;
/** Port server is listening on */
port: number;
/** Promise that resolves when server is closed */
closed(): Promise<void>;
/** Gracefully stop the server */
stop(): Promise<void>;
}Usage Examples:
import createPreviewServer from "@astrojs/node/preview.js";
// Basic preview server
const server = await createPreviewServer({
serverEntrypoint: new URL("./dist/server.js", import.meta.url),
logger: astroLogger
});
console.log(`Preview server running at http://${server.host}:${server.port}`);
// Stop server when done
await server.stop();// Preview server with custom configuration
const server = await createPreviewServer({
serverEntrypoint: new URL("./dist/server.js", import.meta.url),
host: "0.0.0.0", // Listen on all interfaces
port: 3000,
headers: {
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff"
},
logger: astroLogger
});The preview server uses sophisticated host resolution logic to handle different CLI argument patterns:
/**
* Resolves host configuration for preview server binding
* @param configuredHost - Host value from configuration or CLI
* @returns Resolved host string for server binding
*/
function getResolvedHostForHttpServer(host: string | boolean | undefined): string | undefined;Host Resolution Logic:
false: Returns 'localhost' (secure default)true: Returns undefined (listen on all IPs - 0.0.0.0 or ::)undefined: Uses environment or default to '0.0.0.0'string: Uses provided host value directlyEnvironment Variables:
The preview server prevents auto-start of the server entrypoint to avoid conflicts:
// Disables auto-start before importing server module
process.env.ASTRO_NODE_AUTOSTART = 'disabled';Validates that the server entrypoint exists and exports the required handler:
interface ServerModule {
/** Request handler function from server entrypoint */
handler: (
req: IncomingMessage,
res: ServerResponse,
next?: (err?: unknown) => void,
locals?: object
) => void | Promise<void>;
}Error Conditions:
Automatically adds custom headers to successful responses (status 200):
if (preview.headers) {
server.server.addListener('request', (_, res) => {
if (res.statusCode === 200) {
for (const [name, value] of Object.entries(preview.headers ?? {})) {
if (value) res.setHeader(name, value);
}
}
});
}Header Application:
The preview server provides detailed network information including local and network addresses:
/**
* Logs server listening information with local and network addresses
* @param logger - Astro integration logger for formatted output
* @param server - HTTP/HTTPS server instance
* @param configuredHost - Host configuration for address resolution
* @returns Promise that resolves when logging is complete
*/
function logListeningOn(
logger: AstroIntegrationLogger,
server: http.Server | https.Server,
configuredHost: string | boolean | undefined
): Promise<void>;Address Detection:
Example Output:
Server listening on
local: http://localhost:4321
network: http://192.168.1.100:4321Preview server supports HTTPS via environment variables (same as standalone mode):
// Environment variables for HTTPS
SERVER_CERT_PATH="/path/to/certificate.pem"
SERVER_KEY_PATH="/path/to/private-key.pem"HTTPS Configuration:
The preview server handles various startup error conditions:
await new Promise<void>((resolve, reject) => {
server.server.once('listening', resolve);
server.server.once('error', reject);
server.server.listen(port, host);
});Common Error Scenarios:
Provides helpful error messages for common preview issues:
if (
(err as any).code === 'ERR_MODULE_NOT_FOUND' &&
(err as any).url === preview.serverEntrypoint.href
) {
throw new AstroError(
`The server entrypoint ${fileURLToPath(
preview.serverEntrypoint,
)} does not exist. Have you ran a build yet?`,
);
}The preview server supports graceful shutdown with cleanup:
async stop() {
await new Promise((resolve, reject) => {
httpServer.destroy((err) => (err ? reject(err) : resolve(undefined)));
});
}Shutdown Process:
The preview server integrates with Astro's preview command:
# Basic preview
astro preview
# Custom host and port
astro preview --host 0.0.0.0 --port 3000
# With custom headers (via astro.config.mjs)
astro previewCLI Argument Mapping:
--host without value: host = true (listen on all interfaces)--host <value>: host = <value> (listen on specific interface)--port <number>: port = <number> (use specific port)