Skip to content

Commit acbf507

Browse files
authored
feat: integrate devtools (#21331)
1 parent b3f4c43 commit acbf507

File tree

12 files changed

+1820
-1011
lines changed

12 files changed

+1820
-1011
lines changed

docs/config/shared-options.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,17 @@ Whether your application is a Single Page Application (SPA), a [Multi Page Appli
549549

550550
Learn more in Vite's [SSR guide](/guide/ssr#vite-cli). Related: [`server.middlewareMode`](./server-options#server-middlewaremode).
551551

552+
## devtools
553+
554+
- **Experimental:** [Give Feedback](https://github.com/vitejs/devtools/discussions)
555+
- **Type:** `boolean` | `DevToolsConfig`
556+
- **Default:** `false`
557+
558+
Enable devtools integration for visualizing the internal state and build analysis.
559+
Ensure that `@vitejs/devtools` is installed as a dependency. This feature is currently supported only in build mode.
560+
561+
See [Vite DevTools](https://github.com/vitejs/devtools) for more details.
562+
552563
## future
553564

554565
- **Type:** `Record<string, 'warn' | undefined>`

packages/vite/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
"@rollup/pluginutils": "^5.3.0",
9898
"@types/escape-html": "^1.0.4",
9999
"@types/pnpapi": "^0.0.5",
100+
"@vitejs/devtools": "^0.0.0-alpha.24",
100101
"artichokie": "^0.4.2",
101102
"baseline-browser-mapping": "^2.9.19",
102103
"cac": "^6.7.14",
@@ -144,6 +145,7 @@
144145
},
145146
"peerDependencies": {
146147
"@types/node": "^20.19.0 || >=22.12.0",
148+
"@vitejs/devtools": "^0.0.0-alpha.24",
147149
"esbuild": "^0.27.0",
148150
"jiti": ">=1.21.0",
149151
"less": "^4.0.0",
@@ -159,6 +161,9 @@
159161
"@types/node": {
160162
"optional": true
161163
},
164+
"@vitejs/devtools": {
165+
"optional": true
166+
},
162167
"esbuild": {
163168
"optional": true
164169
},

packages/vite/rolldown.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ const nodeConfig = defineConfig({
8686
'supports-color',
8787
'utf-8-validate', // ws
8888
'bufferutil', // ws
89+
'@vitejs/devtools/cli-commands',
8990
...Object.keys(pkg.dependencies),
9091
...Object.keys(pkg.peerDependencies),
9192
],
@@ -143,6 +144,7 @@ const moduleRunnerConfig = defineConfig({
143144
'fsevents',
144145
'lightningcss',
145146
/^rolldown\//,
147+
'@vitejs/devtools/cli-commands',
146148
...Object.keys(pkg.dependencies),
147149
],
148150
plugins: [bundleSizeLimit(54), enableSourceMapsInWatchModePlugin()],

packages/vite/src/node/build.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,7 @@ export interface ViteBuilder {
17231723
build(
17241724
environment: BuildEnvironment,
17251725
): Promise<RolldownOutput | RolldownOutput[] | RolldownWatcher>
1726+
runDevTools(): Promise<void>
17261727
}
17271728

17281729
export interface BuilderOptions {
@@ -1834,6 +1835,20 @@ export async function createBuilder(
18341835
environment.isBuilt = true
18351836
return output
18361837
},
1838+
async runDevTools() {
1839+
const devtoolsConfig = config.devtools
1840+
if (devtoolsConfig.enabled) {
1841+
try {
1842+
const { start } = await import(`@vitejs/devtools/cli-commands`)
1843+
await start(devtoolsConfig.config)
1844+
} catch (e) {
1845+
config.logger.error(
1846+
colors.red(`Failed to run Vite DevTools: ${e.message || e.stack}`),
1847+
{ error: e },
1848+
)
1849+
}
1850+
}
1851+
},
18371852
}
18381853

18391854
async function setupEnvironment(name: string, config: ResolvedConfig) {

packages/vite/src/node/cli.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ cli
365365
}
366366
const builder = await createBuilder(inlineConfig, null)
367367
await builder.buildApp()
368+
await builder.runDevTools()
368369
} catch (e) {
369370
createLogger(options.logLevel).error(
370371
colors.red(`error during build:\n${e.stack}`),

packages/vite/src/node/config.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
type RolldownOptions,
1616
rolldown,
1717
} from 'rolldown'
18+
import type { StartOptions } from '@vitejs/devtools/cli-commands'
1819
import type { Alias, AliasOptions } from '#dep-types/alias'
1920
import type { AnymatchFn } from '../types/anymatch'
2021
import { withTrailingSlash } from '../shared/utils'
@@ -90,6 +91,7 @@ import {
9091
nodeLikeBuiltins,
9192
normalizeAlias,
9293
normalizePath,
94+
resolveHostname,
9395
setupRollupOptionCompat,
9496
} from './utils'
9597
import {
@@ -507,6 +509,13 @@ export interface UserConfig extends DefaultEnvironmentOptions {
507509
* @default 'spa'
508510
*/
509511
appType?: AppType
512+
/**
513+
* Enable devtools integration. Ensure that `@vitejs/devtools` is installed as a dependency.
514+
* This feature is currently supported only in build mode.
515+
* @experimental
516+
* @default false
517+
*/
518+
devtools?: boolean | DevToolsConfig
510519
}
511520

512521
export interface HTMLOptions {
@@ -611,6 +620,15 @@ export interface ResolvedWorkerOptions {
611620
rolldownOptions: RolldownOptions
612621
}
613622

623+
export interface DevToolsConfig extends Partial<StartOptions> {
624+
enabled: boolean
625+
}
626+
627+
export interface ResolvedDevToolsConfig {
628+
config: Omit<DevToolsConfig, 'enabled'> & { host: string }
629+
enabled: boolean
630+
}
631+
614632
export interface InlineConfig extends UserConfig {
615633
configFile?: string | false
616634
/** @experimental */
@@ -636,6 +654,7 @@ export interface ResolvedConfig extends Readonly<
636654
| 'future'
637655
| 'server'
638656
| 'preview'
657+
| 'devtools'
639658
> & {
640659
configFile: string | undefined
641660
configFileDependencies: string[]
@@ -675,6 +694,7 @@ export interface ResolvedConfig extends Readonly<
675694
/** @experimental */
676695
builder: ResolvedBuilderOptions | undefined
677696
build: ResolvedBuildOptions
697+
devtools: ResolvedDevToolsConfig
678698
preview: ResolvedPreviewOptions
679699
ssr: ResolvedSSROptions
680700
assetsInclude: (file: string) => boolean
@@ -725,6 +745,24 @@ export interface ResolvedConfig extends Readonly<
725745
} & PluginHookUtils
726746
> {}
727747

748+
export async function resolveDevToolsConfig(
749+
config: DevToolsConfig | boolean | undefined,
750+
host: string | boolean | undefined,
751+
): Promise<ResolvedDevToolsConfig> {
752+
const resolvedHostname = await resolveHostname(host)
753+
const fallbackHostname = resolvedHostname.host ?? 'localhost'
754+
755+
return {
756+
enabled: config === true || !!(config && config.enabled),
757+
config: {
758+
...(isObject(config) ? config : {}),
759+
host: isObject(config)
760+
? (config?.host ?? fallbackHostname)
761+
: fallbackHostname,
762+
},
763+
}
764+
}
765+
728766
// inferred ones are omitted
729767
const configDefaults = Object.freeze({
730768
define: {},
@@ -1813,6 +1851,11 @@ export async function resolveConfig(
18131851
experimental.renderBuiltUrl = undefined
18141852
}
18151853

1854+
const resolvedDevToolsConfig = await resolveDevToolsConfig(
1855+
config.devtools,
1856+
server.host,
1857+
)
1858+
18161859
resolved = {
18171860
configFile: configFile ? normalizePath(configFile) : undefined,
18181861
configFileDependencies: configFileDependencies.map((name) =>
@@ -1900,6 +1943,7 @@ export async function resolveConfig(
19001943
resolve: resolvedDefaultResolve,
19011944
dev: resolvedDevEnvironmentOptions,
19021945
build: resolvedBuildOptions,
1946+
devtools: resolvedDevToolsConfig,
19031947

19041948
environments: resolvedEnvironments,
19051949

@@ -2004,6 +2048,11 @@ export async function resolveConfig(
20042048
resolved.build.ssrEmitAssets || resolved.build.emitAssets
20052049
}
20062050

2051+
// Enable `rolldownOptions.devtools` if devtools is enabled
2052+
if (resolved.devtools.enabled) {
2053+
resolved.build.rolldownOptions.devtools ??= {}
2054+
}
2055+
20072056
applyDepOptimizationOptionCompat(resolved)
20082057
await setOptimizeDepsPluginNames(resolved)
20092058

playground/devtools/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>DevTools</title>
6+
</head>
7+
8+
<body>
9+
<div id="app"></div>
10+
<script type="module" src="/src/main.ts"></script>
11+
</body>
12+
</html>

playground/devtools/package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "@vitejs/test-devtools",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"debug": "node --inspect-brk ../../packages/vite/bin/vite",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"vue": "^3.5.25"
14+
},
15+
"devDependencies": {
16+
"vite": "workspace:*",
17+
"@vitejs/devtools": "^0.0.0-alpha.24"
18+
}
19+
}

playground/devtools/src/counter.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { ref } from 'vue'
2+
3+
export function useCounter() {
4+
const count = ref(0)
5+
6+
function increment() {
7+
count.value++
8+
}
9+
10+
function decrement() {
11+
count.value--
12+
}
13+
14+
return {
15+
count,
16+
increment,
17+
decrement,
18+
}
19+
}

playground/devtools/src/main.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { watchEffect } from 'vue'
2+
import { useCounter } from './counter'
3+
4+
const { count, increment, decrement } = useCounter()
5+
6+
watchEffect(() => {
7+
document.querySelector('#app')!.textContent = `${count.value}`
8+
})
9+
10+
const timer = setInterval(() => {
11+
if (count.value < 6) {
12+
increment()
13+
} else {
14+
decrement()
15+
clearInterval(timer)
16+
}
17+
}, 1000)

0 commit comments

Comments
 (0)