From 36223f663ef73ef4581c4ad93c88666d2e0190e7 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Fri, 5 Aug 2022 14:41:01 -0500 Subject: [PATCH] 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 --- .changeset/healthy-meals-wink.md | 5 ++ examples/with-vitest/.gitignore | 19 ++++++ examples/with-vitest/.npmrc | 2 + examples/with-vitest/.stackblitzrc | 6 ++ examples/with-vitest/README.md | 9 +++ examples/with-vitest/astro.config.ts | 4 ++ examples/with-vitest/package.json | 17 ++++++ examples/with-vitest/public/favicon.ico | Bin 0 -> 4286 bytes examples/with-vitest/sandbox.config.json | 11 ++++ examples/with-vitest/src/pages/index.astro | 13 ++++ examples/with-vitest/test/basic.test.ts | 21 +++++++ examples/with-vitest/tsconfig.json | 18 ++++++ examples/with-vitest/vitest.config.ts | 9 +++ packages/astro/config.d.ts | 6 ++ packages/astro/config.mjs | 40 ++++++++++++ packages/astro/package.json | 1 - packages/astro/src/core/create-vite.ts | 4 +- pnpm-lock.yaml | 67 ++++++++++++++++++++- 18 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 .changeset/healthy-meals-wink.md create mode 100644 examples/with-vitest/.gitignore create mode 100644 examples/with-vitest/.npmrc create mode 100644 examples/with-vitest/.stackblitzrc create mode 100644 examples/with-vitest/README.md create mode 100644 examples/with-vitest/astro.config.ts create mode 100644 examples/with-vitest/package.json create mode 100644 examples/with-vitest/public/favicon.ico create mode 100644 examples/with-vitest/sandbox.config.json create mode 100644 examples/with-vitest/src/pages/index.astro create mode 100644 examples/with-vitest/test/basic.test.ts create mode 100644 examples/with-vitest/tsconfig.json create mode 100644 examples/with-vitest/vitest.config.ts 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 +``` + +[![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/). 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.ico new file mode 100644 index 0000000000000000000000000000000000000000..578ad458b8906c08fbed84f42b045fea04db89d1 GIT binary patch literal 4286 zcmchZF=!M)6ox0}Fc8GdTHG!cdIY>nA!3n2f|wxIl0rn}Hl#=uf>?-!2r&jMEF^_k zh**lGut*gwBmoNv7AaB&2~nbzULg{WBhPQ{ZVzvF_HL8Cb&hv$_s#qN|IO^o>?+mA zuTW6tU%k~z<&{z+7$G%*nRsTcEO|90xy<-G5&JTt%CgZZCDT4%R?+{Vd^wh>P8_)} z`+dF$HQb9!>1o`Ivn;GInlCw{9T@Rt%q+d^T3Ke%cxkk;$v`{s^zCB9nHAv6w$Vbn z8fb<+eQTNM`;rf9#obfGnV#3+OQEUv4gU;{oA@zol%keY9-e>4W>p7AHmH~&!P7f7!Uj` zwgFeQ=<3G4O;mwWO`L!=R-=y3_~-DPjH3W^3f&jjCfC$o#|oGaahSL`_=f?$&Aa+W z2h8oZ+@?NUcjGW|aWJfbM*ZzxzmCPY`b~RobNrrj=rd`=)8-j`iSW64@0_b6?;GYk zNB+-fzOxlqZ?`y{OA$WigtZXa8)#p#=DPYxH=VeC_Q5q9Cv`mvW6*zU&Gnp1;oPM6 zaK_B3j(l^FyJgYeE9RrmDyhE7W2}}nW%ic#0v@i1E!yTey$W)U>fyd+!@2hWQ!Wa==NAtKoj`f3tp4y$Al`e;?)76?AjdaRR>|?&r)~3Git> zb1)a?uiv|R0_{m#A9c;7)eZ1y6l@yQ#oE*>(Z2fG-&&smPa2QTW>m*^K65^~`coP$ z8y5Y?iS<4Gz{Zg##$1mk)u-0;X|!xu^FCr;ce~X<&UWE&pBgqfYmEJTzpK9I%vr%b z3Ksd6qlPJLI%HFfeXK_^|BXiKZC>Ocu(Kk6hD3G-8usLzVG^q00Qh gz)s7ge@$ApxGu7=(6IGIk+uG&HTev01^#CH3$(Wk5&!@I literal 0 HcmV?d00001 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 @@ +--- +--- + + + + + + Astro + + +

Astro

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