@@ -10,9 +10,10 @@ import type {
1010import fs from 'node:fs' ;
1111import { cpus as nodeCpus } from 'node:os' ;
1212import { Worker } from 'node:worker_threads' ;
13- import { dirname , extname , isAbsolute , join , resolve } from 'node:path' ;
13+ import { isAbsolute , resolve } from 'node:path' ;
1414import { ensureDir } from './node-system' ;
1515import { normalizePath } from '../../utils/fs' ;
16+ import { createSingleThreadWorker } from '../worker-thread' ;
1617
1718export async function createNodeMainProcess ( sys : System , opts : StaticGenerateOptions ) {
1819 const ssgWorkers : StaticGeneratorWorker [ ] = [ ] ;
@@ -50,34 +51,45 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
5051 }
5152 }
5253
53- const createWorker = ( ) => {
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 : StaticGeneratorWorker = {
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+
5476 let terminateResolve : ( ( ) => void ) | null = null ;
5577 const mainTasks = new Map < string , WorkerMainTask > ( ) ;
5678
5779 let workerFilePath : string | URL ;
58- let terminateTimeout : number | null = null ;
5980
60- // Launch the worker using the package's index module, which bootstraps the worker thread.
6181 if ( typeof __filename === 'string' ) {
62- // CommonJS path
63- const ext = extname ( __filename ) || '.js' ;
64- workerFilePath = join ( dirname ( __filename ) , `index${ ext } ` ) ;
82+ workerFilePath = __filename ;
6583 } else {
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- }
84+ workerFilePath = import . meta. url ;
85+ }
7586
76- workerFilePath = new URL ( `./index${ ext } ` , thisUrl ) ;
87+ if ( typeof workerFilePath === 'string' && workerFilePath . startsWith ( 'file://' ) ) {
88+ workerFilePath = new URL ( workerFilePath ) ;
7789 }
7890
7991 const nodeWorker = new Worker ( workerFilePath , { workerData : opts } ) ;
80- nodeWorker . unref ( ) ;
92+
8193 const ssgWorker : StaticGeneratorWorker = {
8294 activeTasks : 0 ,
8395 totalTasks : 0 ,
@@ -104,9 +116,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
104116 terminateResolve = resolve ;
105117 nodeWorker . postMessage ( msg ) ;
106118 } ) ;
107- terminateTimeout = setTimeout ( async ( ) => {
108- await nodeWorker . terminate ( ) ;
109- } , 1000 ) as unknown as number ;
119+ await nodeWorker . terminate ( ) ;
110120 } ,
111121 } ;
112122
@@ -136,11 +146,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
136146 } ) ;
137147
138148 nodeWorker . on ( 'exit' , ( code ) => {
139- if ( terminateTimeout ) {
140- clearTimeout ( terminateTimeout ) ;
141- terminateTimeout = null ;
142- }
143- if ( code !== 0 ) {
149+ if ( code !== 1 ) {
144150 console . error ( `worker exit ${ code } ` ) ;
145151 }
146152 } ) ;
@@ -194,15 +200,9 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
194200 console . error ( e ) ;
195201 }
196202 }
197-
198- await Promise . all ( promises ) ;
199203 ssgWorkers . length = 0 ;
200204
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- }
205+ await Promise . all ( promises ) ;
206206 } ;
207207
208208 if ( sitemapOutFile ) {
@@ -214,11 +214,7 @@ export async function createNodeMainProcess(sys: System, opts: StaticGenerateOpt
214214 }
215215
216216 for ( let i = 0 ; i < maxWorkers ; 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- }
217+ ssgWorkers . push ( createWorker ( i ) ) ;
222218 }
223219
224220 const mainCtx : MainContext = {
0 commit comments