fix(nuxt): compile plugin templates last (#27009)

This commit is contained in:
Daniel Roe 2024-05-01 06:43:35 +01:00 committed by GitHub
parent 54a9914ee6
commit 933c0aa71f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 61 additions and 41 deletions

View File

@ -20,6 +20,12 @@ export function createApp (nuxt: Nuxt, options: Partial<NuxtApp> = {}): NuxtApp
} as unknown as NuxtApp) as NuxtApp
}
const postTemplates = [
defaultTemplates.clientPluginTemplate.filename,
defaultTemplates.serverPluginTemplate.filename,
defaultTemplates.pluginsDeclaration.filename,
]
export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?: (template: ResolvedNuxtTemplate<any>) => boolean } = {}) {
// Resolve app
await resolveApp(nuxt, app)
@ -33,60 +39,74 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?:
// Normalize templates
app.templates = app.templates.map(tmpl => normalizeTemplate(tmpl))
// compile plugins first as they are needed within the nuxt.vfs
// in order to annotate templated plugins
const filteredTemplates: Record<'pre' | 'post', Array<ResolvedNuxtTemplate<any>>> = {
pre: [],
post: [],
}
for (const template of app.templates as Array<ResolvedNuxtTemplate<any>>) {
if (options.filter && !options.filter(template)) { continue }
const key = template.filename && postTemplates.includes(template.filename) ? 'post' : 'pre'
filteredTemplates[key].push(template)
}
// Compile templates into vfs
// TODO: remove utils in v4
const templateContext = { utils: templateUtils, nuxt, app }
const filteredTemplates = (app.templates as Array<ResolvedNuxtTemplate<any>>)
.filter(template => !options.filter || options.filter(template))
const compileTemplate = nuxt.options.experimental.compileTemplate ? _compileTemplate : futureCompileTemplate
const writes: Array<() => void> = []
await Promise.allSettled(filteredTemplates
.map(async (template) => {
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
const mark = performance.mark(fullPath)
const oldContents = nuxt.vfs[fullPath]
const contents = await compileTemplate(template, templateContext).catch((e) => {
logger.error(`Could not compile template \`${template.filename}\`.`)
logger.error(e)
throw e
const changedTemplates: Array<ResolvedNuxtTemplate<any>> = []
async function processTemplate (template: ResolvedNuxtTemplate) {
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
const mark = performance.mark(fullPath)
const oldContents = nuxt.vfs[fullPath]
const contents = await compileTemplate(template, templateContext).catch((e) => {
logger.error(`Could not compile template \`${template.filename}\`.`)
logger.error(e)
throw e
})
template.modified = oldContents !== contents
if (template.modified) {
nuxt.vfs[fullPath] = contents
const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '')
nuxt.vfs[aliasPath] = contents
// In case a non-normalized absolute path is called for on Windows
if (process.platform === 'win32') {
nuxt.vfs[fullPath.replace(/\//g, '\\')] = contents
}
changedTemplates.push(template)
}
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) {
logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`)
}
if (template.modified && template.write) {
writes.push(() => {
mkdirSync(dirname(fullPath), { recursive: true })
writeFileSync(fullPath, contents, 'utf8')
})
}
}
template.modified = oldContents !== contents
if (template.modified) {
nuxt.vfs[fullPath] = contents
const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '')
nuxt.vfs[aliasPath] = contents
// In case a non-normalized absolute path is called for on Windows
if (process.platform === 'win32') {
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) {
logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`)
}
if (template.modified && template.write) {
writes.push(() => {
mkdirSync(dirname(fullPath), { recursive: true })
writeFileSync(fullPath, contents, 'utf8')
})
}
}))
await Promise.allSettled(filteredTemplates.pre.map(processTemplate))
await Promise.allSettled(filteredTemplates.post.map(processTemplate))
// 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() }
const changedTemplates = filteredTemplates.filter(t => t.modified)
if (changedTemplates.length) {
await nuxt.callHook('app:templatesGenerated', app, changedTemplates, options)
}