better concurrency debugging, --concurrency flag for npx quartz build
1 files added
8 files modified
| | |
| | | tsconfig.tsbuildinfo |
| | | .obsidian |
| | | .quartz-cache |
| | | private/ |
| | |
| | | > - `-o` or `--output`: the output folder. This is normally just `public` |
| | | > - `--serve`: run a local hot-reloading server to preview your Quartz |
| | | > - `--port`: what port to run the local preview server on |
| | | > - `--concurrency`: how many threads to use to parse notes |
| | |
| | | default: false, |
| | | describe: "show detailed bundle information", |
| | | }, |
| | | concurrency: { |
| | | number: true, |
| | | describe: "how many threads to use to parse notes" |
| | | } |
| | | } |
| | | |
| | | function escapePath(fp) { |
| | |
| | | import sourceMapSupport from "source-map-support" |
| | | sourceMapSupport.install({ |
| | | retrieveSourceMap(source) { |
| | | // source map hack to get around query param |
| | | // import cache busting |
| | | if (source.includes(".quartz-cache")) { |
| | | let realSource = fileURLToPath(source.split("?", 2)[0] + ".map") |
| | | return { |
| | | map: fs.readFileSync(realSource, "utf8"), |
| | | } |
| | | } else { |
| | | return null |
| | | } |
| | | }, |
| | | }) |
| | | |
| | | sourceMapSupport.install(options) |
| | | import path from "path" |
| | | import { PerfTimer } from "./perf" |
| | | import { rimraf } from "rimraf" |
| | |
| | | import { filterContent } from "./processors/filter" |
| | | import { emitContent } from "./processors/emit" |
| | | import cfg from "../quartz.config" |
| | | import { FilePath, ServerSlug, joinSegments, slugifyFilePath } from "./path" |
| | | import { FilePath, joinSegments, slugifyFilePath } from "./path" |
| | | import chokidar from "chokidar" |
| | | import { ProcessedContent } from "./plugins/vfile" |
| | | import { Argv, BuildCtx } from "./ctx" |
| | | import { glob, toPosixPath } from "./glob" |
| | | import { trace } from "./trace" |
| | | import { fileURLToPath } from "url" |
| | | import fs from "fs" |
| | | import { options } from "./sourcemap" |
| | | |
| | | async function buildQuartz(argv: Argv, clientRefresh: () => void) { |
| | | const ctx: BuildCtx = { |
| | |
| | | output: string |
| | | serve: boolean |
| | | port: number |
| | | concurrency?: number |
| | | } |
| | | |
| | | export interface BuildCtx { |
| | |
| | | platform: "node", |
| | | format: "esm", |
| | | packages: "external", |
| | | sourcemap: true, |
| | | sourcesContent: false, |
| | | plugins: [ |
| | | { |
| | | name: "css-and-scripts-as-text", |
| | |
| | | const log = new QuartzLogger(argv.verbose) |
| | | |
| | | const CHUNK_SIZE = 128 |
| | | let concurrency = fps.length < CHUNK_SIZE ? 1 : os.availableParallelism() |
| | | let concurrency = ctx.argv.concurrency ?? (fps.length < CHUNK_SIZE ? 1 : os.availableParallelism()) |
| | | |
| | | let res: ProcessedContent[] = [] |
| | | log.start(`Parsing input files using ${concurrency} threads`) |
| | |
| | | childPromises.push(pool.exec("parseFiles", [argv, chunk, ctx.allSlugs])) |
| | | } |
| | | |
| | | const results: ProcessedContent[][] = await WorkerPromise.all(childPromises) |
| | | const results: ProcessedContent[][] = await WorkerPromise.all(childPromises).catch((err) => { |
| | | const errString = err.toString().slice("Error:".length) |
| | | console.error(errString) |
| | | process.exit(1) |
| | | }) |
| | | res = results.flat() |
| | | await pool.terminate() |
| | | } |
| New file |
| | |
| | | import fs from "fs" |
| | | import sourceMapSupport from "source-map-support" |
| | | import { fileURLToPath } from "url" |
| | | |
| | | export const options: sourceMapSupport.Options = { |
| | | // source map hack to get around query param |
| | | // import cache busting |
| | | retrieveSourceMap(source) { |
| | | if (source.includes(".quartz-cache")) { |
| | | let realSource = fileURLToPath(source.split("?", 2)[0] + ".map") |
| | | return { |
| | | map: fs.readFileSync(realSource, "utf8"), |
| | | } |
| | | } else { |
| | | return null |
| | | } |
| | | }, |
| | | } |
| | | |
| | |
| | | import chalk from "chalk" |
| | | import process from "process" |
| | | import { isMainThread } from "workerpool" |
| | | |
| | | const rootFile = /.*at file:/ |
| | | export function trace(msg: string, err: Error) { |
| | | const stack = err.stack |
| | | console.log() |
| | | console.log( |
| | | |
| | | const lines: string[] = [] |
| | | |
| | | lines.push("") |
| | | lines.push( |
| | | "\n" + |
| | | chalk.bgRed.black.bold(" ERROR ") + |
| | | "\n" + |
| | | chalk.red(` ${msg}`) + |
| | | (err.message.length > 0 ? `: ${err.message}` : ""), |
| | | chalk.bgRed.black.bold(" ERROR ") + |
| | | "\n" + |
| | | chalk.red(` ${msg}`) + |
| | | (err.message.length > 0 ? `: ${err.message}` : ""), |
| | | ) |
| | | |
| | | if (!stack) { |
| | | return |
| | | } |
| | |
| | | } |
| | | |
| | | if (!line.includes("node_modules")) { |
| | | console.log(` ${line}`) |
| | | lines.push(` ${line}`) |
| | | if (rootFile.test(line)) { |
| | | reachedEndOfLegibleTrace = true |
| | | } |
| | | } |
| | | } |
| | | process.exit(1) |
| | | |
| | | const traceMsg = lines.join("\n") |
| | | if (!isMainThread) { |
| | | // gather lines and throw |
| | | throw new Error(traceMsg) |
| | | } else { |
| | | // print and exit |
| | | console.error(traceMsg) |
| | | process.exit(1) |
| | | } |
| | | } |
| | |
| | | import sourceMapSupport from "source-map-support" |
| | | sourceMapSupport.install(options) |
| | | import cfg from "../quartz.config" |
| | | import { Argv, BuildCtx } from "./ctx" |
| | | import { FilePath, ServerSlug } from "./path" |
| | | import { createFileParser, createProcessor } from "./processors/parse" |
| | | import { options } from "./sourcemap" |
| | | |
| | | // only called from worker thread |
| | | export async function parseFiles(argv: Argv, fps: FilePath[], allSlugs: ServerSlug[]) { |