diff options
| -rw-r--r-- | .changeset/healthy-meals-wink.md | 5 | ||||
| -rw-r--r-- | examples/with-vitest/.gitignore | 19 | ||||
| -rw-r--r-- | examples/with-vitest/.npmrc | 2 | ||||
| -rw-r--r-- | examples/with-vitest/.stackblitzrc | 6 | ||||
| -rw-r--r-- | examples/with-vitest/README.md | 9 | ||||
| -rw-r--r-- | examples/with-vitest/astro.config.ts | 4 | ||||
| -rw-r--r-- | examples/with-vitest/package.json | 17 | ||||
| -rw-r--r-- | examples/with-vitest/public/favicon.ico | bin | 0 -> 4286 bytes | |||
| -rw-r--r-- | examples/with-vitest/sandbox.config.json | 11 | ||||
| -rw-r--r-- | examples/with-vitest/src/pages/index.astro | 13 | ||||
| -rw-r--r-- | examples/with-vitest/test/basic.test.ts | 21 | ||||
| -rw-r--r-- | examples/with-vitest/tsconfig.json | 18 | ||||
| -rw-r--r-- | examples/with-vitest/vitest.config.ts | 9 | ||||
| -rw-r--r-- | packages/astro/config.d.ts | 6 | ||||
| -rw-r--r-- | packages/astro/config.mjs | 40 | ||||
| -rw-r--r-- | packages/astro/package.json | 1 | ||||
| -rw-r--r-- | packages/astro/src/core/create-vite.ts | 4 | ||||
| -rw-r--r-- | pnpm-lock.yaml | 67 | 
18 files changed, 248 insertions, 4 deletions
| diff --git a/.changeset/healthy-meals-wink.md b/.changeset/healthy-meals-wink.md new file mode 100644 index 000000000..4cc5e10b1 --- /dev/null +++ b/.changeset/healthy-meals-wink.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Expose `getViteConfig` from `astro/config` to unblock usage with Vitest diff --git a/examples/with-vitest/.gitignore b/examples/with-vitest/.gitignore new file mode 100644 index 000000000..02f6e50b4 --- /dev/null +++ b/examples/with-vitest/.gitignore @@ -0,0 +1,19 @@ +# build output +dist/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/examples/with-vitest/.npmrc b/examples/with-vitest/.npmrc new file mode 100644 index 000000000..ef83021af --- /dev/null +++ b/examples/with-vitest/.npmrc @@ -0,0 +1,2 @@ +# Expose Astro dependencies for `pnpm` users +shamefully-hoist=true diff --git a/examples/with-vitest/.stackblitzrc b/examples/with-vitest/.stackblitzrc new file mode 100644 index 000000000..43798ecff --- /dev/null +++ b/examples/with-vitest/.stackblitzrc @@ -0,0 +1,6 @@ +{ +  "startCommand": "npm start", +  "env": { +    "ENABLE_CJS_IMPORTS": true +  } +}
\ No newline at end of file diff --git a/examples/with-vitest/README.md b/examples/with-vitest/README.md new file mode 100644 index 000000000..8f1f2e6a0 --- /dev/null +++ b/examples/with-vitest/README.md @@ -0,0 +1,9 @@ +# Astro + [Vitest](https://vitest.dev/) Example + +``` +npm init astro -- --template with-vitest +``` + +[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-vitest) + +This example showcases Astro working with [Vitest](https://vitest.dev/). diff --git a/examples/with-vitest/astro.config.ts b/examples/with-vitest/astro.config.ts new file mode 100644 index 000000000..ad7965b1a --- /dev/null +++ b/examples/with-vitest/astro.config.ts @@ -0,0 +1,4 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig(); diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json new file mode 100644 index 000000000..c445064c9 --- /dev/null +++ b/examples/with-vitest/package.json @@ -0,0 +1,17 @@ +{ +  "name": "@example/with-vitest", +  "version": "0.0.1", +  "type": "module", +  "private": true, +  "scripts": { +    "dev": "astro dev", +    "start": "astro dev", +    "build": "astro build", +    "preview": "astro preview", +    "test": "vitest" +  }, +  "devDependencies": { +    "astro": "^1.0.0-rc.4", +    "vitest": "^0.20.3" +  } +} diff --git a/examples/with-vitest/public/favicon.ico b/examples/with-vitest/public/favicon.icoBinary files differ new file mode 100644 index 000000000..578ad458b --- /dev/null +++ b/examples/with-vitest/public/favicon.ico diff --git a/examples/with-vitest/sandbox.config.json b/examples/with-vitest/sandbox.config.json new file mode 100644 index 000000000..9178af77d --- /dev/null +++ b/examples/with-vitest/sandbox.config.json @@ -0,0 +1,11 @@ +{ +  "infiniteLoopProtection": true, +  "hardReloadOnChange": false, +  "view": "browser", +  "template": "node", +  "container": { +    "port": 3000, +    "startScript": "start", +    "node": "14" +  } +} diff --git a/examples/with-vitest/src/pages/index.astro b/examples/with-vitest/src/pages/index.astro new file mode 100644 index 000000000..4389d5d25 --- /dev/null +++ b/examples/with-vitest/src/pages/index.astro @@ -0,0 +1,13 @@ +--- +--- + +<html lang="en"> +	<head> +		<meta charset="utf-8" /> +		<meta name="viewport" content="width=device-width" /> +		<title>Astro</title> +	</head> +	<body> +		<h1>Astro</h1> +	</body> +</html> diff --git a/examples/with-vitest/test/basic.test.ts b/examples/with-vitest/test/basic.test.ts new file mode 100644 index 000000000..0f6d96168 --- /dev/null +++ b/examples/with-vitest/test/basic.test.ts @@ -0,0 +1,21 @@ +import { assert, expect, test } from 'vitest' + +// Edit an assertion and save to see HMR in action + +test('Math.sqrt()', () => { +  expect(Math.sqrt(4)).toBe(2) +  expect(Math.sqrt(144)).toBe(12) +  expect(Math.sqrt(2)).toBe(Math.SQRT2) +}) + +test('JSON', () => { +  const input = { +    foo: 'hello', +    bar: 'world', +  } + +  const output = JSON.stringify(input) + +  expect(output).eq('{"foo":"hello","bar":"world"}') +  assert.deepEqual(JSON.parse(output), input, 'matches original') +}) diff --git a/examples/with-vitest/tsconfig.json b/examples/with-vitest/tsconfig.json new file mode 100644 index 000000000..be8e3ea96 --- /dev/null +++ b/examples/with-vitest/tsconfig.json @@ -0,0 +1,18 @@ +{ +  "compilerOptions": { +    // Preact specific settings +    "jsx": "react-jsx", +    "jsxImportSource": "preact", +    // Enable top-level await, and other modern ESM features. +    "target": "ESNext", +    "module": "ESNext", +    // Enable node-style module resolution, for things like npm package imports. +    "moduleResolution": "node", +    // Enable JSON imports. +    "resolveJsonModule": true, +    // Enable stricter transpilation for better output. +    "isolatedModules": true, +    // Add type definitions for our Astro runtime. +    "types": ["astro/client"] +  } +} diff --git a/examples/with-vitest/vitest.config.ts b/examples/with-vitest/vitest.config.ts new file mode 100644 index 000000000..a34f19bb1 --- /dev/null +++ b/examples/with-vitest/vitest.config.ts @@ -0,0 +1,9 @@ +/// <reference types="vitest" /> +import { getViteConfig } from 'astro/config'; + +export default getViteConfig({ +	test: { +		/* for example, use global to avoid globals imports (describe, test, expect): */ +		// globals: true, +	}, +}); diff --git a/packages/astro/config.d.ts b/packages/astro/config.d.ts index b63f18336..b43ea268d 100644 --- a/packages/astro/config.d.ts +++ b/packages/astro/config.d.ts @@ -1,3 +1,4 @@ +type ViteUserConfig = import('vite').UserConfig;  type AstroUserConfig = import('./dist/types/@types/astro').AstroUserConfig;  /** @@ -5,3 +6,8 @@ type AstroUserConfig = import('./dist/types/@types/astro').AstroUserConfig;   * https://astro.build/config   */  export function defineConfig(config: AstroUserConfig): AstroUserConfig; + +/** + * Use Astro to generate a fully resolved Vite config + */ +export function getViteConfig(config: ViteUserConfig): ViteUserConfig; diff --git a/packages/astro/config.mjs b/packages/astro/config.mjs index cf19c5aa4..47193dbff 100644 --- a/packages/astro/config.mjs +++ b/packages/astro/config.mjs @@ -1,3 +1,43 @@  export function defineConfig(config) {  	return config;  } + +export function getViteConfig(inlineConfig) { +	// Return an async Vite config getter which exposes a resolved `mode` and `command` +	return async ({ mode, command }) => { +		// Vite `command` is `serve | build`, but Astro uses `dev | build` +		const cmd = command === 'serve' ? 'dev' : command; + +		// Use dynamic import to avoid pulling in deps unless used +		const [ +			{ mergeConfig }, +			{ nodeLogDestination }, +			{ openConfig }, +			{ createVite }, +			{ runHookConfigSetup, runHookConfigDone }, +		] = await Promise.all([ +			import('vite'), +			import('./dist/core/logger/node.js'), +			import('./dist/core/config.js'), +			import('./dist/core/create-vite.js'), +			import('./dist/integrations/index.js'), +		]); +		const logging = { +			dest: nodeLogDestination, +			level: 'info', +		}; +		const { astroConfig: config } = await openConfig({ +			cmd, +			logging, +		}); +		await runHookConfigSetup({ config, command: cmd }); +		const viteConfig = await createVite( +			{ +				mode, +			}, +			{ astroConfig: config, logging: logging, mode } +		); +		await runHookConfigDone({ config }); +		return mergeConfig(viteConfig, inlineConfig); +	} +} diff --git a/packages/astro/package.json b/packages/astro/package.json index d5ee1cbcf..9a47eebee 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -32,7 +32,6 @@      "./jsx/*": "./dist/jsx/*",      "./jsx-runtime": "./dist/jsx-runtime/index.js",      "./config": "./config.mjs", -    "./internal": "./internal.js",      "./app": "./dist/core/app/index.js",      "./app/node": "./dist/core/app/node.js",      "./client/*": "./dist/runtime/client/*", diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 631c1dc2b..d197fb409 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -24,7 +24,7 @@ export type ViteConfigWithSSR = vite.InlineConfig & { ssr?: vite.SSROptions };  interface CreateViteOptions {  	astroConfig: AstroConfig;  	logging: LogOptions; -	mode: 'dev' | 'build'; +	mode: 'dev' | 'build' | string;  }  const ALWAYS_NOEXTERNAL = new Set([ @@ -74,7 +74,7 @@ export async function createVite(  			astroScriptsPlugin({ config: astroConfig }),  			// 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 }), +			mode !== 'build' && astroViteServerPlugin({ config: astroConfig, logging }),  			envVitePlugin({ config: astroConfig }),  			markdownVitePlugin({ config: astroConfig, logging }),  			htmlVitePlugin(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 121e6c5eb..ff53ebbca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -374,6 +374,14 @@ importers:        vite-plugin-pwa: 0.11.11        workbox-window: 6.5.4 +  examples/with-vitest: +    specifiers: +      astro: ^1.0.0-rc.4 +      vitest: ^0.20.3 +    devDependencies: +      astro: link:../../packages/astro +      vitest: 0.20.3 +    packages/astro:      specifiers:        '@astrojs/compiler': ^0.22.1 @@ -8364,6 +8372,12 @@ packages:        '@types/chai': 4.3.1      dev: true +  /@types/chai-subset/1.3.3: +    resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} +    dependencies: +      '@types/chai': 4.3.1 +    dev: true +    /@types/chai/4.3.1:      resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==}      dev: true @@ -15820,6 +15834,16 @@ packages:        globalyzer: 0.1.0        globrex: 0.1.2 +  /tinypool/0.2.4: +    resolution: {integrity: sha512-Vs3rhkUH6Qq1t5bqtb816oT+HeJTXfwt2cbPH17sWHIYKTotQIFPk3tf2fgqRrVyMDVOc1EnPgzIxfIulXVzwQ==} +    engines: {node: '>=14.0.0'} +    dev: true + +  /tinyspy/1.0.0: +    resolution: {integrity: sha512-FI5B2QdODQYDRjfuLF+OrJ8bjWRMCXokQPcwKm0W3IzcbUmBNv536cQc7eXGoAuXphZwgx1DFbqImwzz08Fnhw==} +    engines: {node: '>=14.0.0'} +    dev: true +    /tmp/0.0.33:      resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}      engines: {node: '>=0.6.0'} @@ -16491,7 +16515,6 @@ packages:        rollup: 2.77.2      optionalDependencies:        fsevents: 2.3.2 -    dev: false    /vite/3.0.4_sass@1.54.3:      resolution: {integrity: sha512-NU304nqnBeOx2MkQnskBQxVsa0pRAH5FphokTGmyy8M3oxbvw7qAXts2GORxs+h/2vKsD+osMhZ7An6yK6F1dA==} @@ -16521,6 +16544,48 @@ packages:        fsevents: 2.3.2      dev: false +  /vitest/0.20.3: +    resolution: {integrity: sha512-cXMjTbZxBBUUuIF3PUzEGPLJWtIMeURBDXVxckSHpk7xss4JxkiiWh5cnIlfGyfJne2Ii3QpbiRuFL5dMJtljw==} +    engines: {node: '>=v14.16.0'} +    hasBin: true +    peerDependencies: +      '@edge-runtime/vm': '*' +      '@vitest/browser': '*' +      '@vitest/ui': '*' +      c8: '*' +      happy-dom: '*' +      jsdom: '*' +    peerDependenciesMeta: +      '@edge-runtime/vm': +        optional: true +      '@vitest/browser': +        optional: true +      '@vitest/ui': +        optional: true +      c8: +        optional: true +      happy-dom: +        optional: true +      jsdom: +        optional: true +    dependencies: +      '@types/chai': 4.3.1 +      '@types/chai-subset': 1.3.3 +      '@types/node': 18.6.4 +      chai: 4.3.6 +      debug: 4.3.4 +      local-pkg: 0.4.2 +      tinypool: 0.2.4 +      tinyspy: 1.0.0 +      vite: 3.0.4 +    transitivePeerDependencies: +      - less +      - sass +      - stylus +      - supports-color +      - terser +    dev: true +    /vm2/3.9.10:      resolution: {integrity: sha512-AuECTSvwu2OHLAZYhG716YzwodKCIJxB6u1zG7PgSQwIgAlEaoXH52bxdcvT8GkGjnYK7r7yWDW0m0sOsPuBjQ==}      engines: {node: '>=6.0'} | 
