presta
Version:
Hyper minimal framework for the modern web.
150 lines (127 loc) • 3.6 kB
text/typescript
import fs from 'fs-extra'
import { build as esbuild } from 'esbuild'
import { outputLambdas } from './outputLambdas'
import { getFiles, isStatic, isDynamic } from './getFiles'
import { renderStaticEntries } from './renderStaticEntries'
import { timer } from './timer'
import * as logger from './log'
import { Presta } from './types'
function getRoutesManifestSafely(manifestFilepath: string) {
try {
return require(manifestFilepath)
} catch (e) {
return {}
}
}
export async function build(config: Presta) {
const totalTime = timer()
const files = getFiles(config)
const staticIds = files.filter(isStatic)
const dynamicIds = files.filter(isDynamic)
logger.debug({
label: 'build',
message: 'starting build',
})
if (!staticIds.length && !dynamicIds.length) {
logger.warn({
label: 'files',
message: 'no files were found, nothing to build',
})
} else {
let staticTime = ''
let staticFileAmount = 0
let dynamicTime = ''
let copyTime = ''
const tasks = await Promise.allSettled([
(async () => {
if (staticIds.length) {
const time = timer()
const { allGeneratedFiles } = await renderStaticEntries(staticIds, config)
staticTime = time()
staticFileAmount = allGeneratedFiles.length
}
})(),
(async () => {
if (dynamicIds.length) {
const time = timer()
outputLambdas(dynamicIds, config)
await esbuild({
entryPoints: Object.values(require(config.functionsManifest)),
outdir: config.functionsOutputDir,
bundle: true,
platform: 'node',
target: ['node12'],
minify: true,
allowOverwrite: true,
define: {
'process.env.PRESTA_SERVERLESS_RUNTIME': 'true',
},
})
dynamicTime = time()
}
})(),
(async () => {
if (fs.existsSync(config.assets)) {
const time = timer()
fs.copySync(config.assets, config.staticOutputDir)
copyTime = time()
}
})(),
])
// since we're building (not watch) if any task fails, exit with error
if (tasks.find((task) => task.status === 'rejected')) {
logger.debug({
label: 'build',
message: 'build partially failed',
})
// log out errors
tasks.forEach((task) => {
if (task.status === 'rejected') {
logger.error({
label: 'error',
error: task.reason,
})
}
})
process.exit(1)
return
}
if (staticTime || dynamicTime) {
logger.newline()
}
if (staticTime) {
logger.info({
label: 'static',
message: `rendered ${staticFileAmount} file(s)`,
duration: staticTime,
})
}
if (dynamicTime) {
logger.info({
label: 'lambda',
message: `compiled ${dynamicIds.length} function(s)`,
duration: dynamicTime,
})
}
if (copyTime) {
logger.info({
label: 'assets',
message: `copied in ${copyTime}`,
})
}
config.hooks.emitPostBuild({
output: config.output,
staticOutput: config.staticOutputDir,
functionsOutput: config.functionsOutputDir,
functionsManifest: getRoutesManifestSafely(config.functionsManifest),
})
if (staticTime || dynamicTime) {
logger.newline()
logger.info({
label: 'complete',
message: `in ${totalTime()}`,
})
logger.newline()
}
}
}