UNPKG

utquidem

Version:

The meta-framework suite designed from scratch for frontend-focused modern web development.

156 lines (132 loc) 4.64 kB
import path from 'path'; import { AsyncParallelHook, AsyncSeriesHook, SyncHook } from 'tapable'; import type { EnvironmentVariables, NormalizedEsmpackOptions } from './Options'; import { Compilation, CompilationParams } from './Compilation'; import { Logger } from './Logger'; import { Cache } from './Cache'; export interface ImportMap { imports: { [packageName: string]: string }; } export interface OutputFile { /** * Absolute file path */ fileLoc: string; compilation: Compilation; } interface CompilerHooks { environment: SyncHook<EnvironmentVariables>; initialize: AsyncParallelHook<Compiler>; beforeCompile: AsyncSeriesHook<CompilationParams>; compile: SyncHook<CompilationParams>; afterCompile: AsyncSeriesHook<Compilation>; newCompilation: AsyncSeriesHook<[Compilation, CompilationParams]>; compilation: SyncHook<[Compilation, CompilationParams]>; make: AsyncParallelHook<Compilation>; finishMake: AsyncSeriesHook<Compilation>; failed: SyncHook<Error>; importMap: SyncHook<[ImportMap, Compilation]>; } class Compiler { public hooks: CompilerHooks = Object.freeze({ environment: new SyncHook<EnvironmentVariables>(['envVars']), initialize: new AsyncParallelHook<Compiler>(['compiler']), beforeCompile: new AsyncSeriesHook<CompilationParams>([ 'compilationParams', ]), compile: new SyncHook<CompilationParams>(['compilationParams']), afterCompile: new AsyncSeriesHook<Compilation>(['compilation']), newCompilation: new AsyncSeriesHook<[Compilation, CompilationParams]>([ 'compilation', 'compilationParams', ]), compilation: new SyncHook<[Compilation, CompilationParams]>([ 'compilation', 'compilationParams', ]), make: new AsyncParallelHook<Compilation>(['compilation']), finishMake: new AsyncSeriesHook<Compilation>(['compilation']), failed: new SyncHook<Error>(['error']), importMap: new SyncHook<[ImportMap, Compilation]>([ 'importMap', 'compilation', ]), }); public cache: Cache = new Cache(); public logger: Logger = this.getLogger('esmpack.Compiler'); public importMap: ImportMap = { imports: {} }; public outputFiles: OutputFile[] = []; constructor(public options: NormalizedEsmpackOptions) {} async init() { /// /////////// // env /// /////////// this.hooks.environment.call(this.options.env); await this.hooks.initialize.promise(this); } async run(params: CompilationParams) { try { return await this.compile(params); } catch (e: any) { this.hooks.failed.call(e); throw e; } } close() { // noop } private async createCompilation(compilationParams: CompilationParams) { const compilation = new Compilation(this, { ...compilationParams, specifier: compilationParams.specifier || this.options.specifier || '', state: compilationParams.state || {}, }); return compilation; } private async newCompilation(compilationParams: CompilationParams) { const compilation = await this.createCompilation(compilationParams); await this.hooks.newCompilation.promise(compilation, compilationParams); this.hooks.compilation.call(compilation, compilationParams); await compilation.init(); return compilation; } private async compile(params: CompilationParams) { const compilationParams = params; await this.hooks.beforeCompile.promise(compilationParams); this.hooks.compile.call(compilationParams); const compilation = await this.newCompilation(compilationParams); await this.hooks.make.promise(compilation); await this.hooks.finishMake.promise(compilation); await compilation.build(); await compilation.emit(); await this.hooks.afterCompile.promise(compilation); const rollupOutput = compilation.rollupOutput!; /** * Import map */ const entryChunk = rollupOutput.output.find( chunk => 'isEntry' in chunk && chunk.isEntry, ); if (!entryChunk) { this.logger.error('entry chunk is not found'); } else { // import map path must be a relative path this.importMap.imports[params.specifier] = `./${entryChunk.fileName}`; this.hooks.importMap.call(this.importMap, compilation); } /** * Output files */ this.outputFiles = this.outputFiles.concat( rollupOutput.output.map(chunk => ({ fileLoc: path.resolve(compilation.outputOptions.dir!, chunk.fileName), compilation, })), ); return compilation; } private getLogger(name: string) { return new Logger(name); } } export { Compiler };