mirror of https://github.com/vuejs/vitepress
parent
5c06a082f3
commit
e5ed19d67d
@ -0,0 +1,77 @@
|
|||||||
|
import { Worker, workerData, isMainThread, parentPort } from 'worker_threads'
|
||||||
|
import { type UpdateHandle } from '../utils/task'
|
||||||
|
import { type RenderPageContext } from './render'
|
||||||
|
|
||||||
|
type TaskAllocator<T> = () => Promise<T | undefined>
|
||||||
|
|
||||||
|
import RpcContext from 'rpc-magic-proxy'
|
||||||
|
|
||||||
|
export default async function cluster(
|
||||||
|
entryPath: string,
|
||||||
|
context: RenderPageContext,
|
||||||
|
pages: string[],
|
||||||
|
update: UpdateHandle
|
||||||
|
) {
|
||||||
|
const concurrency = context.config.buildConcurrency || 1
|
||||||
|
const num_tasks = pages.length
|
||||||
|
let progress = -concurrency
|
||||||
|
|
||||||
|
const pageAlloc: TaskAllocator<string> = async () => {
|
||||||
|
progress++
|
||||||
|
if (progress >= 0) update(progress, num_tasks)
|
||||||
|
return pages.shift()
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks = []
|
||||||
|
|
||||||
|
for (let _ = 0; _ < concurrency; _++) {
|
||||||
|
const ctx = new RpcContext()
|
||||||
|
const workerData = await ctx.serialize({
|
||||||
|
entryPath,
|
||||||
|
pageAlloc,
|
||||||
|
context,
|
||||||
|
workload: 'render'
|
||||||
|
})
|
||||||
|
const worker = new Worker(new URL(import.meta.url), { workerData })
|
||||||
|
ctx.bind(worker)
|
||||||
|
tasks.push(
|
||||||
|
new Promise((res, rej) =>
|
||||||
|
worker.once('exit', (code) => {
|
||||||
|
if (code === 0) res(code)
|
||||||
|
else rej()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(tasks)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderWorker() {
|
||||||
|
const ctx = new RpcContext(parentPort!)
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
entryPath,
|
||||||
|
pageAlloc,
|
||||||
|
context
|
||||||
|
}: {
|
||||||
|
entryPath: string
|
||||||
|
pageAlloc: TaskAllocator<string>
|
||||||
|
context: RenderPageContext
|
||||||
|
} = ctx.deserialize(workerData)
|
||||||
|
const { pathToFileURL } = await import('url')
|
||||||
|
const { renderPage } = await import('./render')
|
||||||
|
const { render } = await import(pathToFileURL(entryPath).toString())
|
||||||
|
while (true) {
|
||||||
|
const page = await pageAlloc()
|
||||||
|
if (!page) break
|
||||||
|
await renderPage(render, page, context)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
ctx.reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMainThread && workerData?.workload === 'render') renderWorker()
|
Loading…
Reference in new issue