diff --git a/packages/vite/package.json b/packages/vite/package.json index c8683d5821..68a333de5e 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -41,7 +41,6 @@ "defu": "^6.1.4", "esbuild": "^0.25.0", "escape-string-regexp": "^5.0.0", - "externality": "^1.0.2", "get-port-please": "^3.1.2", "h3": "npm:h3-nightly@1.14.0-20250122-114730-3f9e703", "jiti": "^2.4.2", diff --git a/packages/vite/src/runtime/vite-node.mjs b/packages/vite/src/runtime/vite-node.mjs index bc2da0c41d..59a54ab182 100644 --- a/packages/vite/src/runtime/vite-node.mjs +++ b/packages/vite/src/runtime/vite-node.mjs @@ -39,6 +39,9 @@ function createRunner () { return new ViteNodeRunner({ root: viteNodeOptions.root, // Equals to Nuxt `srcDir` base: viteNodeOptions.base, + async resolveId (id, importer) { + return await viteNodeFetch('/resolve/' + encodeURIComponent(id) + (importer ? '?importer=' + encodeURIComponent(importer) : '')) ?? undefined + }, async fetchModule (id) { id = id.replace(/\/\//g, '/') // TODO: fix in vite-node return await viteNodeFetch('/module/' + encodeURI(id)).catch((err) => { diff --git a/packages/vite/src/utils/external.ts b/packages/vite/src/utils/external.ts deleted file mode 100644 index c6889cb3a1..0000000000 --- a/packages/vite/src/utils/external.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { ExternalsOptions } from 'externality' -import { ExternalsDefaults, isExternal } from 'externality' -import type { ViteDevServer } from 'vite' -import escapeStringRegexp from 'escape-string-regexp' -import { withTrailingSlash } from 'ufo' -import type { Nuxt } from 'nuxt/schema' -import { resolve } from 'pathe' -import { toArray } from '.' - -export function createIsExternal (viteServer: ViteDevServer, nuxt: Nuxt) { - const externalOpts: ExternalsOptions = { - inline: [ - /virtual:/, - /\.ts$/, - ...ExternalsDefaults.inline || [], - ...( - viteServer.config.ssr.noExternal && viteServer.config.ssr.noExternal !== true - ? toArray(viteServer.config.ssr.noExternal) - : [] - ), - ], - external: [ - '#shared', - new RegExp('^' + escapeStringRegexp(withTrailingSlash(resolve(nuxt.options.rootDir, nuxt.options.dir.shared)))), - ...(viteServer.config.ssr.external as string[]) || [], - /node_modules/, - ], - resolve: { - modules: nuxt.options.modulesDir, - type: 'module', - extensions: ['.ts', '.js', '.json', '.vue', '.mjs', '.jsx', '.tsx', '.wasm'], - }, - } - - return (id: string) => isExternal(id, nuxt.options.rootDir, externalOpts) -} diff --git a/packages/vite/src/vite-node.ts b/packages/vite/src/vite-node.ts index 9d0892f139..1f18dd3672 100644 --- a/packages/vite/src/vite-node.ts +++ b/packages/vite/src/vite-node.ts @@ -1,18 +1,16 @@ import { mkdir, writeFile } from 'node:fs/promises' import { pathToFileURL } from 'node:url' -import { createApp, createError, defineEventHandler, defineLazyEventHandler, eventHandler, toNodeListener } from 'h3' +import { createApp, createError, defineEventHandler, toNodeListener } from 'h3' import { ViteNodeServer } from 'vite-node/server' import { isAbsolute, join, normalize, resolve } from 'pathe' // import { addDevServerHandler } from '@nuxt/kit' import { isFileServingAllowed } from 'vite' -import type { ModuleNode, Plugin as VitePlugin } from 'vite' +import type { ModuleNode, ViteDevServer, Plugin as VitePlugin } from 'vite' import { getQuery } from 'ufo' import { normalizeViteManifest } from 'vue-bundle-renderer' -import { resolve as resolveModule } from 'mlly' import { distDir } from './dirs' import type { ViteBuildContext } from './vite' import { isCSS } from './utils' -import { createIsExternal } from './utils/external' // TODO: Remove this in favor of registerViteNodeMiddleware // after Nitropack or h3 allows adding middleware after setup @@ -101,6 +99,19 @@ function getManifest (ctx: ViteBuildContext) { function createViteNodeApp (ctx: ViteBuildContext, invalidates: Set = new Set()) { const app = createApp() + let _node: ViteNodeServer | undefined + function getNode (server: ViteDevServer) { + return _node ||= new ViteNodeServer(server, { + deps: { + inline: [/^#/, /\?/], + }, + transformMode: { + ssr: [/.*/], + web: [], + }, + }) + } + app.use('/manifest', defineEventHandler(() => { const manifest = getManifest(ctx) return manifest @@ -112,54 +123,38 @@ function createViteNodeApp (ctx: ViteBuildContext, invalidates: Set = ne return ids })) - app.use('/module', defineLazyEventHandler(() => { - const viteServer = ctx.ssrServer! - const node = new ViteNodeServer(viteServer, { - deps: { - inline: [ - // Common - /^#/, - /\?/, - ], - }, - transformMode: { - ssr: [/.*/], - web: [], - }, - }) - - const isExternal = createIsExternal(viteServer, ctx.nuxt) - node.shouldExternalize = async (id: string) => { - const result = await isExternal(id) - if (result?.external) { - return resolveModule(result.id, { url: ctx.nuxt.options.modulesDir }).catch(() => false) - } - return false + const RESOLVE_RE = /^\/(?[^?]+)(?:\?importer=(?.*))?$/ + app.use('/resolve', defineEventHandler(async (event) => { + const { id, importer } = event.path.match(RESOLVE_RE)?.groups || {} + if (!id || !ctx.ssrServer) { + throw createError({ statusCode: 400 }) } + return await getNode(ctx.ssrServer).resolveId(decodeURIComponent(id), importer ? decodeURIComponent(importer) : undefined).catch(() => null) + })) - return eventHandler(async (event) => { - const moduleId = decodeURI(event.path).substring(1) - if (moduleId === '/') { - throw createError({ statusCode: 400 }) + app.use('/module', defineEventHandler(async (event) => { + const moduleId = decodeURI(event.path).substring(1) + if (moduleId === '/' || !ctx.ssrServer) { + throw createError({ statusCode: 400 }) + } + if (isAbsolute(moduleId) && !isFileServingAllowed(ctx.ssrServer.config, moduleId)) { + throw createError({ statusCode: 403 /* Restricted */ }) + } + const node = getNode(ctx.ssrServer) + const module = await node.fetchModule(moduleId).catch(async (err) => { + const errorData = { + code: 'VITE_ERROR', + id: moduleId, + stack: '', + ...err, } - if (isAbsolute(moduleId) && !isFileServingAllowed(moduleId, viteServer)) { - throw createError({ statusCode: 403 /* Restricted */ }) - } - const module = await node.fetchModule(moduleId).catch(async (err) => { - const errorData = { - code: 'VITE_ERROR', - id: moduleId, - stack: '', - ...err, - } - if (!errorData.frame && errorData.code === 'PARSE_ERROR') { - errorData.frame = await node.transformModule(moduleId, 'web').then(({ code }) => `${err.message || ''}\n${code}`).catch(() => undefined) - } - throw createError({ data: errorData }) - }) - return module + if (!errorData.frame && errorData.code === 'PARSE_ERROR') { + errorData.frame = await node.transformModule(moduleId, 'web').then(({ code }) => `${err.message || ''}\n${code}`).catch(() => undefined) + } + throw createError({ data: errorData }) }) + return module })) return app diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a4d9da1cd..4d7038e633 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -891,9 +891,6 @@ importers: escape-string-regexp: specifier: ^5.0.0 version: 5.0.0 - externality: - specifier: ^1.0.2 - version: 1.0.2 get-port-please: specifier: ^3.1.2 version: 3.1.2 @@ -4580,9 +4577,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - externality@1.0.2: - resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} - fake-indexeddb@6.0.0: resolution: {integrity: sha512-YEboHE5VfopUclOck7LncgIqskAqnv4q0EWbYCaxKKjAvO93c+TJIaBuGy8CBFdbg9nKdpN3AuPRwVBJ4k7NrQ==} engines: {node: '>=18'} @@ -11933,13 +11927,6 @@ snapshots: extend@3.0.2: {} - externality@1.0.2: - dependencies: - enhanced-resolve: 5.18.0 - mlly: 1.7.4 - pathe: 1.1.2 - ufo: 1.5.4 - fake-indexeddb@6.0.0: {} fast-deep-equal@3.1.3: {}