diff --git a/.changeset/fresh-moose-compare.md b/.changeset/fresh-moose-compare.md new file mode 100644 index 0000000000..4dfd6fcde5 --- /dev/null +++ b/.changeset/fresh-moose-compare.md @@ -0,0 +1,7 @@ +--- +'astro': patch +--- + +Fixes build slowness on large apps + +This fixes slowness on large apps, particularly during the static build. Fix is to prevent the Vite dev server plugin from being run during build, as it is not needed. diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 0142713511..b54e68622e 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -71,7 +71,7 @@ class AstroBuilder { }, this.config.vite || {} ), - { astroConfig: this.config, logging } + { astroConfig: this.config, logging, mode: 'build' } ); this.viteConfig = viteConfig; const viteServer = await vite.createServer(viteConfig); diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 61eb5edc72..b458bea285 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -35,10 +35,11 @@ export type ViteConfigWithSSR = vite.InlineConfig & { ssr?: { external?: string[ interface CreateViteOptions { astroConfig: AstroConfig; logging: LogOptions; + mode: 'dev' | 'build'; } /** Return a common starting point for all Vite actions */ -export async function createVite(inlineConfig: ViteConfigWithSSR, { astroConfig, logging }: CreateViteOptions): Promise { +export async function createVite(inlineConfig: ViteConfigWithSSR, { astroConfig, logging, mode }: CreateViteOptions): Promise { // First, start with the Vite configuration that Astro core needs let viteConfig: ViteConfigWithSSR = { cacheDir: fileURLToPath(new URL('./node_modules/.vite/', astroConfig.projectRoot)), // using local caches allows Astro to be used in monorepos, etc. @@ -50,7 +51,9 @@ export async function createVite(inlineConfig: ViteConfigWithSSR, { astroConfig, plugins: [ configAliasVitePlugin({ config: astroConfig }), astroVitePlugin({ config: astroConfig, logging }), - astroViteServerPlugin({ config: astroConfig, logging }), + // The server plugin is for dev only and having it run during the build causes + // the build to run very slow as the filewatcher is triggered often. + mode === 'dev' && astroViteServerPlugin({ config: astroConfig, logging }), markdownVitePlugin({ config: astroConfig }), jsxVitePlugin({ config: astroConfig, logging }), astroPostprocessVitePlugin({ config: astroConfig }), diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts index c8da25490d..37fc767fcf 100644 --- a/packages/astro/src/core/dev/index.ts +++ b/packages/astro/src/core/dev/index.ts @@ -33,7 +33,7 @@ export default async function dev(config: AstroConfig, options: DevOptions = { l }, config.vite || {} ); - const viteConfig = await createVite(viteUserConfig, { astroConfig: config, logging: options.logging }); + const viteConfig = await createVite(viteUserConfig, { astroConfig: config, logging: options.logging, mode: 'dev' }); const viteServer = await vite.createServer(viteConfig); await viteServer.listen(config.devOptions.port); const address = viteServer.httpServer!.address() as AddressInfo; diff --git a/packages/astro/test/astro-class-list.test.js b/packages/astro/test/astro-class-list.test.js index 46549788a2..9516c3002f 100644 --- a/packages/astro/test/astro-class-list.test.js +++ b/packages/astro/test/astro-class-list.test.js @@ -2,14 +2,14 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ projectRoot: './fixtures/astro-class-list/' }); - await fixture.build(); -}); - describe('Class List', async () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-class-list/' }); + await fixture.build(); + }); + it('Passes class:list attributes as expected to elements', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/astro-client-only.test.js b/packages/astro/test/astro-client-only.test.js index 2f767ba5be..c39ae4535c 100644 --- a/packages/astro/test/astro-client-only.test.js +++ b/packages/astro/test/astro-client-only.test.js @@ -2,14 +2,14 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ projectRoot: './fixtures/astro-client-only/' }); - await fixture.build(); -}); - describe('Client only components', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-client-only/' }); + await fixture.build(); + }); + it('Loads pages using client:only hydrator', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/astro-component-code.test.js b/packages/astro/test/astro-component-code.test.js index f8a7ed9567..6c143eb187 100644 --- a/packages/astro/test/astro-component-code.test.js +++ b/packages/astro/test/astro-component-code.test.js @@ -2,14 +2,14 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ projectRoot: './fixtures/astro-component-code/' }); - await fixture.build(); -}); - describe('', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-component-code/' }); + await fixture.build(); + }); + it(' without lang or theme', async () => { let html = await fixture.readFile('/no-lang/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/astro-doctype.test.js b/packages/astro/test/astro-doctype.test.js index a5fdba6fdb..fb7038fd05 100644 --- a/packages/astro/test/astro-doctype.test.js +++ b/packages/astro/test/astro-doctype.test.js @@ -2,14 +2,14 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ projectRoot: './fixtures/astro-doctype/' }); - await fixture.build(); -}); - describe('Doctype', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-doctype/' }); + await fixture.build(); + }); + it('Automatically prepends the standards mode doctype', async () => { const html = await fixture.readFile('/prepend/index.html'); diff --git a/packages/astro/test/astro-jsx.test.js b/packages/astro/test/astro-jsx.test.js index e8fbdb8586..cca247d017 100644 --- a/packages/astro/test/astro-jsx.test.js +++ b/packages/astro/test/astro-jsx.test.js @@ -1,41 +1,44 @@ import { expect } from 'chai'; import { loadFixture } from './test-utils.js'; -let cwd = './fixtures/astro-jsx/'; -let orders = [ - ['preact', 'react', 'solid'], - ['preact', 'solid', 'react'], - ['react', 'preact', 'solid'], - ['react', 'solid', 'preact'], - ['solid', 'react', 'preact'], - ['solid', 'preact', 'react'], -]; -let fixtures = {}; +describe('JSX', () => { -before(async () => { - await Promise.all( - orders.map((renderers, n) => - loadFixture({ - projectRoot: cwd, - renderers: renderers.map((name) => `@astrojs/renderer-${name}`), - dist: new URL(`${cwd}dist-${n}/`, import.meta.url), - }).then((fixture) => { - fixtures[renderers.toString()] = fixture; - return fixture.build(); - }) - ) - ); -}); - -it('Renderer order', () => { - it('JSX renderers can be defined in any order', async () => { - if (!Object.values(fixtures).length) { - throw new Error(`JSX renderers didn’t build properly`); - } - - for (const [name, fixture] of Object.entries(fixtures)) { - const html = await fixture.readFile('/index.html'); - expect(html, name).to.be.ok; - } + let cwd = './fixtures/astro-jsx/'; + let orders = [ + ['preact', 'react', 'solid'], + ['preact', 'solid', 'react'], + ['react', 'preact', 'solid'], + ['react', 'solid', 'preact'], + ['solid', 'react', 'preact'], + ['solid', 'preact', 'react'], + ]; + let fixtures = {}; + + before(async () => { + await Promise.all( + orders.map((renderers, n) => + loadFixture({ + projectRoot: cwd, + renderers: renderers.map((name) => `@astrojs/renderer-${name}`), + dist: new URL(`${cwd}dist-${n}/`, import.meta.url), + }).then((fixture) => { + fixtures[renderers.toString()] = fixture; + return fixture.build(); + }) + ) + ); + }); + + it('Renderer order', () => { + it('JSX renderers can be defined in any order', async () => { + if (!Object.values(fixtures).length) { + throw new Error(`JSX renderers didn’t build properly`); + } + + for (const [name, fixture] of Object.entries(fixtures)) { + const html = await fixture.readFile('/index.html'); + expect(html, name).to.be.ok; + } + }); }); }); diff --git a/packages/astro/test/astro-pagination.test.js b/packages/astro/test/astro-pagination.test.js index acdef93a4c..923342cd7e 100644 --- a/packages/astro/test/astro-pagination.test.js +++ b/packages/astro/test/astro-pagination.test.js @@ -2,20 +2,20 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ - projectRoot: './fixtures/astro-pagination/', - buildOptions: { - site: 'https://mysite.dev/blog/', - sitemap: false, - }, - }); - await fixture.build(); -}); - describe('Pagination', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/astro-pagination/', + buildOptions: { + site: 'https://mysite.dev/blog/', + sitemap: false, + }, + }); + await fixture.build(); + }); + it('optional root page', async () => { for (const file of ['/posts/optional-root-page/index.html', '/posts/optional-root-page/2/index.html', '/posts/optional-root-page/3/index.html']) { expect(await fixture.readFile(file)).to.be.ok; diff --git a/packages/astro/test/builtins.test.js b/packages/astro/test/builtins.test.js index 8eff6b7928..af2fea0b88 100644 --- a/packages/astro/test/builtins.test.js +++ b/packages/astro/test/builtins.test.js @@ -2,14 +2,14 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ projectRoot: './fixtures/builtins/' }); - await fixture.build(); -}); - describe('Node builtins', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/builtins/' }); + await fixture.build(); + }); + it('Can be used with the node: prefix', async () => { const html = await fixture.readFile('/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/lit-element.test.js b/packages/astro/test/lit-element.test.js index 07367431f9..ad11fb641a 100644 --- a/packages/astro/test/lit-element.test.js +++ b/packages/astro/test/lit-element.test.js @@ -2,24 +2,24 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -const NODE_VERSION = parseFloat(process.versions.node); -const stripExpressionMarkers = (html) => html.replace(//g, ''); - -before(async () => { - // @lit-labs/ssr/ requires Node 13.9 or higher - if (NODE_VERSION < 13.9) { - return; - } - fixture = await loadFixture({ - projectRoot: './fixtures/lit-element/', - renderers: ['@astrojs/renderer-lit'], - }); - await fixture.build(); -}); - describe('LitElement test', () => { + let fixture; + + const NODE_VERSION = parseFloat(process.versions.node); + const stripExpressionMarkers = (html) => html.replace(//g, ''); + + before(async () => { + // @lit-labs/ssr/ requires Node 13.9 or higher + if (NODE_VERSION < 13.9) { + return; + } + fixture = await loadFixture({ + projectRoot: './fixtures/lit-element/', + renderers: ['@astrojs/renderer-lit'], + }); + await fixture.build(); + }); + it('Renders a custom element by tag name', async () => { // @lit-labs/ssr/ requires Node 13.9 or higher if (NODE_VERSION < 13.9) { diff --git a/packages/astro/test/markdown.test.js b/packages/astro/test/markdown.test.js index aec486a19b..db0ed8a4e2 100644 --- a/packages/astro/test/markdown.test.js +++ b/packages/astro/test/markdown.test.js @@ -2,20 +2,20 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ - projectRoot: './fixtures/markdown/', - buildOptions: { - sitemap: false, - }, - renderers: ['@astrojs/renderer-preact'], - }); - await fixture.build(); -}); - describe('Markdown tests', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/markdown/', + buildOptions: { + sitemap: false, + }, + renderers: ['@astrojs/renderer-preact'], + }); + await fixture.build(); + }); + it('Can load a simple markdown page with Astro', async () => { const html = await fixture.readFile('/post/index.html'); const $ = cheerio.load(html); diff --git a/packages/astro/test/postcss.test.js b/packages/astro/test/postcss.test.js index 09ef4a0bc9..006c432e10 100644 --- a/packages/astro/test/postcss.test.js +++ b/packages/astro/test/postcss.test.js @@ -3,25 +3,25 @@ import cheerio from 'cheerio'; import eol from 'eol'; import { loadFixture } from './test-utils.js'; -const PREFIXED_CSS = `{-webkit-appearance:none;appearance:none}`; - -let fixture; -let bundledCSS; -before(async () => { - fixture = await loadFixture({ - projectRoot: './fixtures/postcss', - renderers: ['@astrojs/renderer-solid', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'], - }); - await fixture.build(); - - // get bundled CSS (will be hashed, hence DOM query) - const html = await fixture.readFile('/index.html'); - const $ = cheerio.load(html); - const bundledCSSHREF = $('link[rel=stylesheet][href^=./assets/]').attr('href'); - bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); -}); - describe('PostCSS', () => { + const PREFIXED_CSS = `{-webkit-appearance:none;appearance:none}`; + + let fixture; + let bundledCSS; + before(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/postcss', + renderers: ['@astrojs/renderer-solid', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'], + }); + await fixture.build(); + + // get bundled CSS (will be hashed, hence DOM query) + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + const bundledCSSHREF = $('link[rel=stylesheet][href^=./assets/]').attr('href'); + bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); + }); + it('works in Astro page styles', () => { expect(bundledCSS).to.match(new RegExp(`.astro-page.astro-[^{]+${PREFIXED_CSS}`)); }); diff --git a/packages/astro/test/preact-component.test.js b/packages/astro/test/preact-component.test.js index 4684d48e13..10d4820720 100644 --- a/packages/astro/test/preact-component.test.js +++ b/packages/astro/test/preact-component.test.js @@ -2,20 +2,20 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - -before(async () => { - fixture = await loadFixture({ - devOptions: { - port: 3009, - }, - projectRoot: './fixtures/preact-component/', - renderers: ['@astrojs/renderer-preact'], - }); - await fixture.build(); -}); - describe('Preact component', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + devOptions: { + port: 3009, + }, + projectRoot: './fixtures/preact-component/', + renderers: ['@astrojs/renderer-preact'], + }); + await fixture.build(); + }); + it('Can load class component', async () => { const html = await fixture.readFile('/class/index.html'); const $ = cheerio.load(html);