feat(kit): reimplement cjs utils using `mlly` (#28012)

This commit is contained in:
Daniel Roe 2024-07-03 23:02:05 +01:00 committed by GitHub
parent e0d8ab3e69
commit ef35ff27df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 32 additions and 27 deletions

View File

@ -517,10 +517,7 @@ These options have been set to their current values for some time and we do not
We have now removed the following utils exported from `@nuxt/kit`:
* `resolveModule`
* `requireModule`
* `importModule`
* `tryImportModule`
* `tryRequireModule`
They were previously marked as deprecated and relied on CJS resolutions.

View File

@ -32,4 +32,5 @@ export { addTemplate, addTypeTemplate, normalizeTemplate, updateTemplates, write
export { logger, useLogger } from './logger'
// Internal Utils
export { tryResolveModule } from './internal/esm'
export { resolveModule, tryResolveModule, importModule, tryImportModule } from './internal/esm'
export type { ImportModuleOptions, ResolveModuleOptions } from './internal/esm'

View File

@ -1,6 +1,10 @@
import { pathToFileURL } from 'node:url'
import { interopDefault, resolvePath } from 'mlly'
export interface ResolveModuleOptions {
paths?: string | string[]
}
/**
* Resolve a module from a given root path using an algorithm patterned on
* the upcoming `import.meta.resolve`. It returns a file URL
@ -15,14 +19,23 @@ export async function tryResolveModule (id: string, url: string | string[] = imp
}
}
export async function importModule (id: string, url: string | string[] = import.meta.url) {
const resolvedPath = await resolvePath(id, { url })
return import(pathToFileURL(resolvedPath).href).then(interopDefault)
export async function resolveModule (id: string, options?: ResolveModuleOptions) {
return await resolvePath(id, { url: options?.paths ?? [import.meta.url] })
}
export function tryImportModule (id: string, url = import.meta.url) {
export interface ImportModuleOptions extends ResolveModuleOptions {
/** Automatically de-default the result of requiring the module. */
interopDefault?: boolean
}
export async function importModule<T = unknown> (id: string, opts?: ImportModuleOptions) {
const resolvedPath = await resolveModule(id, opts)
return import(pathToFileURL(resolvedPath).href).then(r => opts?.interopDefault !== false ? interopDefault(r) : r) as Promise<T>
}
export function tryImportModule<T = unknown> (id: string, opts?: ImportModuleOptions) {
try {
return importModule(id, url).catch(() => undefined)
return importModule<T>(id, opts).catch(() => undefined)
} catch {
// intentionally empty as this is a `try-` function
}

View File

@ -31,7 +31,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
const rootDir = pathToFileURL(opts.cwd!).href
const { loadNuxt } = await importModule((pkg as any)._name || pkg.name, rootDir)
const { loadNuxt } = await importModule<typeof import('nuxt')>((pkg as any)._name || pkg.name, { paths: rootDir })
const nuxt = await loadNuxt(opts)
return nuxt
}
@ -39,6 +39,6 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
export async function buildNuxt (nuxt: Nuxt): Promise<any> {
const rootDir = pathToFileURL(nuxt.options.rootDir).href
const { build } = await tryImportModule('nuxt-nightly', rootDir) || await importModule('nuxt', rootDir)
const { build } = await tryImportModule<typeof import('nuxt')>('nuxt-nightly', { paths: rootDir }) || await importModule<typeof import('nuxt')>('nuxt', { paths: rootDir })
return build(nuxt)
}

View File

@ -1,9 +1,7 @@
import { pathToFileURL } from 'node:url'
import type { EventType } from '@parcel/watcher'
import type { FSWatcher } from 'chokidar'
import { watch as chokidarWatch } from 'chokidar'
import { isIgnored, logger, tryResolveModule, useNuxt } from '@nuxt/kit'
import { interopDefault } from 'mlly'
import { importModule, isIgnored, logger, tryResolveModule, useNuxt } from '@nuxt/kit'
import { debounce } from 'perfect-debounce'
import { normalize, relative, resolve } from 'pathe'
import type { Nuxt, NuxtBuilder } from 'nuxt/schema'
@ -151,7 +149,7 @@ async function createParcelWatcher () {
return false
}
const { subscribe } = await import(pathToFileURL(watcherPath).href).then(interopDefault) as typeof import('@parcel/watcher')
const { subscribe } = await importModule<typeof import('@parcel/watcher')>(watcherPath)
for (const layer of nuxt.options._layers) {
if (!layer.config.srcDir) { continue }
const watcher = subscribe(layer.config.srcDir, (err, events) => {
@ -201,5 +199,5 @@ async function loadBuilder (nuxt: Nuxt, builder: string): Promise<NuxtBuilder> {
if (!builderPath) {
throw new Error(`Loading \`${builder}\` builder failed. You can read more about the nuxt \`builder\` option at: \`https://nuxt.com/docs/api/nuxt-config#builder\``)
}
return import(pathToFileURL(builderPath).href)
return importModule(builderPath)
}

View File

@ -1,12 +1,11 @@
import { existsSync } from 'node:fs'
import { mkdir, writeFile } from 'node:fs/promises'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { fileURLToPath } from 'node:url'
import { resolve } from 'pathe'
import { watch } from 'chokidar'
import { interopDefault } from 'mlly'
import { defu } from 'defu'
import { debounce } from 'perfect-debounce'
import { createResolver, defineNuxtModule, logger, tryResolveModule } from '@nuxt/kit'
import { createResolver, defineNuxtModule, importModule, logger, tryResolveModule } from '@nuxt/kit'
import {
generateTypes,
resolveSchema as resolveUntypedSchema,
@ -60,7 +59,7 @@ export default defineNuxtModule({
if (nuxt.options.experimental.watcher === 'parcel') {
const watcherPath = await tryResolveModule('@parcel/watcher', [nuxt.options.rootDir, ...nuxt.options.modulesDir])
if (watcherPath) {
const { subscribe } = await import(pathToFileURL(watcherPath).href).then(interopDefault) as typeof import('@parcel/watcher')
const { subscribe } = await importModule<typeof import('@parcel/watcher')>(watcherPath)
for (const layer of nuxt.options._layers) {
const subscription = await subscribe(layer.config.rootDir, onChange, {
ignore: ['!nuxt.schema.*'],

View File

@ -1,8 +1,8 @@
import { pathToFileURL } from 'node:url'
import { globby } from 'globby'
import { genSafeVariableName } from 'knitwork'
import { resolve } from 'pathe'
import type { Plugin } from 'rollup'
import { importModule } from '@nuxt/kit'
const PLUGIN_NAME = 'dynamic-require'
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.mjs`
@ -61,9 +61,8 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
let files = []
try {
const wpManifest = resolve(dir, './server.manifest.json')
files = await import(pathToFileURL(wpManifest).href).then(r =>
Object.keys(r.files).filter(file => !ignore.includes(file)),
)
files = await importModule<{ files: Record<string, unknown> }>(wpManifest)
.then(r => Object.keys(r.files).filter(file => !ignore.includes(file)))
} catch {
files = await globby('**/*.{cjs,mjs,js}', {
cwd: dir,
@ -89,9 +88,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
}
async function getWebpackChunkMeta (src: string) {
const chunk = await import(pathToFileURL(src).href).then(
r => r.default || r || {},
)
const chunk = await importModule<{ id: string, ids: string[], modules: Record<string, unknown> }>(src) || {}
const { id, ids, modules } = chunk
if (!id && !ids) {
return null // Not a webpack chunk