Add getViteConfig helper (#4154)

* feat: add astro/compat entrypoint for vitest

* chore: add with-vitest example

* chore: add vitest as optional peer dependency

* chore: update lockfile

* refactor: remove astro/compat, use astro/config

* feat: allow arbitrary modes for `create-vite`

* feat: pass vite mode and command when using `getViteConfig`

* chore: remove vitest from peer deps

* chore: add changeset

* chore: update lockfile

Co-authored-by: Nate Moore <nate@astro.build>
This commit is contained in:
Nate Moore 2022-08-05 14:41:01 -05:00 committed by GitHub
parent 23ec87532b
commit 36223f663e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 248 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Expose `getViteConfig` from `astro/config` to unblock usage with Vitest

19
examples/with-vitest/.gitignore vendored Normal file
View file

@ -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

View file

@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true

View file

@ -0,0 +1,6 @@
{
"startCommand": "npm start",
"env": {
"ENABLE_CJS_IMPORTS": true
}
}

View file

@ -0,0 +1,9 @@
# Astro + [Vitest](https://vitest.dev/) Example
```
npm init astro -- --template with-vitest
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/with-vitest)
This example showcases Astro working with [Vitest](https://vitest.dev/).

View file

@ -0,0 +1,4 @@
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig();

View file

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,11 @@
{
"infiniteLoopProtection": true,
"hardReloadOnChange": false,
"view": "browser",
"template": "node",
"container": {
"port": 3000,
"startScript": "start",
"node": "14"
}
}

View file

@ -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>

View file

@ -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')
})

View file

@ -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"]
}
}

View file

@ -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,
},
});

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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/*",

View file

@ -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(),

View file

@ -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'}