mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-15 18:34:50 +00:00
158 lines
5.4 KiB
TypeScript
158 lines
5.4 KiB
TypeScript
import { relative, resolve, join } from 'pathe'
|
|
import consola from 'consola'
|
|
import * as rollup from 'rollup'
|
|
import fse from 'fs-extra'
|
|
import { printFSTree } from './utils/tree'
|
|
import { getRollupConfig } from './rollup/config'
|
|
import { hl, prettyPath, serializeTemplate, writeFile, isDirectory } from './utils'
|
|
import { NitroContext } from './context'
|
|
import { scanMiddleware } from './server/middleware'
|
|
|
|
export async function prepare (nitroContext: NitroContext) {
|
|
consola.info(`Nitro preset is ${hl(nitroContext.preset)}`)
|
|
|
|
await cleanupDir(nitroContext.output.dir)
|
|
|
|
if (!nitroContext.output.publicDir.startsWith(nitroContext.output.dir)) {
|
|
await cleanupDir(nitroContext.output.publicDir)
|
|
}
|
|
|
|
if (!nitroContext.output.serverDir.startsWith(nitroContext.output.dir)) {
|
|
await cleanupDir(nitroContext.output.serverDir)
|
|
}
|
|
}
|
|
|
|
async function cleanupDir (dir: string) {
|
|
consola.info('Cleaning up', prettyPath(dir))
|
|
await fse.emptyDir(dir)
|
|
}
|
|
|
|
export async function generate (nitroContext: NitroContext) {
|
|
consola.start('Generating public...')
|
|
|
|
const clientDist = resolve(nitroContext._nuxt.buildDir, 'dist/client')
|
|
if (await isDirectory(clientDist)) {
|
|
await fse.copy(clientDist, join(nitroContext.output.publicDir, nitroContext._nuxt.publicPath))
|
|
}
|
|
|
|
const publicDir = nitroContext._nuxt.publicDir
|
|
if (await isDirectory(publicDir)) {
|
|
await fse.copy(publicDir, nitroContext.output.publicDir)
|
|
}
|
|
|
|
consola.success('Generated public ' + prettyPath(nitroContext.output.publicDir))
|
|
}
|
|
|
|
export async function build (nitroContext: NitroContext) {
|
|
// Compile html template
|
|
const htmlSrc = resolve(nitroContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`)
|
|
const htmlTemplate = { src: htmlSrc, contents: '', dst: '' }
|
|
htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.mjs').replace('app.template.mjs', 'document.template.mjs')
|
|
htmlTemplate.contents = nitroContext.vfs[htmlTemplate.src] || await fse.readFile(htmlTemplate.src, 'utf-8')
|
|
await nitroContext._internal.hooks.callHook('nitro:document', htmlTemplate)
|
|
const compiled = 'export default ' + serializeTemplate(htmlTemplate.contents)
|
|
await writeFile(htmlTemplate.dst, compiled)
|
|
|
|
nitroContext.rollupConfig = getRollupConfig(nitroContext)
|
|
await nitroContext._internal.hooks.callHook('nitro:rollup:before', nitroContext)
|
|
return nitroContext._nuxt.dev ? _watch(nitroContext) : _build(nitroContext)
|
|
}
|
|
|
|
async function writeTypes (nitroContext: NitroContext) {
|
|
const routeTypes: Record<string, string[]> = {}
|
|
|
|
const middleware = [
|
|
...nitroContext.scannedMiddleware,
|
|
...nitroContext.middleware
|
|
]
|
|
|
|
for (const mw of middleware) {
|
|
if (typeof mw.handle !== 'string') { continue }
|
|
const relativePath = relative(nitroContext._nuxt.buildDir, mw.handle).replace(/\.[a-z]+$/, '')
|
|
routeTypes[mw.route] = routeTypes[mw.route] || []
|
|
routeTypes[mw.route].push(`Awaited<ReturnType<typeof import('${relativePath}').default>>`)
|
|
}
|
|
|
|
const lines = [
|
|
'// Generated by nitro',
|
|
'declare module \'@nuxt/nitro\' {',
|
|
' type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T',
|
|
' interface InternalApi {',
|
|
...Object.entries(routeTypes).map(([path, types]) => ` '${path}': ${types.join(' | ')}`),
|
|
' }',
|
|
'}',
|
|
// Makes this a module for augmentation purposes
|
|
'export {}'
|
|
]
|
|
|
|
await writeFile(join(nitroContext._nuxt.buildDir, 'nitro.d.ts'), lines.join('\n'))
|
|
}
|
|
|
|
async function _build (nitroContext: NitroContext) {
|
|
nitroContext.scannedMiddleware = await scanMiddleware(nitroContext._nuxt.serverDir)
|
|
await writeTypes(nitroContext)
|
|
|
|
consola.start('Building server...')
|
|
const build = await rollup.rollup(nitroContext.rollupConfig).catch((error) => {
|
|
consola.error('Rollup error: ' + error.message)
|
|
throw error
|
|
})
|
|
|
|
consola.start('Writing server bundle...')
|
|
await build.write(nitroContext.rollupConfig.output)
|
|
|
|
consola.success('Server built')
|
|
await printFSTree(nitroContext.output.serverDir)
|
|
await nitroContext._internal.hooks.callHook('nitro:compiled', nitroContext)
|
|
|
|
return {
|
|
entry: resolve(nitroContext.rollupConfig.output.dir, nitroContext.rollupConfig.output.entryFileNames as string)
|
|
}
|
|
}
|
|
|
|
function startRollupWatcher (nitroContext: NitroContext) {
|
|
const watcher = rollup.watch(nitroContext.rollupConfig)
|
|
let start: number
|
|
|
|
watcher.on('event', (event) => {
|
|
switch (event.code) {
|
|
// The watcher is (re)starting
|
|
case 'START':
|
|
return
|
|
|
|
// Building an individual bundle
|
|
case 'BUNDLE_START':
|
|
start = Date.now()
|
|
return
|
|
|
|
// Finished building all bundles
|
|
case 'END':
|
|
nitroContext._internal.hooks.callHook('nitro:compiled', nitroContext)
|
|
consola.success('Nitro built', start ? `in ${Date.now() - start} ms` : '')
|
|
return
|
|
|
|
// Encountered an error while bundling
|
|
case 'ERROR':
|
|
consola.error('Rollup error: ' + event.error)
|
|
// consola.error(event.error)
|
|
}
|
|
})
|
|
return watcher
|
|
}
|
|
|
|
async function _watch (nitroContext: NitroContext) {
|
|
let watcher = startRollupWatcher(nitroContext)
|
|
|
|
nitroContext.scannedMiddleware = await scanMiddleware(nitroContext._nuxt.serverDir,
|
|
(middleware, event) => {
|
|
nitroContext.scannedMiddleware = middleware
|
|
if (['add', 'addDir'].includes(event)) {
|
|
watcher.close()
|
|
writeTypes(nitroContext).catch(console.error)
|
|
watcher = startRollupWatcher(nitroContext)
|
|
}
|
|
}
|
|
)
|
|
await writeTypes(nitroContext)
|
|
}
|