# Hooks
The @quercia/cli uses the tapable library for creating hooks via which you
can interact with the building process and modify configuration, add
functionality(even in a blocking manner).
The hooks are defined inside the quercia.ts file in the source directory of
the @quercia/cli module. Here's the code itself, which also includes helpful
comments about the time-of-execution of each and every hook.
TIP
The relevant lines are highlighted
import { AsyncParallelHook, AsyncSeriesHook } from 'tapable'
import Structure from './tasks/structure'
import Config from './tasks/config'
import Prerender from './tasks/prerender'
import Logger from '@quercia/logger'
import { Tasks } from 'task'
export interface Args {
src: string
}
export interface Flags {
mode: 'development' | 'production'
debug: boolean
typecheck: boolean
stats: boolean
}
// Shared class for both the build and watch command
// Shared steps:
// - flags = parsing command line flags
// - structure = reading the directory structure(pages, config)
// - configure = generating the webpack configurtion
// - build = either watching or building
// - prerender = prerendering pages(run on every change in watch mode)
export default class Quercia {
public static getInstance(): Quercia {
return Quercia.instance
}
private static instance: Quercia
public args: Args
public flags: Flags
public command: 'build' | 'watch'
constructor(command: 'build' | 'watch', args: Args, flags: Flags) {
Quercia.instance = this
this.command = command
this.args = args
this.flags = flags
this.logger = new Logger(flags.debug)
this.tasks = {
structure: new Structure(this),
config: new Config(this),
builder: null as any,
prerender: new Prerender(this)
}
}
public hooks = {
// called as the first hook available, before any logic is executed by quercia
beforeFlags: new AsyncParallelHook(['quercia']),
// called after the flags/args have been parsed
afterFlags: new AsyncParallelHook(['quercia']),
// called afeter the structure task has been executed
// it can be used as a beforeConfig
afterStructure: new AsyncSeriesHook(['quercia', 'structure']),
// called after the custom configuration(if any) has been executed
afterConfig: new AsyncSeriesHook(['quercia', 'config']),
// called after the build process has ended with the webpack stats
build: new AsyncSeriesHook(['quercia', 'stats']),
// called before starting the webpack watcher
beforeWatch: new AsyncSeriesHook(['quercia']),
// called after every watch cycle has completed
watch: new AsyncSeriesHook(['quercia', 'stats']),
// called after the compilation has ended
afterWatch: new AsyncSeriesHook(['quercia']),
// called before we start the prerender task (every new change in watch mode)
beforePrerender: new AsyncSeriesHook(['quercia']),
// called after the prerender task has ended (every new change in watch mode)
afterPrerender: new AsyncSeriesHook(['quercia', 'prerender']),
// called after the manifest files have been written
manifest: new AsyncSeriesHook(['quercia'])
}
public tasks: Tasks
public logger: Logger
public exit(code: number) {
process.exit(code)
}
public async run() {
// TODO: Load extensions
await this.hooks.beforeFlags.promise(this)
await this.hooks.afterFlags.promise(this)
await this.tasks.structure.execute()
await this.hooks.afterStructure.promise(this, this.tasks.structure)
await this.tasks.config.execute()
await this.hooks.afterConfig.promise(this, this.tasks.config)
// From here on its custom code based on the watch/build command
}
}