Skip to content

Commit d585946

Browse files
Harden build failures and dev CSS placeholders
Propagate webpack build failures via explicit exit codes so production builds fail loudly. Derive dev CSS placeholders from the computed output list to avoid hardcoded filenames.
1 parent 013de8e commit d585946

1 file changed

Lines changed: 49 additions & 16 deletions

File tree

build.mjs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -406,21 +406,33 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil
406406
if (isProduction) {
407407
// Ensure compiler is properly closed after production runs
408408
compiler.run((err, stats) => {
409+
const hasErrors = !!(
410+
err ||
411+
(stats && typeof stats.hasErrors === 'function' && stats.hasErrors())
412+
)
413+
let callbackFailed = false
409414
const finishClose = () =>
410415
compiler.close((closeErr) => {
411416
if (closeErr) {
412417
console.error('Error closing compiler:', closeErr)
413418
process.exitCode = 1
414419
}
420+
if (hasErrors || callbackFailed) {
421+
process.exitCode = 1
422+
}
415423
})
416424
try {
417425
const ret = callback(err, stats)
418426
if (ret && typeof ret.then === 'function') {
419-
ret.then(finishClose, finishClose)
427+
ret.then(finishClose, () => {
428+
callbackFailed = true
429+
finishClose()
430+
})
420431
} else {
421432
finishClose()
422433
}
423434
} catch (_) {
435+
callbackFailed = true
424436
finishClose()
425437
}
426438
})
@@ -517,18 +529,19 @@ async function copyFiles(entryPoints, targetDir) {
517529
}
518530

519531
// In development, create placeholder CSS and sourcemap files to avoid 404 noise
520-
async function ensureDevCssPlaceholders(targetDir) {
521-
if (isProduction) return
522-
const cssFiles = [path.join(targetDir, 'popup.css'), path.join(targetDir, 'content-script.css')]
523-
for (const cssPath of cssFiles) {
524-
if (!(await fs.pathExists(cssPath))) {
525-
await fs.outputFile(cssPath, '/* dev placeholder */\n')
526-
}
527-
const mapPath = `${cssPath}.map`
528-
if (!(await fs.pathExists(mapPath))) {
529-
await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}')
530-
}
531-
}
532+
async function ensureDevCssPlaceholders(cssFiles) {
533+
if (isProduction || cssFiles.length === 0) return
534+
await Promise.all(
535+
cssFiles.map(async (cssPath) => {
536+
if (!(await fs.pathExists(cssPath))) {
537+
await fs.outputFile(cssPath, '/* dev placeholder */\n')
538+
}
539+
const mapPath = `${cssPath}.map`
540+
if (!(await fs.pathExists(mapPath))) {
541+
await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}')
542+
}
543+
}),
544+
)
532545
}
533546

534547
async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) {
@@ -567,7 +580,15 @@ async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) {
567580
[...commonFiles, { src: 'src/manifest.json', dst: 'manifest.json' }],
568581
chromiumOutputDir,
569582
)
570-
await ensureDevCssPlaceholders(chromiumOutputDir)
583+
await ensureDevCssPlaceholders(
584+
Array.from(
585+
new Set(
586+
commonFiles
587+
.filter((file) => file.dst.endsWith('.css'))
588+
.map((file) => path.join(chromiumOutputDir, file.dst)),
589+
),
590+
),
591+
)
571592
if (isProduction) await zipFolder(chromiumOutputDir)
572593

573594
// firefox
@@ -576,7 +597,15 @@ async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) {
576597
[...commonFiles, { src: 'src/manifest.v2.json', dst: 'manifest.json' }],
577598
firefoxOutputDir,
578599
)
579-
await ensureDevCssPlaceholders(firefoxOutputDir)
600+
await ensureDevCssPlaceholders(
601+
Array.from(
602+
new Set(
603+
commonFiles
604+
.filter((file) => file.dst.endsWith('.css'))
605+
.map((file) => path.join(firefoxOutputDir, file.dst)),
606+
),
607+
),
608+
)
580609
if (isProduction) await zipFolder(firefoxOutputDir)
581610
}
582611

@@ -612,10 +641,14 @@ async function build() {
612641
const tmpMin = `${outdir}/.tmp-min`
613642
try {
614643
if (parallelBuild) {
615-
await Promise.all([
644+
const results = await Promise.allSettled([
616645
createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken'),
617646
createWebpackBuildPromise(false, false, false, tmpFull, ''),
618647
])
648+
const failed = results.find((result) => result.status === 'rejected')
649+
if (failed) {
650+
throw failed.reason
651+
}
619652
} else {
620653
await createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken')
621654
await createWebpackBuildPromise(false, false, false, tmpFull, '')

0 commit comments

Comments
 (0)