diff --git a/packages/kit/src/internal/template.ts b/packages/kit/src/internal/template.ts index 00feb2bdae..8672429638 100644 --- a/packages/kit/src/internal/template.ts +++ b/packages/kit/src/internal/template.ts @@ -6,6 +6,7 @@ import { genDynamicImport, genImport, genSafeVariableName } from 'knitwork' import type { NuxtTemplate } from '@nuxt/schema' /** @deprecated */ +// TODO: Remove support for compiling ejs templates in v4 export async function compileTemplate (template: NuxtTemplate, ctx: any) { const data = { ...ctx, options: template.options } if (template.src) { diff --git a/packages/nuxt/src/core/app.ts b/packages/nuxt/src/core/app.ts index 565e5e2959..523f1d7d5a 100644 --- a/packages/nuxt/src/core/app.ts +++ b/packages/nuxt/src/core/app.ts @@ -1,4 +1,4 @@ -import { promises as fsp } from 'node:fs' +import { promises as fsp, mkdirSync, writeFileSync } from 'node:fs' import { dirname, join, resolve } from 'pathe' import { defu } from 'defu' import { compileTemplate, findPath, normalizePlugin, normalizeTemplate, resolveAlias, resolveFiles, resolvePath, templateUtils, tryResolveModule } from '@nuxt/kit' @@ -32,15 +32,21 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?: app.templates = app.templates.map(tmpl => normalizeTemplate(tmpl)) // Compile templates into vfs + // TODO: remove utils in v4 const templateContext = { utils: templateUtils, nuxt, app } const filteredTemplates = (app.templates as Array>) .filter(template => !options.filter || options.filter(template)) - await Promise.all(filteredTemplates + const writes: Array<() => void> = [] + await Promise.allSettled(filteredTemplates .map(async (template) => { - const contents = await compileTemplate(template, templateContext) - const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!) + const mark = performance.mark(fullPath) + const contents = await compileTemplate(template, templateContext).catch((e) => { + console.error(`[nuxt] Could not compile template \`${template.filename}\`.`) + throw e + }) + nuxt.vfs[fullPath] = contents const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '') @@ -51,12 +57,25 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?: nuxt.vfs[fullPath.replace(/\//g, '\\')] = contents } + const perf = performance.measure(fullPath, mark?.name) // TODO: remove when Node 14 reaches EOL + const setupTime = perf ? Math.round((perf.duration * 100)) / 100 : 0 // TODO: remove when Node 14 reaches EOL + + if (nuxt.options.debug || setupTime > 500) { + console.info(`[nuxt] compiled \`${template.filename}\` in ${setupTime}ms`) + } + if (template.write) { - await fsp.mkdir(dirname(fullPath), { recursive: true }) - await fsp.writeFile(fullPath, contents, 'utf8') + writes.push(() => { + mkdirSync(dirname(fullPath), { recursive: true }) + writeFileSync(fullPath, contents, 'utf8') + }) } })) + // Write template files in single synchronous step to avoid (possible) additional + // runtime overhead of cascading HMRs from vite/webpack + for (const write of writes) { write() } + await nuxt.callHook('app:templatesGenerated', app, filteredTemplates, options) }