${statusCode ? `${statusCode} ` : ''}${title}
-${message.replace(/\n/g, '
')}
${encode(message)}
diff --git a/packages/astro/package.json b/packages/astro/package.json index 76ab7ba0e..2d5541722 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -73,6 +73,7 @@ "fast-xml-parser": "^3.19.0", "fdir": "^5.1.0", "get-port": "^5.1.1", + "html-entities": "^2.3.2", "kleur": "^4.1.4", "mime": "^2.5.2", "morphdom": "^2.6.1", @@ -88,6 +89,7 @@ "source-map": "^0.7.3", "srcset-parse": "^1.1.0", "string-width": "^5.0.0", + "strip-ansi": "^7.0.1", "supports-esm": "^1.0.0", "vite": "^2.5.7", "yargs-parser": "^20.2.9", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 762e3eca0..668efc18e 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -312,6 +312,8 @@ export type RSSResult = { url: string; xml?: string }; export type ScriptInfo = ScriptInfoInline | ScriptInfoExternal; +export type SSRError = Error & vite.ErrorPayload['err']; + export interface ScriptInfoInline { content: string; } diff --git a/packages/astro/src/dev/index.ts b/packages/astro/src/dev/index.ts index 1bec87310..8756f0b08 100644 --- a/packages/astro/src/dev/index.ts +++ b/packages/astro/src/dev/index.ts @@ -1,6 +1,6 @@ import type { NextFunction } from 'connect'; import type http from 'http'; -import type { AstroConfig, ManifestData, RouteCache, RouteData } from '../@types/astro'; +import type { AstroConfig, ManifestData, RouteCache, RouteData, SSRError } from '../@types/astro'; import type { LogOptions } from '../logger'; import type { HmrContext, ModuleNode } from 'vite'; @@ -11,8 +11,7 @@ import getEtag from 'etag'; import { performance } from 'perf_hooks'; import { fileURLToPath } from 'url'; import { createRequire } from 'module'; -import path from 'path'; -import { promises as fs } from 'fs'; +import stripAnsi from 'strip-ansi'; import vite from 'vite'; import { defaultLogOptions, error, info } from '../logger.js'; import { createRouteManifest, matchRoute } from '../runtime/routing.js'; @@ -153,6 +152,8 @@ export class AstroDevServer { return this.viteServer.middlewares.handle(req, res, next); } + let filePath: URL | undefined; + try { const route = matchRoute(pathname, this.manifest); @@ -165,9 +166,10 @@ export class AstroDevServer { this.mostRecentRoute = route; // handle .astro and .md pages + filePath = new URL(`./${route.component}`, this.config.projectRoot); const html = await ssr({ astroConfig: this.config, - filePath: new URL(`./${route.component}`, this.config.projectRoot), + filePath, logging: this.logging, mode: 'development', origin: this.origin, @@ -183,12 +185,16 @@ export class AstroDevServer { }); res.write(html); res.end(); - } catch (e) { - const err = e as Error; + } catch (err: any) { this.viteServer.ssrFixStacktrace(err); - console.log(err.stack); + this.viteServer.ws.send({ type: 'error', err }); const statusCode = 500; - const html = errorTemplate({ statusCode, title: 'Internal Error', tabTitle: '500: Error', message: err.message }); + const html = errorTemplate({ + statusCode, + title: 'Internal Error', + tabTitle: '500: Error', + message: stripAnsi(err.message), + }); info(this.logging, 'astro', msg.req({ url: pathname, statusCode: 500, reqTime: performance.now() - reqStart })); res.writeHead(statusCode, { 'Content-Type': mime.getType('.html') as string, diff --git a/packages/astro/src/dev/template/error.ts b/packages/astro/src/dev/template/error.ts index e29694302..7060e93a0 100644 --- a/packages/astro/src/dev/template/error.ts +++ b/packages/astro/src/dev/template/error.ts @@ -1,3 +1,5 @@ +import { encode } from 'html-entities'; + interface ErrorTemplateOptions { statusCode?: number; tabTitle: string; @@ -29,7 +31,7 @@ export function errorTemplate({ title, message, statusCode, tabTitle }: ErrorTem margin-top: 1rem; margin-bottom: 0; } - p { + pre { color: #999; font-size: 1.4em; margin-top: 0; @@ -43,7 +45,7 @@ export function errorTemplate({ title, message, statusCode, tabTitle }: ErrorTem
${message.replace(/\n/g, '
')}
${encode(message)}