@@ -10,10 +10,9 @@ import type {
1010import fs from 'node:fs' ;
1111import { cpus as nodeCpus } from 'node:os' ;
1212import { Worker } from 'node:worker_threads' ;
13- import { isAbsolute , resolve } from 'node:path' ;
13+ import { dirname , extname , isAbsolute , join , resolve } from 'node:path' ;
1414import { ensureDir } from './node-system' ;
1515import { normalizePath } from '../../utils/fs' ;
16- import { createSingleThreadWorker } from '../worker-thread' ;
1716
1817export async function createNodeMainProcess ( sys : System , opts : SsgOptions ) {
1918 const ssgWorkers : SsgWorker [ ] = [ ] ;
@@ -51,45 +50,34 @@ export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
5150 }
5251 }
5352
54- const singleThreadWorker = await createSingleThreadWorker ( sys ) ;
55-
56- const createWorker = ( workerIndex : number ) => {
57- if ( workerIndex === 0 ) {
58- // same thread worker, don't start a new process
59- const ssgSameThreadWorker : SsgWorker = {
60- activeTasks : 0 ,
61- totalTasks : 0 ,
62-
63- render : async ( staticRoute ) => {
64- ssgSameThreadWorker . activeTasks ++ ;
65- ssgSameThreadWorker . totalTasks ++ ;
66- const result = await singleThreadWorker ( staticRoute ) ;
67- ssgSameThreadWorker . activeTasks -- ;
68- return result ;
69- } ,
70-
71- terminate : async ( ) => { } ,
72- } ;
73- return ssgSameThreadWorker ;
74- }
75-
53+ const createWorker = ( ) => {
7654 let terminateResolve : ( ( ) => void ) | null = null ;
7755 const mainTasks = new Map < string , WorkerMainTask > ( ) ;
7856
7957 let workerFilePath : string | URL ;
58+ let terminateTimeout : number | null = null ;
8059
60+ // Launch the worker using the package's index module, which bootstraps the worker thread.
8161 if ( typeof __filename === 'string' ) {
82- workerFilePath = __filename ;
62+ // CommonJS path
63+ const ext = extname ( __filename ) || '.js' ;
64+ workerFilePath = join ( dirname ( __filename ) , `index${ ext } ` ) ;
8365 } else {
84- workerFilePath = import . meta. url ;
85- }
66+ // ESM path (import.meta.url)
67+ const thisUrl = new URL ( import . meta. url ) ;
68+ const pathname = thisUrl . pathname || '' ;
69+ let ext = '.js' ;
70+ if ( pathname . endsWith ( '.ts' ) ) {
71+ ext = '.ts' ;
72+ } else if ( pathname . endsWith ( '.mjs' ) ) {
73+ ext = '.mjs' ;
74+ }
8675
87- if ( typeof workerFilePath === 'string' && workerFilePath . startsWith ( 'file://' ) ) {
88- workerFilePath = new URL ( workerFilePath ) ;
76+ workerFilePath = new URL ( `./index${ ext } ` , thisUrl ) ;
8977 }
9078
9179 const nodeWorker = new Worker ( workerFilePath , { workerData : opts } ) ;
92-
80+ nodeWorker . unref ( ) ;
9381 const ssgWorker : SsgWorker = {
9482 activeTasks : 0 ,
9583 totalTasks : 0 ,
@@ -116,7 +104,9 @@ export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
116104 terminateResolve = resolve ;
117105 nodeWorker . postMessage ( msg ) ;
118106 } ) ;
119- await nodeWorker . terminate ( ) ;
107+ terminateTimeout = setTimeout ( async ( ) => {
108+ await nodeWorker . terminate ( ) ;
109+ } , 1000 ) as unknown as number ;
120110 } ,
121111 } ;
122112
@@ -146,7 +136,11 @@ export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
146136 } ) ;
147137
148138 nodeWorker . on ( 'exit' , ( code ) => {
149- if ( code !== 1 ) {
139+ if ( terminateTimeout ) {
140+ clearTimeout ( terminateTimeout ) ;
141+ terminateTimeout = null ;
142+ }
143+ if ( code !== 0 ) {
150144 console . error ( `worker exit ${ code } ` ) ;
151145 }
152146 } ) ;
@@ -200,9 +194,15 @@ export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
200194 console . error ( e ) ;
201195 }
202196 }
203- ssgWorkers . length = 0 ;
204197
205198 await Promise . all ( promises ) ;
199+ ssgWorkers . length = 0 ;
200+
201+ // On Windows, give extra time for all workers to fully exit
202+ // This prevents resource conflicts in back-to-back builds
203+ if ( process . platform === 'win32' ) {
204+ await new Promise ( ( resolve ) => setTimeout ( resolve , 300 ) ) ;
205+ }
206206 } ;
207207
208208 if ( sitemapOutFile ) {
@@ -214,7 +214,11 @@ export async function createNodeMainProcess(sys: System, opts: SsgOptions) {
214214 }
215215
216216 for ( let i = 0 ; i < maxWorkers ; i ++ ) {
217- ssgWorkers . push ( createWorker ( i ) ) ;
217+ ssgWorkers . push ( createWorker ( ) ) ;
218+ // On Windows, add delay between worker creation to avoid resource contention
219+ if ( process . platform === 'win32' && i < maxWorkers - 1 ) {
220+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
221+ }
218222 }
219223
220224 const mainCtx : MainContext = {
0 commit comments