diff --git a/.changeset/four-worms-wonder.md b/.changeset/four-worms-wonder.md new file mode 100644 index 0000000000..409ada67eb --- /dev/null +++ b/.changeset/four-worms-wonder.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add "waiting for X integration" log for long-running integration hooks diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 154a77a7ad..aa823fef22 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -62,7 +62,7 @@ class AstroBuilder { debug('build', 'Initial setup...'); const { logging } = this; this.timer.init = performance.now(); - this.config = await runHookConfigSetup({ config: this.config, command: 'build' }); + this.config = await runHookConfigSetup({ config: this.config, command: 'build', logging }); this.manifest = createRouteManifest({ config: this.config }, this.logging); const viteConfig = await createVite( @@ -76,7 +76,7 @@ class AstroBuilder { }, { astroConfig: this.config, logging, mode: 'build' } ); - await runHookConfigDone({ config: this.config }); + await runHookConfigDone({ config: this.config, logging }); return { viteConfig }; } @@ -87,7 +87,7 @@ class AstroBuilder { server: new URL('./server/', this.config.outDir), serverEntry: 'entry.mjs', }; - await runHookBuildStart({ config: this.config, buildConfig }); + await runHookBuildStart({ config: this.config, buildConfig, logging: this.logging }); info(this.logging, 'build', `output target: ${colors.green(this.config.output)}`); if (this.config._ctx.adapter) { @@ -145,6 +145,7 @@ class AstroBuilder { buildConfig, pages: pageNames, routes: Object.values(allPages).map((pd) => pd.route), + logging: this.logging, }); if (this.logging.level && levels[this.logging.level] <= levels['info']) { diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index f7e205205c..06bae75f45 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -167,6 +167,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp pages: internals.pagesByComponent, vite: viteBuildConfig, target: 'server', + logging: opts.logging, }); return await vite.build(viteBuildConfig); @@ -236,6 +237,7 @@ async function clientBuild( pages: internals.pagesByComponent, vite: viteBuildConfig, target: 'client', + logging: opts.logging, }); const buildResult = await vite.build(viteBuildConfig); diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts index 71a58bfe4c..84352af725 100644 --- a/packages/astro/src/core/build/vite-plugin-ssr.ts +++ b/packages/astro/src/core/build/vite-plugin-ssr.ts @@ -103,7 +103,7 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B const staticFiles = internals.staticFiles; const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles)); - await runHookBuildSsr({ config: buildOpts.astroConfig, manifest }); + await runHookBuildSsr({ config: buildOpts.astroConfig, manifest, logging: buildOpts.logging }); const chunk = internals.ssrEntryChunk; const code = chunk.code; diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 37a31ed666..e981d983d0 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -83,7 +83,7 @@ export async function createVite( htmlVitePlugin(), jsxVitePlugin({ config: astroConfig, logging }), astroPostprocessVitePlugin({ config: astroConfig }), - astroIntegrationsContainerPlugin({ config: astroConfig }), + astroIntegrationsContainerPlugin({ config: astroConfig, logging }), astroScriptsPageSSRPlugin({ config: astroConfig }), ], publicDir: fileURLToPath(astroConfig.publicDir), diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts index eff09c5a4e..b768093ed7 100644 --- a/packages/astro/src/core/dev/index.ts +++ b/packages/astro/src/core/dev/index.ts @@ -31,7 +31,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro const devStart = performance.now(); applyPolyfill(); await options.telemetry.record([]); - config = await runHookConfigSetup({ config, command: 'dev' }); + config = await runHookConfigSetup({ config, command: 'dev', logging: options.logging }); const { host, port } = config.server; // The client entrypoint for renderers. Since these are imported dynamically @@ -50,9 +50,9 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro }, { astroConfig: config, logging: options.logging, mode: 'dev' } ); - await runHookConfigDone({ config }); + await runHookConfigDone({ config, logging: options.logging }); const viteServer = await vite.createServer(viteConfig); - runHookServerSetup({ config, server: viteServer }); + runHookServerSetup({ config, server: viteServer, logging: options.logging }); await viteServer.listen(port); const devServerAddressInfo = viteServer.httpServer!.address() as AddressInfo; @@ -77,7 +77,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro warn(options.logging, null, msg.fsStrictWarning()); } - await runHookServerStart({ config, address: devServerAddressInfo }); + await runHookServerStart({ config, address: devServerAddressInfo, logging: options.logging }); return { address: devServerAddressInfo, @@ -86,7 +86,7 @@ export default async function dev(config: AstroConfig, options: DevOptions): Pro }, stop: async () => { await viteServer.close(); - await runHookServerDone({ config }); + await runHookServerDone({ config, logging: options.logging }); }, }; } diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index 89abcf12ab..0f6832bdab 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -1,5 +1,6 @@ import type { AddressInfo } from 'net'; import type { ViteDevServer } from 'vite'; +import { bold } from 'kleur/colors'; import { AstroConfig, AstroRenderer, @@ -11,13 +12,35 @@ import type { SerializedSSRManifest } from '../core/app/types'; import type { PageBuildData } from '../core/build/types'; import { mergeConfig } from '../core/config.js'; import type { ViteConfigWithSSR } from '../core/create-vite.js'; +import { info, LogOptions } from '../core/logger/core.js'; + +async function withTakingALongTimeMsg({ + name, + hookResult, + timeoutMs = 3000, + logging, +}: { + name: string; + hookResult: T | Promise; + timeoutMs?: number; + logging: LogOptions; +}): Promise { + const timeout = setTimeout(() => { + info(logging, 'build', `Waiting for the ${bold(name)} integration...`); + }, timeoutMs); + const result = await hookResult; + clearTimeout(timeout); + return result; +} export async function runHookConfigSetup({ config: _config, command, + logging, }: { config: AstroConfig; command: 'dev' | 'build'; + logging: LogOptions; }): Promise { // An adapter is an integration, so if one is provided push it. if (_config.adapter) { @@ -65,25 +88,39 @@ export async function runHookConfigSetup({ writable: false, enumerable: false, }); - await integration.hooks['astro:config:setup'](hooks); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:config:setup'](hooks), + logging, + }); } } return updatedConfig; } -export async function runHookConfigDone({ config }: { config: AstroConfig }) { +export async function runHookConfigDone({ + config, + logging, +}: { + config: AstroConfig; + logging: LogOptions; +}) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:config:done']) { - await integration.hooks['astro:config:done']({ - config, - setAdapter(adapter) { - if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) { - throw new Error( - `Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.` - ); - } - config._ctx.adapter = adapter; - }, + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:config:done']({ + config, + setAdapter(adapter) { + if (config._ctx.adapter && config._ctx.adapter.name !== adapter.name) { + throw new Error( + `Integration "${integration.name}" conflicts with "${config._ctx.adapter.name}". You can only configure one deployment integration.` + ); + } + config._ctx.adapter = adapter; + }, + }), + logging, }); } } @@ -92,13 +129,19 @@ export async function runHookConfigDone({ config }: { config: AstroConfig }) { export async function runHookServerSetup({ config, server, + logging, }: { config: AstroConfig; server: ViteDevServer; + logging: LogOptions; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:server:setup']) { - await integration.hooks['astro:server:setup']({ server }); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:server:setup']({ server }), + logging, + }); } } } @@ -106,21 +149,37 @@ export async function runHookServerSetup({ export async function runHookServerStart({ config, address, + logging, }: { config: AstroConfig; address: AddressInfo; + logging: LogOptions; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:server:start']) { - await integration.hooks['astro:server:start']({ address }); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:server:start']({ address }), + logging, + }); } } } -export async function runHookServerDone({ config }: { config: AstroConfig }) { +export async function runHookServerDone({ + config, + logging, +}: { + config: AstroConfig; + logging: LogOptions; +}) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:server:done']) { - await integration.hooks['astro:server:done'](); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:server:done'](), + logging, + }); } } } @@ -128,13 +187,19 @@ export async function runHookServerDone({ config }: { config: AstroConfig }) { export async function runHookBuildStart({ config, buildConfig, + logging, }: { config: AstroConfig; buildConfig: BuildConfig; + logging: LogOptions; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:start']) { - await integration.hooks['astro:build:start']({ buildConfig }); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:build:start']({ buildConfig }), + logging, + }); } } } @@ -144,21 +209,27 @@ export async function runHookBuildSetup({ vite, pages, target, + logging, }: { config: AstroConfig; vite: ViteConfigWithSSR; pages: Map; target: 'server' | 'client'; + logging: LogOptions; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:setup']) { - await integration.hooks['astro:build:setup']({ - vite, - pages, - target, - updateConfig: (newConfig) => { - mergeConfig(vite, newConfig); - }, + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:build:setup']({ + vite, + pages, + target, + updateConfig: (newConfig) => { + mergeConfig(vite, newConfig); + }, + }), + logging, }); } } @@ -167,13 +238,19 @@ export async function runHookBuildSetup({ export async function runHookBuildSsr({ config, manifest, + logging, }: { config: AstroConfig; manifest: SerializedSSRManifest; + logging: LogOptions; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:ssr']) { - await integration.hooks['astro:build:ssr']({ manifest }); + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:build:ssr']({ manifest }), + logging, + }); } } } @@ -183,20 +260,26 @@ export async function runHookBuildDone({ buildConfig, pages, routes, + logging, }: { config: AstroConfig; buildConfig: BuildConfig; pages: string[]; routes: RouteData[]; + logging: LogOptions; }) { const dir = config.output === 'server' ? buildConfig.client : config.outDir; for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:done']) { - await integration.hooks['astro:build:done']({ - pages: pages.map((p) => ({ pathname: p })), - dir, - routes, + await withTakingALongTimeMsg({ + name: integration.name, + hookResult: integration.hooks['astro:build:done']({ + pages: pages.map((p) => ({ pathname: p })), + dir, + routes, + }), + logging, }); } } diff --git a/packages/astro/src/vite-plugin-integrations-container/index.ts b/packages/astro/src/vite-plugin-integrations-container/index.ts index 5be13be1ba..f386cd0558 100644 --- a/packages/astro/src/vite-plugin-integrations-container/index.ts +++ b/packages/astro/src/vite-plugin-integrations-container/index.ts @@ -1,17 +1,20 @@ import { Plugin as VitePlugin } from 'vite'; import { AstroConfig } from '../@types/astro.js'; +import { LogOptions } from '../core/logger/core.js'; import { runHookServerSetup } from '../integrations/index.js'; /** Connect Astro integrations into Vite, as needed. */ export default function astroIntegrationsContainerPlugin({ config, + logging, }: { config: AstroConfig; + logging: LogOptions; }): VitePlugin { return { name: 'astro:integration-container', configureServer(server) { - runHookServerSetup({ config, server }); + runHookServerSetup({ config, server, logging }); }, }; }