UNPKG

@farmfe/core

Version:

Farm is a extremely fast web build tool written in Rust. Farm can start a project in milliseconds and perform HMR within 10ms, making it much faster than similar tools like webpack and vite.

169 lines 5.87 kB
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import { Compiler as BindingCompiler } from '../../binding/index.js'; import { Logger } from '../utils/logger.js'; export const VIRTUAL_FARM_DYNAMIC_IMPORT_SUFFIX = '.farm_dynamic_import_virtual_module'; export class Compiler { constructor(config, logger = new Logger()) { this.config = config; this.logger = logger; this._updateQueue = []; this._onUpdateFinishQueue = []; this.compiling = false; this._bindingCompiler = new BindingCompiler(this.config); } async traceDependencies() { return this._bindingCompiler.traceDependencies(); } async traceModuleGraph() { return this._bindingCompiler.traceModuleGraph(); } async compile() { if (this.compiling) { this.logger.error('Already compiling', { exit: true }); } this.compiling = true; if (process.env.FARM_PROFILE) { this._bindingCompiler.compileSync(); } else { await this._bindingCompiler.compile(); } this.compiling = false; } compileSync() { if (this.compiling) { this.logger.error('Already compiling', { exit: true }); } this.compiling = true; this._bindingCompiler.compileSync(); this.compiling = false; } async update(paths, sync = false, ignoreCompilingCheck = false, generateUpdateResource = true) { let resolve; const promise = new Promise((r) => { resolve = r; }); // if there is already a update process, we need to wait for it to finish if (this.compiling && !ignoreCompilingCheck) { this._updateQueue.push({ paths, resolve }); return promise; } this.compiling = true; try { const res = await this._bindingCompiler.update(paths, async () => { const next = this._updateQueue.shift(); if (next) { await this.update(next.paths, true, true, generateUpdateResource).then(next.resolve); } else { this.compiling = false; while (this._onUpdateFinishQueue.length) { if (this.compiling) { break; } const cb = this._onUpdateFinishQueue.shift(); await cb(); } } }, sync, generateUpdateResource); return res; } catch (e) { this.compiling = false; throw e; } } hasModule(resolvedPath) { return this._bindingCompiler.hasModule(resolvedPath); } getParentFiles(idOrResolvedPath) { return this._bindingCompiler.getParentFiles(idOrResolvedPath); } resources() { return this._bindingCompiler.resources(); } resource(path) { return this._bindingCompiler.resource(path); } resourcesMap() { return this._bindingCompiler.resourcesMap(); } writeResourcesToDisk() { const resources = this.resources(); const configOutputPath = this.config.config.output.path; const outputPath = path.isAbsolute(configOutputPath) ? configOutputPath : path.join(this.config.config.root, configOutputPath); for (const [name, resource] of Object.entries(resources)) { // remove query params and hash of name const nameWithoutQuery = name.split('?')[0]; const nameWithoutHash = nameWithoutQuery.split('#')[0]; let filePath = path.join(outputPath, nameWithoutHash); if (!existsSync(path.dirname(filePath))) { mkdirSync(path.dirname(filePath), { recursive: true }); } writeFileSync(filePath, resource); } this.callWriteResourcesHook(); } callWriteResourcesHook() { for (const jsPlugin of this.config.jsPlugins ?? []) { jsPlugin.writeResources?.executor?.({ resourcesMap: this._bindingCompiler.resourcesMap(), config: this.config.config }); } } removeOutputPathDir() { const outputPath = this.outputPath(); if (existsSync(outputPath)) { rmSync(outputPath, { recursive: true }); } } resolvedWatchPaths() { return this._bindingCompiler.watchModules(); } resolvedModulePaths(root) { return this._bindingCompiler .relativeModulePaths() .map((p) => this.transformModulePath(root, p)); } transformModulePath(root, p) { if (p.endsWith(VIRTUAL_FARM_DYNAMIC_IMPORT_SUFFIX)) { p = p.slice(0, -VIRTUAL_FARM_DYNAMIC_IMPORT_SUFFIX.length); } if (path.isAbsolute(p)) { return p; } if (p.includes('?')) { return path.join(root, p.split('?')[0]); } return path.join(root, p); } onUpdateFinish(cb) { this._onUpdateFinishQueue.push(cb); } outputPath() { const { output, root } = this.config.config; const configOutputPath = output.path; const outputPath = path.isAbsolute(configOutputPath) ? configOutputPath : path.join(root, configOutputPath); return outputPath; } addExtraWatchFile(root, paths) { this._bindingCompiler.addWatchFiles(root, paths); } stats() { return this._bindingCompiler.stats(); } invalidateModule(moduleId) { this._bindingCompiler.invalidateModule(moduleId); } } //# sourceMappingURL=index.js.map