refactor(kit,nuxi): resolve module paths using node algorithm (#19537)

This commit is contained in:
Daniel Roe 2023-03-10 14:55:01 +00:00 committed by GitHub
parent f7a5cf07b5
commit 6d79b71588
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 76 additions and 40 deletions

View File

@ -24,5 +24,13 @@ export * from './logger'
// Internal Utils
// TODO
export * from './internal/cjs'
export {
resolveModule,
requireModule,
importModule,
tryImportModule,
tryRequireModule
} from './internal/cjs'
export type { ResolveModuleOptions, RequireModuleOptions } from './internal/cjs'
export { tryResolveModule } from './internal/esm'
export * from './internal/template'

View File

@ -1,5 +1,5 @@
import { pathToFileURL } from 'node:url'
import { join, normalize } from 'pathe'
import { normalize } from 'pathe'
import { interopDefault } from 'mlly'
import jiti from 'jiti'
@ -82,11 +82,6 @@ export function getRequireCacheItem (id: string) {
}
}
/** Resolve the `package.json` file for a given module. */
export function requireModulePkg (id: string, opts: RequireModuleOptions = {}) {
return requireModule(join(id, 'package.json'), opts)
}
/** @deprecated Do not use CJS utils */
export function resolveModule (id: string, opts: ResolveModuleOptions = {}) {
return normalize(_require.resolve(id, {

View File

@ -0,0 +1,25 @@
import { pathToFileURL } from 'node:url'
import { interopDefault, resolvePath } from 'mlly'
/**
* Resolve a module from a given root path using an algorithm patterned on
* the upcoming `import.meta.resolve`. It returns a file URL
*
* @internal
*/
export async function tryResolveModule (id: string, url = import.meta.url) {
try {
return await resolvePath(id, { url })
} catch { }
}
export async function importModule (id: string, url = import.meta.url) {
const resolvedPath = await resolvePath(id, { url })
return import(pathToFileURL(resolvedPath).href).then(interopDefault)
}
export function tryImportModule (id: string, url = import.meta.url) {
try {
return importModule(id, url).catch(() => undefined)
} catch { }
}

View File

@ -1,7 +1,7 @@
import { pathToFileURL } from 'node:url'
import { readPackageJSON, resolvePackageJSON } from 'pkg-types'
import type { Nuxt } from '@nuxt/schema'
import type { RequireModuleOptions } from '../internal/cjs'
import { importModule, tryImportModule } from '../internal/cjs'
import { importModule, tryImportModule } from '../internal/esm'
import type { LoadNuxtConfigOptions } from './config'
export interface LoadNuxtOptions extends LoadNuxtConfigOptions {
@ -23,8 +23,6 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
opts.cwd = opts.cwd || opts.rootDir
opts.overrides = opts.overrides || opts.config || {}
const resolveOpts: RequireModuleOptions = { paths: opts.cwd }
// Apply dev as config override
opts.overrides.dev = !!opts.dev
@ -37,15 +35,17 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
const pkg = await readPackageJSON(nearestNuxtPkg)
const majorVersion = parseInt((pkg.version || '').split('.')[0])
const rootDir = pathToFileURL(opts.cwd || process.cwd()).href
// Nuxt 3
if (majorVersion === 3) {
const { loadNuxt } = await importModule((pkg as any)._name || pkg.name, resolveOpts)
const { loadNuxt } = await importModule((pkg as any)._name || pkg.name, rootDir)
const nuxt = await loadNuxt(opts)
return nuxt
}
// Nuxt 2
const { loadNuxt } = await tryImportModule('nuxt-edge', resolveOpts) || await importModule('nuxt', resolveOpts)
const { loadNuxt } = await tryImportModule('nuxt-edge', rootDir) || await importModule('nuxt', rootDir)
const nuxt = await loadNuxt({
rootDir: opts.cwd,
for: opts.dev ? 'dev' : 'build',
@ -58,15 +58,15 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
}
export async function buildNuxt (nuxt: Nuxt): Promise<any> {
const resolveOpts: RequireModuleOptions = { paths: nuxt.options.rootDir }
const rootDir = pathToFileURL(nuxt.options.rootDir).href
// Nuxt 3
if (nuxt.options._majorVersion === 3) {
const { build } = await tryImportModule('nuxt3', resolveOpts) || await importModule('nuxt', resolveOpts)
const { build } = await tryImportModule('nuxt3', rootDir) || await importModule('nuxt', rootDir)
return build(nuxt)
}
// Nuxt 2
const { build } = await tryImportModule('nuxt-edge', resolveOpts) || await importModule('nuxt', resolveOpts)
const { build } = await tryImportModule('nuxt-edge', rootDir) || await importModule('nuxt', rootDir)
return build(nuxt)
}

View File

@ -1,6 +1,7 @@
import type { Nuxt, NuxtModule } from '@nuxt/schema'
import { useNuxt } from '../context'
import { resolveModule, requireModule, importModule } from '../internal/cjs'
import { resolveModule, requireModule } from '../internal/cjs'
import { importModule } from '../internal/esm'
import { resolveAlias } from '../resolve'
/** Installs a module on a Nuxt instance. */
@ -38,7 +39,7 @@ async function normalizeModule (nuxtModule: string | NuxtModule, inlineOptions?:
const isESM = _src.endsWith('.mjs')
try {
nuxtModule = isESM ? await importModule(_src) : requireModule(_src)
nuxtModule = isESM ? await importModule(_src, nuxt.options.rootDir) : requireModule(_src)
} catch (error: unknown) {
console.error(`Error while requiring module \`${nuxtModule}\`: ${error}`)
throw error

View File

@ -1,7 +1,7 @@
import { execa } from 'execa'
import consola from 'consola'
import { resolve } from 'pathe'
import { tryResolveModule } from '../utils/cjs'
import { tryResolveModule } from '../utils/esm'
import { defineNuxtCommand } from './index'
const MODULE_BUILDER_PKG = '@nuxt/module-builder'
@ -15,7 +15,7 @@ export default defineNuxtCommand({
async invoke (args) {
// Find local installed version
const rootDir = resolve(args._[0] || '.')
const hasLocal = tryResolveModule(`${MODULE_BUILDER_PKG}/package.json`, rootDir)
const hasLocal = await tryResolveModule(`${MODULE_BUILDER_PKG}/package.json`, rootDir)
const execArgs = Object.entries({
'--stub': args.stub

View File

@ -10,7 +10,7 @@ import { setupDotenv } from 'c12'
import { showBanner, showVersions } from '../utils/banner'
import { writeTypes } from '../utils/prepare'
import { loadKit } from '../utils/kit'
import { importModule } from '../utils/cjs'
import { importModule } from '../utils/esm'
import { overrideEnv } from '../utils/env'
import { writeNuxtManifest, loadNuxtManifest, cleanupNuxtDirs } from '../utils/nuxt'
import { defineNuxtCommand } from './index'

View File

@ -1,6 +1,6 @@
import { execa } from 'execa'
import { resolve } from 'pathe'
import { tryResolveModule } from '../utils/cjs'
import { tryResolveModule } from '../utils/esm'
import { loadKit } from '../utils/kit'
import { writeTypes } from '../utils/prepare'
@ -31,7 +31,7 @@ export default defineNuxtCommand({
await nuxt.close()
// Prefer local install if possible
const hasLocalInstall = tryResolveModule('typescript', rootDir) && tryResolveModule('vue-tsc/package.json', rootDir)
const hasLocalInstall = await tryResolveModule('typescript', rootDir) && await tryResolveModule('vue-tsc/package.json', rootDir)
if (hasLocalInstall) {
await execa('vue-tsc', ['--noEmit'], { preferLocal: true, stdio: 'inherit', cwd: rootDir })
} else {

View File

@ -1,5 +1,4 @@
import { createRequire } from 'node:module'
import { pathToFileURL } from 'node:url'
import { normalize, dirname } from 'pathe'
export function getModulePaths (paths?: string | string[]): string[] {
@ -21,12 +20,6 @@ export function resolveModule (id: string, paths?: string | string[]) {
return normalize(_require.resolve(id, { paths: getModulePaths(paths) }))
}
export function tryResolveModule (id: string, paths?: string | string[]) {
try {
return resolveModule(id, paths)
} catch { return null }
}
export function requireModule (id: string, paths?: string | string[]) {
return _require(resolveModule(id, paths))
}
@ -35,11 +28,6 @@ export function tryRequireModule (id: string, paths?: string | string[]) {
try { return requireModule(id, paths) } catch { return null }
}
export function importModule (id: string, paths?: string | string[]) {
const resolvedPath = resolveModule(id, paths)
return import(pathToFileURL(resolvedPath).href)
}
export function getNearestPackage (id: string, paths?: string | string[]) {
while (dirname(id) !== id) {
try { return requireModule(id + '/package.json', paths) } catch { }

View File

@ -0,0 +1,19 @@
import { pathToFileURL } from 'node:url'
import { interopDefault, resolvePath } from 'mlly'
export async function tryResolveModule (id: string, url = import.meta.url) {
try {
return await resolvePath(id, { url })
} catch { }
}
export async function importModule (id: string, url = import.meta.url) {
const resolvedPath = await resolvePath(id, { url })
return import(pathToFileURL(resolvedPath).href).then(interopDefault)
}
export function tryImportModule (id: string, url = import.meta.url) {
try {
return importModule(id, url).catch(() => undefined)
} catch { }
}

View File

@ -1,4 +1,4 @@
import { importModule } from './cjs'
import { importModule } from './esm'
export const loadKit = async (rootDir: string): Promise<typeof import('@nuxt/kit')> => {
try {

View File

@ -67,7 +67,7 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
)
}
if (!app.mainComponent) {
app.mainComponent = tryResolveModule('@nuxt/ui-templates/templates/welcome.vue')
app.mainComponent = (await tryResolveModule('@nuxt/ui-templates/templates/welcome.vue'))!
}
// Resolve root component

View File

@ -165,7 +165,7 @@ async function initNuxt (nuxt: Nuxt) {
addComponent({
name: 'NuxtWelcome',
priority: 10, // built-in that we do not expect the user to override
filePath: tryResolveModule('@nuxt/ui-templates/templates/welcome.vue')!
filePath: (await tryResolveModule('@nuxt/ui-templates/templates/welcome.vue'))!
})
addComponent({

View File

@ -8,7 +8,7 @@ export default defineNuxtModule({
meta: {
name: 'head'
},
setup (options, nuxt) {
async setup (options, nuxt) {
const runtimeDir = resolve(distDir, 'head/runtime')
// Transpile @unhead/vue
@ -53,7 +53,7 @@ export default defineNuxtModule({
// Opt-out feature allowing dependencies using @vueuse/head to work
if (nuxt.options.experimental.polyfillVueUseHead) {
// backwards compatibility
nuxt.options.alias['@vueuse/head'] = tryResolveModule('@unhead/vue') || '@unhead/vue'
nuxt.options.alias['@vueuse/head'] = await tryResolveModule('@unhead/vue') || '@unhead/vue'
addPlugin({ src: resolve(runtimeDir, 'plugins/vueuse-head-polyfill') })
}