[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix: apply `development|production` condition on Vite 6 (#7301)

Co-authored-by: Vladimir Sheremet <sleuths.slews0s@icloud.com>

authored by

Hiroshi Ogawa
Vladimir Sheremet
and committed by
GitHub
(Jan 23, 2025, 2:38 PM +0100) ef1464fc 0b404e56

+233 -25
+15
pnpm-lock.yaml
··· 1123 1123 1124 1124 test/config: 1125 1125 devDependencies: 1126 + '@vitest/test-dep-conditions': 1127 + specifier: file:./deps/test-dep-conditions 1128 + version: file:test/config/deps/test-dep-conditions 1126 1129 tinyexec: 1127 1130 specifier: ^0.3.2 1128 1131 version: 0.3.2 ··· 4125 4128 4126 4129 '@vitest/test-dep-cjs@file:test/core/deps/dep-cjs': 4127 4130 resolution: {directory: test/core/deps/dep-cjs, type: directory} 4131 + 4132 + '@vitest/test-dep-conditions-indirect@file:test/config/deps/test-dep-conditions-indirect': 4133 + resolution: {directory: test/config/deps/test-dep-conditions-indirect, type: directory} 4134 + 4135 + '@vitest/test-dep-conditions@file:test/config/deps/test-dep-conditions': 4136 + resolution: {directory: test/config/deps/test-dep-conditions, type: directory} 4128 4137 4129 4138 '@vitest/test-dep1@file:test/core/deps/dep1': 4130 4139 resolution: {directory: test/core/deps/dep1, type: directory} ··· 12718 12727 vitest: link:packages/vitest 12719 12728 12720 12729 '@vitest/test-dep-cjs@file:test/core/deps/dep-cjs': {} 12730 + 12731 + '@vitest/test-dep-conditions-indirect@file:test/config/deps/test-dep-conditions-indirect': {} 12732 + 12733 + '@vitest/test-dep-conditions@file:test/config/deps/test-dep-conditions': 12734 + dependencies: 12735 + '@vitest/test-dep-conditions-indirect': file:test/config/deps/test-dep-conditions-indirect 12721 12736 12722 12737 '@vitest/test-dep1@file:test/core/deps/dep1': {} 12723 12738
+4
docs/guide/migration.md
··· 129 129 130 130 See PR for more details: [#5876](https://github.com/vitest-dev/vitest/pull/5876). 131 131 132 + ### `module` condition export is not resolved by default on Vite 6 133 + 134 + Vite 6 allows more flexible [`resolve.conditions`](https://vite.dev/config/shared-options#resolve-conditions) options and Vitest configures it to exclude `module` conditional export by default. 135 + 132 136 ### `Custom` Type is Deprecated <Badge type="danger">API</Badge> {#custom-type-is-deprecated} 133 137 134 138 The `Custom` type is now an alias for the `Test` type. Note that Vitest updated the public types in 2.1 and changed exported names to `RunnerCustomCase` and `RunnerTestCase`:
+1
test/config/package.json
··· 6 6 "test": "vitest --typecheck.enabled" 7 7 }, 8 8 "devDependencies": { 9 + "@vitest/test-dep-conditions": "file:./deps/test-dep-conditions", 9 10 "tinyexec": "^0.3.2", 10 11 "vite": "latest", 11 12 "vitest": "workspace:*"
+39
test/config/test/conditions-cli.test.ts
··· 53 53 resolve: { 54 54 conditions: ['custom'], 55 55 }, 56 + ssr: { 57 + resolve: { 58 + conditions: ['custom'], 59 + }, 60 + }, 56 61 define: { 57 62 TEST_CONDITION: '"custom"', 63 + }, 64 + }) 65 + 66 + expect(stderr).toBe('') 67 + }) 68 + 69 + test('conditions (external)', async () => { 70 + const { stderr } = await runVitest({ 71 + root: 'fixtures/conditions', 72 + }) 73 + 74 + expect(stderr).toBe('') 75 + }) 76 + 77 + test('conditions (inline direct)', async () => { 78 + const { stderr } = await runVitest({ 79 + root: 'fixtures/conditions', 80 + server: { 81 + deps: { 82 + inline: ['@vitest/test-dep-conditions'], 83 + }, 84 + }, 85 + }) 86 + 87 + expect(stderr).toBe('') 88 + }) 89 + 90 + test('conditions (inline indirect)', async () => { 91 + const { stderr } = await runVitest({ 92 + root: 'fixtures/conditions', 93 + server: { 94 + deps: { 95 + inline: ['@vitest/test-dep-conditions', '@vitest/test-dep-conditions-indirect'], 96 + }, 58 97 }, 59 98 }) 60 99
+15 -5
packages/vitest/src/node/pool.ts
··· 5 5 import type { BuiltinPool, Pool } from './types/pool-options' 6 6 import { isatty } from 'node:tty' 7 7 import mm from 'micromatch' 8 + import { version as viteVersion } from 'vite' 8 9 import { isWindows } from '../utils/env' 9 10 import { createForksPool } from './pools/forks' 10 11 import { createThreadsPool } from './pools/threads' ··· 91 92 92 93 // in addition to resolve.conditions Vite also adds production/development, 93 94 // see: https://github.com/vitejs/vite/blob/af2aa09575229462635b7cbb6d248ca853057ba2/packages/vite/src/node/plugins/resolve.ts#L1056-L1080 94 - const potentialConditions = new Set([ 95 - 'production', 96 - 'development', 97 - ...ctx.vite.config.resolve.conditions, 98 - ]) 95 + const viteMajor = Number(viteVersion.split('.')[0]) 96 + const potentialConditions = new Set(viteMajor >= 6 97 + ? (ctx.vite.config.ssr.resolve?.conditions ?? []) 98 + : [ 99 + 'production', 100 + 'development', 101 + ...ctx.vite.config.resolve.conditions, 102 + ]) 99 103 const conditions = [...potentialConditions] 100 104 .filter((condition) => { 101 105 if (condition === 'production') { ··· 105 109 return !ctx.vite.config.isProduction 106 110 } 107 111 return true 112 + }) 113 + .map((condition) => { 114 + if (viteMajor >= 6 && condition === 'development|production') { 115 + return ctx.vite.config.isProduction ? 'production' : 'development' 116 + } 117 + return condition 108 118 }) 109 119 .flatMap(c => ['--conditions', c]) 110 120
+1
test/config/deps/test-dep-conditions-indirect/false.js
··· 1 + export default false
+27
test/config/deps/test-dep-conditions-indirect/package.json
··· 1 + { 2 + "name": "@vitest/test-dep-conditions-indirect", 3 + "type": "module", 4 + "private": true, 5 + "exports": { 6 + "./custom": { 7 + "custom": "./true.js", 8 + "default": "./false.js" 9 + }, 10 + "./module": { 11 + "module": "./true.js", 12 + "default": "./false.js" 13 + }, 14 + "./node": { 15 + "node": "./true.js", 16 + "default": "./false.js" 17 + }, 18 + "./development": { 19 + "development": "./true.js", 20 + "default": "./false.js" 21 + }, 22 + "./production": { 23 + "production": "./true.js", 24 + "default": "./false.js" 25 + } 26 + } 27 + }
+1
test/config/deps/test-dep-conditions-indirect/true.js
··· 1 + export default true
+1
test/config/deps/test-dep-conditions/false.js
··· 1 + export default false
+13
test/config/deps/test-dep-conditions/indirect.js
··· 1 + import conditionCustom from '@vitest/test-dep-conditions-indirect/custom' 2 + import conditionDevelopment from '@vitest/test-dep-conditions-indirect/development' 3 + import conditionModule from '@vitest/test-dep-conditions-indirect/module' 4 + import conditionNode from '@vitest/test-dep-conditions-indirect/node' 5 + import conditionProductioin from '@vitest/test-dep-conditions-indirect/production' 6 + 7 + export default { 8 + conditionCustom, 9 + conditionModule, 10 + conditionNode, 11 + conditionDevelopment, 12 + conditionProductioin, 13 + }
+1
test/config/deps/test-dep-conditions/inline.js
··· 1 + export default !!import.meta.__IS_INLINE__
+32
test/config/deps/test-dep-conditions/package.json
··· 1 + { 2 + "name": "@vitest/test-dep-conditions", 3 + "type": "module", 4 + "private": true, 5 + "exports": { 6 + "./custom": { 7 + "custom": "./true.js", 8 + "default": "./false.js" 9 + }, 10 + "./module": { 11 + "module": "./true.js", 12 + "default": "./false.js" 13 + }, 14 + "./node": { 15 + "node": "./true.js", 16 + "default": "./false.js" 17 + }, 18 + "./development": { 19 + "development": "./true.js", 20 + "default": "./false.js" 21 + }, 22 + "./production": { 23 + "production": "./true.js", 24 + "default": "./false.js" 25 + }, 26 + "./inline": "./inline.js", 27 + "./indirect": "./indirect.js" 28 + }, 29 + "dependencies": { 30 + "@vitest/test-dep-conditions-indirect": "file:../test-dep-conditions-indirect" 31 + } 32 + }
+1
test/config/deps/test-dep-conditions/true.js
··· 1 + export default true
+37
test/config/fixtures/conditions/basic.test.js
··· 1 + import { test, expect } from 'vitest'; 2 + import conditionCustom from '@vitest/test-dep-conditions/custom'; 3 + import conditionModule from '@vitest/test-dep-conditions/module'; 4 + import conditionNode from '@vitest/test-dep-conditions/node'; 5 + import conditionDevelopment from '@vitest/test-dep-conditions/development'; 6 + import conditionProduction from '@vitest/test-dep-conditions/production'; 7 + import inline from '@vitest/test-dep-conditions/inline'; 8 + import indirect from '@vitest/test-dep-conditions/indirect'; 9 + 10 + import { viteVersion } from 'vitest/node' 11 + const viteMajor = Number(viteVersion.split('.')[0]) 12 + 13 + test('conditions', () => { 14 + expect({ 15 + conditionCustom, 16 + conditionModule, 17 + conditionNode, 18 + conditionDevelopment, 19 + conditionProduction, 20 + indirect 21 + }).toEqual( 22 + { 23 + conditionCustom: true, 24 + "conditionDevelopment": true, 25 + "conditionModule": viteMajor <= 5, 26 + "conditionNode": true, 27 + "conditionProduction": false, 28 + "indirect": { 29 + conditionCustom: true, 30 + "conditionDevelopment": true, 31 + "conditionModule": viteMajor <= 5 && inline, 32 + "conditionNode": true, 33 + "conditionProductioin": false, 34 + }, 35 + } 36 + ) 37 + })
+15
test/config/fixtures/conditions/vite.config.ts
··· 1 + import { defineConfig } from "vitest/config" 2 + 3 + export default defineConfig({ 4 + define: { 5 + 'import.meta.__IS_INLINE__': 'true', 6 + }, 7 + resolve: { 8 + conditions: ['custom'], 9 + }, 10 + ssr: { 11 + resolve: { 12 + conditions: ['custom'], 13 + }, 14 + } 15 + })
+5 -10
packages/vitest/src/node/plugins/index.ts
··· 20 20 import { SsrReplacerPlugin } from './ssrReplacer' 21 21 import { 22 22 deleteDefineConfig, 23 + getDefaultResolveOptions, 23 24 hijackVitePluginInject, 24 25 resolveFsAllow, 25 26 } from './utils' ··· 73 74 open = testConfig.uiBase ?? '/__vitest__/' 74 75 } 75 76 77 + const resolveOptions = getDefaultResolveOptions() 78 + 76 79 const config: ViteConfig = { 77 80 root: viteConfig.test?.root || options.root, 78 81 esbuild: ··· 86 89 legalComments: 'inline', 87 90 }, 88 91 resolve: { 89 - // by default Vite resolves `module` field, which not always a native ESM module 90 - // setting this option can bypass that and fallback to cjs version 91 - mainFields: [], 92 + ...resolveOptions, 92 93 alias: testConfig.alias, 93 - conditions: ['node'], 94 94 }, 95 95 server: { 96 96 ...testConfig.api, ··· 115 115 // @ts-ignore Vite 6 compat 116 116 environments: { 117 117 ssr: { 118 - resolve: { 119 - // by default Vite resolves `module` field, which not always a native ESM module 120 - // setting this option can bypass that and fallback to cjs version 121 - mainFields: [], 122 - conditions: ['node'], 123 - }, 118 + resolve: resolveOptions, 124 119 }, 125 120 }, 126 121 test: {
+21
packages/vitest/src/node/plugins/utils.ts
··· 6 6 import type { DepsOptimizationOptions, InlineConfig } from '../types/config' 7 7 import { dirname } from 'pathe' 8 8 import { searchForWorkspaceRoot, version as viteVersion } from 'vite' 9 + import * as vite from 'vite' 9 10 import { rootDir } from '../../paths' 10 11 import { VitestCache } from '../cache' 11 12 ··· 146 147 searchForWorkspaceRoot(projectRoot), 147 148 rootDir, 148 149 ] 150 + } 151 + 152 + export function getDefaultResolveOptions(): vite.ResolveOptions { 153 + return { 154 + // by default Vite resolves `module` field, which is not always a native ESM module 155 + // setting this option can bypass that and fallback to cjs version 156 + mainFields: [], 157 + // same for `module` condition and Vite 5 doesn't even allow excluding it, 158 + // but now it's possible since Vite 6. 159 + conditions: getDefaultServerConditions(), 160 + } 161 + } 162 + 163 + function getDefaultServerConditions(): string[] { 164 + const viteMajor = Number(viteVersion.split('.')[0]) 165 + if (viteMajor >= 6) { 166 + const conditions: string[] = (vite as any).defaultServerConditions 167 + return conditions.filter(c => c !== 'module') 168 + } 169 + return ['node'] 149 170 }
+4 -10
packages/vitest/src/node/plugins/workspace.ts
··· 16 16 import { SsrReplacerPlugin } from './ssrReplacer' 17 17 import { 18 18 deleteDefineConfig, 19 + getDefaultResolveOptions, 19 20 hijackVitePluginInject, 20 21 resolveFsAllow, 21 22 } from './utils' ··· 92 93 } 93 94 } 94 95 96 + const resolveOptions = getDefaultResolveOptions() 95 97 const config: ViteConfig = { 96 98 root, 97 99 resolve: { 98 - // by default Vite resolves `module` field, which not always a native ESM module 99 - // setting this option can bypass that and fallback to cjs version 100 - mainFields: [], 100 + ...resolveOptions, 101 101 alias: testConfig.alias, 102 - conditions: ['node'], 103 102 }, 104 103 esbuild: viteConfig.esbuild === false 105 104 ? false ··· 130 129 // @ts-ignore Vite 6 compat 131 130 environments: { 132 131 ssr: { 133 - resolve: { 134 - // by default Vite resolves `module` field, which not always a native ESM module 135 - // setting this option can bypass that and fallback to cjs version 136 - mainFields: [], 137 - conditions: ['node'], 138 - }, 132 + resolve: resolveOptions, 139 133 }, 140 134 }, 141 135 test: {