Skip to content

Commit 87be127

Browse files
authored
feat: add multi-env support for build (#148)
1 parent 0bd37de commit 87be127

File tree

2 files changed

+105
-56
lines changed

2 files changed

+105
-56
lines changed

src/node/build.ts

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Environment } from 'vite'
12
import type { ModuleTransformInfo } from '../types'
23
import type { InspectContext } from './context'
34
import fs from 'node:fs/promises'
@@ -6,9 +7,36 @@ import process from 'node:process'
67
import { hash } from 'ohash'
78
import { DIR_CLIENT } from '../dirs'
89

9-
export async function generateBuild(
10-
ctx: InspectContext,
10+
export interface EnvOrderHooks<Args extends readonly unknown[]> {
11+
onFirst?: (...args: Args) => Promise<void>
12+
onEach?: (...args: Args) => Promise<void>
13+
onLast?: (...args: Args) => Promise<void>
14+
}
15+
export function createEnvOrderHooks<Args extends readonly unknown[]>(
16+
environmentNames: string[],
17+
{ onFirst, onEach, onLast }: EnvOrderHooks<Args>,
1118
) {
19+
const remainingEnvs = new Set<string>(environmentNames)
20+
let ranFirst = false
21+
let ranLast = false
22+
23+
return async (envName: string, ...args: Args) => {
24+
if (!ranFirst) {
25+
ranFirst = true
26+
await onFirst?.(...args)
27+
}
28+
29+
remainingEnvs.delete(envName)
30+
await onEach?.(...args)
31+
32+
if (!ranLast && remainingEnvs.size === 0) {
33+
ranLast = true
34+
await onLast?.(...args)
35+
}
36+
}
37+
}
38+
39+
export function createBuildGenerator(ctx: InspectContext) {
1240
const {
1341
outputDir = '.vite-inspect',
1442
} = ctx.options
@@ -19,55 +47,62 @@ export async function generateBuild(
1947
: resolve(process.cwd(), outputDir)
2048
const reportsDir = join(targetDir, 'reports')
2149

22-
await fs.rm(targetDir, { recursive: true, force: true })
23-
await fs.mkdir(reportsDir, { recursive: true })
24-
await fs.cp(DIR_CLIENT, targetDir, { recursive: true })
25-
26-
await Promise.all([
27-
fs.writeFile(
28-
join(targetDir, 'index.html'),
29-
(await fs.readFile(join(targetDir, 'index.html'), 'utf-8'))
30-
.replace(
31-
'data-vite-inspect-mode="DEV"',
32-
'data-vite-inspect-mode="BUILD"',
50+
return {
51+
getOutputDir() {
52+
return targetDir
53+
},
54+
async setupOutputDir() {
55+
await fs.rm(targetDir, { recursive: true, force: true })
56+
await fs.mkdir(reportsDir, { recursive: true })
57+
await fs.cp(DIR_CLIENT, targetDir, { recursive: true })
58+
await Promise.all([
59+
fs.writeFile(
60+
join(targetDir, 'index.html'),
61+
(await fs.readFile(join(targetDir, 'index.html'), 'utf-8'))
62+
.replace(
63+
'data-vite-inspect-mode="DEV"',
64+
'data-vite-inspect-mode="BUILD"',
65+
),
66+
),
67+
writeJSON(
68+
join(reportsDir, 'metadata.json'),
69+
ctx.getMetadata(),
3370
),
34-
),
35-
writeJSON(
36-
join(reportsDir, 'metadata.json'),
37-
ctx.getMetadata(),
38-
),
39-
...[...ctx._idToInstances.values()]
40-
.flatMap(v => [...v.environments.values()]
41-
.map((e) => {
42-
const key = `${v.id}-${e.env.name}`
71+
])
72+
},
73+
async generateForEnv(env: Environment) {
74+
await Promise.all([...ctx._idToInstances.values()]
75+
.filter(v => v.environments.has(env.name))
76+
.map((v) => {
77+
const e = v.environments.get(env.name)!
78+
const key = `${v.id}-${env.name}`
4379
return [key, e] as const
80+
})
81+
.map(async ([key, env]) => {
82+
await fs.mkdir(join(reportsDir, key, 'transforms'), { recursive: true })
83+
84+
return await Promise.all([
85+
writeJSON(
86+
join(reportsDir, key, 'modules.json'),
87+
env.getModulesList(),
88+
),
89+
writeJSON(
90+
join(reportsDir, key, 'metric-plugins.json'),
91+
env.getPluginMetrics(),
92+
),
93+
...Object.entries(env.data.transform)
94+
.map(([id, info]) => writeJSON(
95+
join(reportsDir, key, 'transforms', `${hash(id)}.json`),
96+
<ModuleTransformInfo>{
97+
resolvedId: id,
98+
transforms: info,
99+
},
100+
)),
101+
])
44102
}),
45103
)
46-
.map(async ([key, env]) => {
47-
await fs.mkdir(join(reportsDir, key, 'transforms'), { recursive: true })
48-
49-
return await Promise.all([
50-
writeJSON(
51-
join(reportsDir, key, 'modules.json'),
52-
env.getModulesList(),
53-
),
54-
writeJSON(
55-
join(reportsDir, key, 'metric-plugins.json'),
56-
env.getPluginMetrics(),
57-
),
58-
...Object.entries(env.data.transform)
59-
.map(([id, info]) => writeJSON(
60-
join(reportsDir, key, 'transforms', `${hash(id)}.json`),
61-
<ModuleTransformInfo>{
62-
resolvedId: id,
63-
transforms: info,
64-
},
65-
)),
66-
])
67-
}),
68-
])
69-
70-
return targetDir
104+
},
105+
}
71106
}
72107

73108
function writeJSON(filename: string, data: any) {

src/node/index.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Connect, Plugin, ViteDevServer } from 'vite'
1+
import type { Connect, Plugin, Rollup, ViteDevServer } from 'vite'
22
import type { HMRData, RpcFunctions } from '../types'
33
import type { InspectContextVite } from './context'
44
import type { ViteInspectOptions } from './options'
@@ -8,7 +8,7 @@ import { debounce } from 'perfect-debounce'
88
import sirv from 'sirv'
99
import { createRPCServer } from 'vite-dev-rpc'
1010
import { DIR_CLIENT } from '../dirs'
11-
import { generateBuild } from './build'
11+
import { createBuildGenerator, createEnvOrderHooks } from './build'
1212
import { InspectContext } from './context'
1313
import { hijackPlugin } from './hijack'
1414
import { createPreviewServer } from './preview'
@@ -39,6 +39,7 @@ export default function PluginInspect(options: ViteInspectOptions = {}): Plugin
3939
}
4040

4141
const ctx = new InspectContext(options)
42+
let onBuildEnd: (envName: string, pluginCtx: Rollup.PluginContext) => Promise<void> | undefined
4243

4344
const timestampRE = /\bt=\d{13}&?\b/
4445
const trailingSeparatorRE = /[?&]$/
@@ -211,6 +212,24 @@ export default function PluginInspect(options: ViteInspectOptions = {}): Plugin
211212
return result
212213
}
213214
}
215+
216+
if (build) {
217+
const buildGenerator = createBuildGenerator(ctx)
218+
onBuildEnd = createEnvOrderHooks<[pluginCtx: Rollup.PluginContext]>(Object.keys(config.environments), {
219+
async onFirst() {
220+
await buildGenerator.setupOutputDir()
221+
},
222+
async onEach(pluginCtx) {
223+
await buildGenerator.generateForEnv(pluginCtx.environment)
224+
},
225+
async onLast(pluginCtx) {
226+
const dir = buildGenerator.getOutputDir()
227+
pluginCtx.environment.logger.info(`${c.green('Inspect report generated at')} ${c.dim(dir)}`)
228+
if (_open && !isCI)
229+
createPreviewServer(dir)
230+
},
231+
})
232+
}
214233
},
215234
configureServer(server) {
216235
const rpc = configureServer(server)
@@ -242,14 +261,9 @@ export default function PluginInspect(options: ViteInspectOptions = {}): Plugin
242261
})
243262
},
244263
async buildEnd() {
245-
if (!build)
246-
return
247-
const dir = await generateBuild(ctx)
248-
249-
this.environment!.logger.info(`${c.green('Inspect report generated at')} ${c.dim(dir)}`)
250-
if (_open && !isCI)
251-
createPreviewServer(dir)
264+
onBuildEnd?.(this.environment.name, this)
252265
},
266+
sharedDuringBuild: true,
253267
}
254268
return plugin
255269
}

0 commit comments

Comments
 (0)