diff --git a/.changeset/tough-cherries-bathe.md b/.changeset/tough-cherries-bathe.md new file mode 100644 index 0000000000..906d1f739b --- /dev/null +++ b/.changeset/tough-cherries-bathe.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improve build performance, especially on large sites diff --git a/.changeset/tough-dragons-sniff.md b/.changeset/tough-dragons-sniff.md new file mode 100644 index 0000000000..4b7697ca7d --- /dev/null +++ b/.changeset/tough-dragons-sniff.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Surface vite warnings to the user diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 6234505928..5f5be3ca7b 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -65,7 +65,7 @@ class AstroBuilder { { mode: this.mode, server: { - hmr: { overlay: false }, + hmr: false, middlewareMode: 'ssr', }, }, diff --git a/packages/astro/src/core/build/scan-based-build.ts b/packages/astro/src/core/build/scan-based-build.ts index 632d5489de..9a08ec1f6d 100644 --- a/packages/astro/src/core/build/scan-based-build.ts +++ b/packages/astro/src/core/build/scan-based-build.ts @@ -47,7 +47,7 @@ export async function build(opts: ScanBasedBuildOptions) { const internals = createBuildInternals(); return await vite.build({ - logLevel: 'error', + logLevel: 'warn', mode: 'production', build: { emptyOutDir: true, diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 9c014f87cf..50b58cdc5a 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -35,7 +35,11 @@ export interface StaticBuildOptions { viteConfig: ViteConfigWithSSR; } -const MAX_CONCURRENT_RENDERS = 10; +// Render is usually compute, which Node.js can't parallelize well. +// In real world testing, dropping from 10->1 showed a notiable perf +// improvement. In the future, we can revisit a smarter parallel +// system, possibly one that parallelizes if async IO is detected. +const MAX_CONCURRENT_RENDERS = 1; const STATUS_CODE_PAGES = new Set(['/404', '/500']); @@ -161,8 +165,9 @@ export async function staticBuild(opts: StaticBuildOptions) { // condition, so we are doing it ourselves emptyDir(astroConfig.dist, new Set('.git')); - // Run the SSR build and client build in parallel - const [ssrResult] = (await Promise.all([ssrBuild(opts, internals, pageInput), clientBuild(opts, internals, jsInput)])) as RollupOutput[]; + // Build your project (SSR application code, assets, client JS, etc.) + const ssrResult = await ssrBuild(opts, internals, pageInput) as RollupOutput; + await clientBuild(opts, internals, jsInput); // SSG mode, generate pages. if (staticMode) { @@ -181,13 +186,12 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp const out = ssr ? getServerRoot(astroConfig) : getOutRoot(astroConfig); return await vite.build({ - logLevel: 'error', + logLevel: 'warn', mode: 'production', build: { ...viteConfig.build, emptyOutDir: false, manifest: ssr, - minify: false, outDir: fileURLToPath(out), ssr: true, rollupOptions: { @@ -199,7 +203,12 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp assetFileNames: 'assets/[name].[hash][extname]', }, }, - target: 'esnext', // must match an esbuild target + // must match an esbuild target + target: 'esnext', + // improve build performance + minify: false, + polyfillModulePreload: false, + reportCompressedSize: false, }, plugins: [ vitePluginNewBuild(input, internals, 'mjs'), @@ -226,9 +235,8 @@ async function clientBuild(opts: StaticBuildOptions, internals: BuildInternals, } const out = astroConfig.buildOptions.experimentalSsr ? getClientRoot(astroConfig) : getOutRoot(astroConfig); - return await vite.build({ - logLevel: 'error', + logLevel: 'warn', mode: 'production', build: { emptyOutDir: false, @@ -295,13 +303,11 @@ async function generatePages(result: RollupOutput, opts: StaticBuildOptions, int // Get renderers to be shared for each page generation. const renderers = await collectRenderers(opts); - const generationPromises = []; for (let output of result.output) { if (chunkIsPage(opts.astroConfig, output, internals)) { - generationPromises.push(generatePage(output as OutputChunk, opts, internals, facadeIdToPageDataMap, renderers)); + await (generatePage(output as OutputChunk, opts, internals, facadeIdToPageDataMap, renderers)); } } - await Promise.all(generationPromises); } async function generatePage(output: OutputChunk, opts: StaticBuildOptions, internals: BuildInternals, facadeIdToPageDataMap: Map, renderers: Renderer[]) { diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index af0c17631a..b605d063c8 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -49,7 +49,7 @@ export async function createVite(inlineConfig: ViteConfigWithSSR, { astroConfig, let viteConfig: ViteConfigWithSSR = { cacheDir: fileURLToPath(new URL('./node_modules/.vite/', astroConfig.projectRoot)), // using local caches allows Astro to be used in monorepos, etc. clearScreen: false, // we want to control the output, not Vite - logLevel: 'error', // log errors only + logLevel: 'warn', // log warnings and errors only optimizeDeps: { entries: ['src/**/*'], // Try and scan a user’s project (won’t catch everything), }, diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index 4b74e1060a..f08eb32773 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -5,6 +5,7 @@ import type { LogOptions } from '../core/logger.js'; import esbuild from 'esbuild'; import { fileURLToPath } from 'url'; import slash from 'slash'; +import fs from 'fs'; import { getViteTransform, TransformHook } from './styles.js'; import { parseAstroRequest } from './query.js'; import { cachedCompilation } from './compile.js'; @@ -124,13 +125,11 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu } } - return null; - }, - async transform(source, id, opts) { if (!id.endsWith('.astro')) { - return; + return null; } + const source = await fs.promises.readFile(id, {encoding: 'utf-8'}); try { const transformResult = await cachedCompilation(config, id, source, viteTransform, { ssr: Boolean(opts?.ssr) }); @@ -140,6 +139,8 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu loader: 'ts', sourcemap: 'external', sourcefile: id, + // Pass relevant Vite options, if needed: + define: config.vite.define, }); // Signal to Vite that we accept HMR updates diff --git a/packages/astro/test/fixtures/astro-doctype/src/styles/global.css b/packages/astro/test/fixtures/astro-doctype/public/styles/global.css similarity index 100% rename from packages/astro/test/fixtures/astro-doctype/src/styles/global.css rename to packages/astro/test/fixtures/astro-doctype/public/styles/global.css diff --git a/packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro b/packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro index cbfe5c4784..c6befb6474 100644 --- a/packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro +++ b/packages/astro/test/fixtures/astro-doctype/src/layouts/WithDoctype.astro @@ -5,7 +5,7 @@ import Meta from '../components/Meta.astro'; My App - + diff --git a/packages/astro/test/fixtures/astro-doctype/src/layouts/WithoutDoctype.astro b/packages/astro/test/fixtures/astro-doctype/src/layouts/WithoutDoctype.astro index 692c75571f..d589cbeac7 100644 --- a/packages/astro/test/fixtures/astro-doctype/src/layouts/WithoutDoctype.astro +++ b/packages/astro/test/fixtures/astro-doctype/src/layouts/WithoutDoctype.astro @@ -1,7 +1,7 @@ My App - +