mirror of
https://github.com/nuxt/nuxt.git
synced 2025-03-21 16:55:57 +00:00
feat(kit,nuxt): resolve template imports from originating module (#31175)
This commit is contained in:
parent
156ab7c93c
commit
0b6c698e55
@ -1,5 +1,6 @@
|
|||||||
import { existsSync, promises as fsp } from 'node:fs'
|
import { existsSync, promises as fsp } from 'node:fs'
|
||||||
import { basename, isAbsolute, join, parse, relative, resolve } from 'pathe'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { basename, isAbsolute, join, normalize, parse, relative, resolve } from 'pathe'
|
||||||
import { hash } from 'ohash'
|
import { hash } from 'ohash'
|
||||||
import type { Nuxt, NuxtServerTemplate, NuxtTemplate, NuxtTypeTemplate, ResolvedNuxtTemplate, TSReference } from '@nuxt/schema'
|
import type { Nuxt, NuxtServerTemplate, NuxtTemplate, NuxtTypeTemplate, ResolvedNuxtTemplate, TSReference } from '@nuxt/schema'
|
||||||
import { withTrailingSlash } from 'ufo'
|
import { withTrailingSlash } from 'ufo'
|
||||||
@ -8,8 +9,9 @@ import type { TSConfig } from 'pkg-types'
|
|||||||
import { gte } from 'semver'
|
import { gte } from 'semver'
|
||||||
import { readPackageJSON } from 'pkg-types'
|
import { readPackageJSON } from 'pkg-types'
|
||||||
import { resolveModulePath } from 'exsolve'
|
import { resolveModulePath } from 'exsolve'
|
||||||
|
import { captureStackTrace } from 'errx'
|
||||||
|
|
||||||
import { filterInPlace } from './utils'
|
import { distDirURL, filterInPlace } from './utils'
|
||||||
import { directoryToURL } from './internal/esm'
|
import { directoryToURL } from './internal/esm'
|
||||||
import { getDirectory } from './module/install'
|
import { getDirectory } from './module/install'
|
||||||
import { tryUseNuxt, useNuxt } from './context'
|
import { tryUseNuxt, useNuxt } from './context'
|
||||||
@ -27,6 +29,19 @@ export function addTemplate<T> (_template: NuxtTemplate<T> | string) {
|
|||||||
// Remove any existing template with the same destination path
|
// Remove any existing template with the same destination path
|
||||||
filterInPlace(nuxt.options.build.templates, p => normalizeTemplate(p).dst !== template.dst)
|
filterInPlace(nuxt.options.build.templates, p => normalizeTemplate(p).dst !== template.dst)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const distDir = distDirURL.toString()
|
||||||
|
const { source } = captureStackTrace().find(e => e.source && !e.source.startsWith(distDir)) ?? {}
|
||||||
|
if (source) {
|
||||||
|
const path = normalize(fileURLToPath(source))
|
||||||
|
if (existsSync(path)) {
|
||||||
|
template._path = path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore errors as this is an additive feature
|
||||||
|
}
|
||||||
|
|
||||||
// Add to templates array
|
// Add to templates array
|
||||||
nuxt.options.build.templates.push(template)
|
nuxt.options.build.templates.push(template)
|
||||||
|
|
||||||
|
@ -19,3 +19,5 @@ export function filterInPlace<T> (array: T[], predicate: (item: T, index: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MODE_RE = /\.(server|client)(\.\w+)*$/
|
export const MODE_RE = /\.(server|client)(\.\w+)*$/
|
||||||
|
|
||||||
|
export const distDirURL = new URL('.', import.meta.url)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { parseNodeModulePath } from 'mlly'
|
import { parseNodeModulePath } from 'mlly'
|
||||||
import { resolveModulePath } from 'exsolve'
|
import { resolveModulePath } from 'exsolve'
|
||||||
import { isAbsolute, normalize } from 'pathe'
|
import { isAbsolute, normalize, resolve } from 'pathe'
|
||||||
import type { Plugin } from 'vite'
|
import type { Plugin } from 'vite'
|
||||||
import { directoryToURL, resolveAlias } from '@nuxt/kit'
|
import { directoryToURL, resolveAlias } from '@nuxt/kit'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
@ -8,6 +8,8 @@ import type { Nuxt } from '@nuxt/schema'
|
|||||||
import { pkgDir } from '../../dirs'
|
import { pkgDir } from '../../dirs'
|
||||||
import { logger } from '../../utils'
|
import { logger } from '../../utils'
|
||||||
|
|
||||||
|
const VIRTUAL_RE = /^\0?virtual:(?:nuxt:)?/
|
||||||
|
|
||||||
export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
|
export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
|
||||||
const exclude: string[] = ['virtual:', '\0virtual:', '/__skip_vite', '@vitest/']
|
const exclude: string[] = ['virtual:', '\0virtual:', '/__skip_vite', '@vitest/']
|
||||||
let conditions: string[]
|
let conditions: string[]
|
||||||
@ -29,12 +31,24 @@ export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
|
|||||||
conditions = [...resolvedConditions]
|
conditions = [...resolvedConditions]
|
||||||
},
|
},
|
||||||
async resolveId (id, importer) {
|
async resolveId (id, importer) {
|
||||||
if (!importer || isAbsolute(id) || (!isAbsolute(importer) && !importer.startsWith('virtual:') && !importer.startsWith('\0virtual:')) || exclude.some(e => id.startsWith(e))) {
|
if (!importer || isAbsolute(id) || (!isAbsolute(importer) && !VIRTUAL_RE.test(importer)) || exclude.some(e => id.startsWith(e))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalisedId = resolveAlias(normalize(id), nuxt.options.alias)
|
const normalisedId = resolveAlias(normalize(id), nuxt.options.alias)
|
||||||
const normalisedImporter = importer.replace(/^\0?virtual:(?:nuxt:)?/, '')
|
const isNuxtTemplate = importer.startsWith('virtual:nuxt')
|
||||||
|
const normalisedImporter = (isNuxtTemplate ? decodeURIComponent(importer) : importer).replace(VIRTUAL_RE, '')
|
||||||
|
|
||||||
|
if (nuxt.options.experimental.templateImportResolution !== false && isNuxtTemplate) {
|
||||||
|
const template = nuxt.options.build.templates.find(t => resolve(nuxt.options.buildDir, t.filename!) === normalisedImporter)
|
||||||
|
if (template?._path) {
|
||||||
|
const res = await this.resolve?.(normalisedId, template._path, { skipSelf: true })
|
||||||
|
if (res !== undefined && res !== null) {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dir = parseNodeModulePath(normalisedImporter).dir || pkgDir
|
const dir = parseNodeModulePath(normalisedImporter).dir || pkgDir
|
||||||
|
|
||||||
const res = await this.resolve?.(normalisedId, dir, { skipSelf: true })
|
const res = await this.resolve?.(normalisedId, dir, { skipSelf: true })
|
||||||
|
@ -646,5 +646,10 @@ export default defineResolvers({
|
|||||||
return typeof val === 'boolean' ? val : true
|
return typeof val === 'boolean' ? val : true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable resolving imports into Nuxt templates from the path of the module that added the template.
|
||||||
|
*/
|
||||||
|
templateImportResolution: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -43,6 +43,11 @@ export interface NuxtTemplate<Options = TemplateDefaultOptions> {
|
|||||||
getContents?: (data: { nuxt: Nuxt, app: NuxtApp, options: Options }) => string | Promise<string>
|
getContents?: (data: { nuxt: Nuxt, app: NuxtApp, options: Options }) => string | Promise<string>
|
||||||
/** Write to filesystem */
|
/** Write to filesystem */
|
||||||
write?: boolean
|
write?: boolean
|
||||||
|
/**
|
||||||
|
* The source path of the template (to try resolving dependencies from).
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
_path?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NuxtServerTemplate {
|
export interface NuxtServerTemplate {
|
||||||
|
Loading…
Reference in New Issue
Block a user