Skip to content

Commit d30f813

Browse files
null51_hanyue.phegoist
authored
fix: build promise resolves before types are emitted (#597)
Co-authored-by: hanyue.ph <[email protected]> Co-authored-by: EGOIST <[email protected]>
1 parent 93bf6e8 commit d30f813

File tree

2 files changed

+155
-144
lines changed

2 files changed

+155
-144
lines changed

src/index.ts

Lines changed: 154 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -144,165 +144,175 @@ export async function build(_options: Options) {
144144
logger.info('CLI', 'Running in watch mode')
145145
}
146146

147-
if (options.dts) {
148-
const worker = new Worker(path.join(__dirname, './rollup.js'))
149-
worker.postMessage({
150-
configName: item?.name,
151-
options: {
152-
...options, // functions cannot be cloned
153-
banner: undefined,
154-
footer: undefined,
155-
esbuildPlugins: undefined,
156-
esbuildOptions: undefined,
157-
plugins: undefined,
158-
},
159-
})
160-
worker.on('message', (data) => {
161-
if (data === 'error') {
162-
process.exitCode = 1
163-
} else if (data === 'success') {
164-
process.exitCode = 0
165-
}
166-
})
147+
const dtsTask = async () => {
148+
if (options.dts) {
149+
await new Promise<void>((resolve, reject) => {
150+
const worker = new Worker(path.join(__dirname, './rollup.js'))
151+
worker.postMessage({
152+
configName: item?.name,
153+
options: {
154+
...options, // functions cannot be cloned
155+
banner: undefined,
156+
footer: undefined,
157+
esbuildPlugins: undefined,
158+
esbuildOptions: undefined,
159+
plugins: undefined,
160+
},
161+
})
162+
worker.on('message', (data) => {
163+
if (data === 'error') {
164+
process.exitCode = 1
165+
reject()
166+
} else if (data === 'success') {
167+
process.exitCode = 0
168+
resolve()
169+
}
170+
})
171+
})
172+
}
167173
}
168174

169-
if (!options.dts?.only) {
170-
let existingOnSuccess: ChildProcess | undefined
171-
/** Files imported by the entry */
172-
const buildDependencies: Set<string> = new Set()
175+
const otherTasks = async () => {
176+
if (!options.dts?.only) {
177+
let existingOnSuccess: ChildProcess | undefined
178+
/** Files imported by the entry */
179+
const buildDependencies: Set<string> = new Set()
173180

174-
const killPreviousProcess = async () => {
175-
if (existingOnSuccess) {
176-
await killProcess({
177-
pid: existingOnSuccess.pid,
178-
})
179-
existingOnSuccess = undefined
181+
const killPreviousProcess = async () => {
182+
if (existingOnSuccess) {
183+
await killProcess({
184+
pid: existingOnSuccess.pid,
185+
})
186+
existingOnSuccess = undefined
187+
}
180188
}
181-
}
182189

183-
const debouncedBuildAll = debouncePromise(
184-
() => {
185-
return buildAll()
186-
},
187-
100,
188-
handleError
189-
)
190-
191-
const buildAll = async () => {
192-
const killPromise = killPreviousProcess()
193-
// Store previous build dependencies in case the build failed
194-
// So we can restore it
195-
const previousBuildDependencies = new Set(buildDependencies)
196-
buildDependencies.clear()
197-
198-
if (options.clean) {
199-
const extraPatterns = Array.isArray(options.clean)
200-
? options.clean
201-
: []
202-
await removeFiles(
203-
['**/*', '!**/*.d.ts', ...extraPatterns],
204-
options.outDir
205-
)
206-
logger.info('CLI', 'Cleaning output folder')
207-
}
190+
const debouncedBuildAll = debouncePromise(
191+
() => {
192+
return buildAll()
193+
},
194+
100,
195+
handleError
196+
)
208197

209-
const css: Map<string, string> = new Map()
210-
await Promise.all([
211-
...options.format.map(async (format, index) => {
212-
const pluginContainer = new PluginContainer([
213-
shebang(),
214-
...(options.plugins || []),
215-
cjsSplitting(),
216-
es5(),
217-
sizeReporter(),
218-
])
219-
await pluginContainer.buildStarted()
220-
await runEsbuild(options, {
221-
pluginContainer,
222-
format,
223-
css: index === 0 || options.injectStyle ? css : undefined,
224-
logger,
225-
buildDependencies,
226-
}).catch((error) => {
227-
previousBuildDependencies.forEach((v) =>
228-
buildDependencies.add(v)
229-
)
230-
throw error
198+
const buildAll = async () => {
199+
const killPromise = killPreviousProcess()
200+
// Store previous build dependencies in case the build failed
201+
// So we can restore it
202+
const previousBuildDependencies = new Set(buildDependencies)
203+
buildDependencies.clear()
204+
205+
if (options.clean) {
206+
const extraPatterns = Array.isArray(options.clean)
207+
? options.clean
208+
: []
209+
await removeFiles(
210+
['**/*', '!**/*.d.ts', ...extraPatterns],
211+
options.outDir
212+
)
213+
logger.info('CLI', 'Cleaning output folder')
214+
}
215+
216+
const css: Map<string, string> = new Map()
217+
await Promise.all([
218+
...options.format.map(async (format, index) => {
219+
const pluginContainer = new PluginContainer([
220+
shebang(),
221+
...(options.plugins || []),
222+
cjsSplitting(),
223+
es5(),
224+
sizeReporter(),
225+
])
226+
await pluginContainer.buildStarted()
227+
await runEsbuild(options, {
228+
pluginContainer,
229+
format,
230+
css: index === 0 || options.injectStyle ? css : undefined,
231+
logger,
232+
buildDependencies,
233+
}).catch((error) => {
234+
previousBuildDependencies.forEach((v) =>
235+
buildDependencies.add(v)
236+
)
237+
throw error
238+
})
239+
}),
240+
])
241+
await killPromise
242+
if (options.onSuccess) {
243+
const parts = parseArgsStringToArgv(options.onSuccess)
244+
const exec = parts[0]
245+
const args = parts.splice(1)
246+
existingOnSuccess = execa(exec, args, {
247+
stdio: 'inherit',
231248
})
232-
}),
233-
])
234-
await killPromise
235-
if (options.onSuccess) {
236-
const parts = parseArgsStringToArgv(options.onSuccess)
237-
const exec = parts[0]
238-
const args = parts.splice(1)
239-
existingOnSuccess = execa(exec, args, {
240-
stdio: 'inherit',
241-
})
249+
}
242250
}
243-
}
244251

245-
const startWatcher = async () => {
246-
if (!options.watch) return
247-
248-
const { watch } = await import('chokidar')
249-
250-
const customIgnores = options.ignoreWatch
251-
? Array.isArray(options.ignoreWatch)
252-
? options.ignoreWatch
253-
: [options.ignoreWatch]
254-
: []
255-
256-
const ignored = [
257-
'**/{.git,node_modules}/**',
258-
options.outDir,
259-
...customIgnores,
260-
]
261-
262-
const watchPaths =
263-
typeof options.watch === 'boolean'
264-
? '.'
265-
: Array.isArray(options.watch)
266-
? options.watch.filter(
267-
(path): path is string => typeof path === 'string'
268-
)
269-
: options.watch
270-
271-
logger.info(
272-
'CLI',
273-
`Watching for changes in ${
274-
Array.isArray(watchPaths)
275-
? watchPaths.map((v) => '"' + v + '"').join(' | ')
276-
: '"' + watchPaths + '"'
277-
}`
278-
)
279-
logger.info(
280-
'CLI',
281-
`Ignoring changes in ${ignored
282-
.map((v) => '"' + v + '"')
283-
.join(' | ')}`
284-
)
252+
const startWatcher = async () => {
253+
if (!options.watch) return
285254

286-
const watcher = watch(watchPaths, {
287-
ignoreInitial: true,
288-
ignorePermissionErrors: true,
289-
ignored,
290-
})
291-
watcher.on('all', (type, file) => {
292-
file = slash(file)
293-
if (!buildDependencies.has(file)) return
255+
const { watch } = await import('chokidar')
294256

295-
logger.info('CLI', `Change detected: ${type} ${file}`)
296-
debouncedBuildAll()
297-
})
298-
}
257+
const customIgnores = options.ignoreWatch
258+
? Array.isArray(options.ignoreWatch)
259+
? options.ignoreWatch
260+
: [options.ignoreWatch]
261+
: []
299262

300-
logger.info('CLI', `Target: ${options.target}`)
263+
const ignored = [
264+
'**/{.git,node_modules}/**',
265+
options.outDir,
266+
...customIgnores,
267+
]
268+
269+
const watchPaths =
270+
typeof options.watch === 'boolean'
271+
? '.'
272+
: Array.isArray(options.watch)
273+
? options.watch.filter(
274+
(path): path is string => typeof path === 'string'
275+
)
276+
: options.watch
277+
278+
logger.info(
279+
'CLI',
280+
`Watching for changes in ${
281+
Array.isArray(watchPaths)
282+
? watchPaths.map((v) => '"' + v + '"').join(' | ')
283+
: '"' + watchPaths + '"'
284+
}`
285+
)
286+
logger.info(
287+
'CLI',
288+
`Ignoring changes in ${ignored
289+
.map((v) => '"' + v + '"')
290+
.join(' | ')}`
291+
)
301292

302-
await buildAll()
293+
const watcher = watch(watchPaths, {
294+
ignoreInitial: true,
295+
ignorePermissionErrors: true,
296+
ignored,
297+
})
298+
watcher.on('all', (type, file) => {
299+
file = slash(file)
300+
if (!buildDependencies.has(file)) return
303301

304-
startWatcher()
302+
logger.info('CLI', `Change detected: ${type} ${file}`)
303+
debouncedBuildAll()
304+
})
305+
}
306+
307+
logger.info('CLI', `Target: ${options.target}`)
308+
309+
await buildAll()
310+
311+
startWatcher()
312+
}
305313
}
314+
315+
await Promise.all([dtsTask(), otherTasks()])
306316
}
307317
)
308318
)

src/rollup.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ const startRollup = async (options: NormalizedOptions) => {
244244
watchRollup(config)
245245
} else {
246246
await runRollup(config)
247+
parentPort?.postMessage('success')
247248
parentPort?.close()
248249
}
249250
}

0 commit comments

Comments
 (0)