import { isBuiltin } from "node:module"; import fs, { existsSync, readFileSync } from "node:fs"; import { performance } from "node:perf_hooks"; import * as vite from "vite"; import { createBuilder, createLogger, createServer, isCSSRequest, mergeConfig } from "vite"; import { basename, dirname, isAbsolute, join, normalize, relative, resolve } from "pathe"; import { createIsIgnored, directoryToURL, getLayerDirectories, logger, resolveAlias, resolvePath, tryUseNuxt, useNitro, useNuxt } from "@nuxt/kit"; import { findStaticImports, parseNodeModulePath, sanitizeFilePath } from "mlly"; import viteJsxPlugin from "@vitejs/plugin-vue-jsx"; import vuePlugin from "@vitejs/plugin-vue"; import { getQuery, joinURL, parseQuery, parseURL, withLeadingSlash, withTrailingSlash, withoutBase, withoutLeadingSlash } from "ufo"; import { filename } from "pathe/utils"; import { resolveModulePath } from "exsolve"; import { fileURLToPath, pathToFileURL } from "node:url"; import MagicString from "magic-string"; import process from "node:process"; import { mkdir, readFile, rm, unlink, writeFile } from "node:fs/promises"; import net from "node:net"; import os from "node:os"; import { Buffer } from "node:buffer"; import { ViteNodeServer } from "vite-node/server"; import { normalizeViteManifest, precomputeDependencies } from "vue-bundle-renderer"; import { hasTTY, isCI, provider } from "std-env"; import { colorize } from "consola/utils"; import escapeStringRegexp from "escape-string-regexp"; import { transform } from "esbuild"; import { defu } from "defu"; import { getPort } from "get-port-please"; import { readTSConfig, resolveTSConfig } from "pkg-types"; import { serialize } from "seroval"; import { createJiti } from "jiti"; import { genArrayFromRaw, genImport, genObjectFromRawEntries } from "knitwork"; import replacePlugin from "@rollup/plugin-replace"; import { defineEnv } from "unenv"; function isVue(id, opts = {}) { const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href)); if (id.endsWith(".vue") && !search) return true; if (!search) return false; const query = parseQuery(search); if (query.nuxt_component) return false; if (query.macro && (search === "?macro=true" || !opts.type || opts.type.includes("script"))) return true; const type = "setup" in query ? "script" : query.type; if (!("vue" in query) || opts.type && !opts.type.includes(type)) return false; return true; } const IS_CSS_RE = /\.(?:css|scss|sass|postcss|pcss|less|stylus|styl)(?:\?[^.]+)?$/; function isCSS(file) { return IS_CSS_RE.test(file); } function toArray(value) { return Array.isArray(value) ? value : [value]; } function DevStyleSSRPlugin(options) { return { name: "nuxt:dev-style-ssr", apply: "serve", enforce: "post", applyToEnvironment: (environment) => environment.name === "client", transform(code, id) { if (!isCSS(id) || !code.includes("import.meta.hot")) return; let moduleId = id; if (moduleId.startsWith(options.srcDir)) moduleId = moduleId.slice(options.srcDir.length); return code + [joinURL(options.buildAssetsURL, moduleId), joinURL(options.buildAssetsURL, "@fs", moduleId)].map((selector) => `\ndocument.querySelectorAll(\`link[href="${selector}"]\`).forEach(i=>i.remove())`).join(""); } }; } const VITE_ASSET_RE = /__VITE_ASSET__|__VITE_PUBLIC_ASSET__/; function RuntimePathsPlugin() { let sourcemap; return { name: "nuxt:runtime-paths-dep", enforce: "post", applyToEnvironment: (environment) => environment.name === "client", configResolved(config) { sourcemap = !!config.build.sourcemap; }, transform(code, id) { const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)); if (isCSS(pathname)) return; if (pathname.endsWith(".vue")) { if (search && parseQuery(search).type === "style") return; } if (VITE_ASSET_RE.test(code)) { const s = new MagicString(code); s.prepend("import \"#internal/nuxt/paths\";"); return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } } }; } function resolveClientEntry(config) { const input = config.environments.client?.build.rollupOptions.input ?? config.build.rollupOptions.input; if (input) { if (typeof input === "string") return input; if (!Array.isArray(input) && input.entry) return input.entry; } throw new Error("No entry found in rollupOptions.input"); } function resolveServerEntry(config) { const input = config.environments.ssr?.build.rollupOptions.input ?? config.build.rollupOptions.input; if (input) { if (typeof input === "string") return input; if (!Array.isArray(input) && input.server) return input.server; } throw new Error("No entry found in rollupOptions.input"); } const QUERY_RE$2 = /\?.+$/; function TypeCheckPlugin(nuxt) { let entry; let sourcemap; return { name: "nuxt:type-check", applyToEnvironment: (environment) => environment.name === "client" && !environment.config.isProduction, apply: () => { return !nuxt.options.test && nuxt.options.typescript.typeCheck === true; }, configResolved(config) { try { entry = resolveClientEntry(config); sourcemap = !!config.build.sourcemap; } catch { console.debug("[nuxt:type-check] Could not resolve client entry, type checking will not be applied."); } }, transform(code, id) { if (id.replace(QUERY_RE$2, "") !== entry) return; const s = new MagicString(code); s.prepend("import \"/@vite-plugin-checker-runtime-entry\";\n"); return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } }; } const QUERY_RE$1 = /\?.+$/; function ModulePreloadPolyfillPlugin() { let isDisabled = false; let entry; let sourcemap; return { name: "nuxt:module-preload-polyfill", applyToEnvironment: (environment) => environment.name === "client", configResolved(config) { try { isDisabled = config.build.modulePreload === false || config.build.modulePreload.polyfill === false; sourcemap = !!config.build.sourcemap; entry = resolveClientEntry(config); } catch { console.debug("[nuxt:module-preload-polyfill] Could not resolve client entry, module preload polyfill will not be injected."); } }, transform(code, id) { if (isDisabled || id.replace(QUERY_RE$1, "") !== entry) return; const s = new MagicString(code); s.prepend("import \"vite/modulepreload-polyfill\";\n"); return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } }; } function getManifest(nuxt, viteServer, clientEntry) { const css = /* @__PURE__ */ new Set(); const ssrServer = nuxt.options.experimental.viteEnvironmentApi ? viteServer.environments.ssr : viteServer; for (const key of ssrServer.moduleGraph.urlToModuleMap.keys()) if (isCSS(key)) { if ("raw" in getQuery(key)) continue; const importers = ssrServer.moduleGraph.urlToModuleMap.get(key)?.importers; if (importers && [...importers].every((i) => i.id && "raw" in getQuery(i.id))) continue; css.add(key); } for (const globalCss of nuxt.options.css) if (typeof globalCss === "string") css.add(resolveAlias(globalCss, nuxt.options.alias)); return normalizeViteManifest({ "@vite/client": { file: "@vite/client", css: [...css], module: true, isEntry: true }, ...nuxt.options.features.noScripts === "all" ? {} : { [clientEntry]: { file: clientEntry, isEntry: true, module: true, resourceType: "script" } } }); } function generateSocketPath() { const socketName = `nuxt-vite-node-${`${process.pid}-${Date.now()}`}`; if (process.platform === "win32") return join(String.raw`\\.\pipe`, socketName); if (process.platform === "linux") { if (Number.parseInt(process.versions.node.split(".")[0], 10) >= 20 && provider !== "stackblitz") { let isDocker = false; try { isDocker = fs.existsSync("/.dockerenv") || fs.existsSync("/proc/1/cgroup") && fs.readFileSync("/proc/1/cgroup", "utf8").includes("docker"); } catch {} if (!isDocker) return `\0${socketName}.sock`; } } return join(os.tmpdir(), `${socketName}.sock`); } function useInvalidates() { const invalidates = /* @__PURE__ */ new Set(); function markInvalidate(mod) { if (!mod.id) return; if (invalidates.has(mod.id)) return; invalidates.add(mod.id); markInvalidates(mod.importers); } function markInvalidates(mods) { if (!mods) return; for (const mod of mods) markInvalidate(mod); } return { invalidates, markInvalidate, markInvalidates }; } function ViteNodePlugin(nuxt) { let socketServer; const socketPath = generateSocketPath(); const { invalidates, markInvalidate, markInvalidates } = useInvalidates(); async function cleanupSocket() { if (socketServer && socketServer.listening) await new Promise((resolveClose) => socketServer.close(() => resolveClose())); if (socketPath && !socketPath.startsWith("\\\\.\\pipe\\")) try { await unlink(socketPath); } catch {} } return { name: "nuxt:vite-node-server", enforce: "post", configureServer(clientServer) { if (!tryUseNuxt()) return; function resolveServer(ssrServer) { const viteNodeServerOptions = { socketPath, root: nuxt.options.srcDir, entryPath: resolveServerEntry(ssrServer.config), base: ssrServer.config.base || "/_nuxt/", maxRetryAttempts: nuxt.options.vite.viteNode?.maxRetryAttempts, baseRetryDelay: nuxt.options.vite.viteNode?.baseRetryDelay, maxRetryDelay: nuxt.options.vite.viteNode?.maxRetryDelay, requestTimeout: nuxt.options.vite.viteNode?.requestTimeout, baseURL: nuxt.options.devServer.url }; process.env.NUXT_VITE_NODE_OPTIONS = JSON.stringify(viteNodeServerOptions); socketServer = createViteNodeSocketServer(nuxt, ssrServer, clientServer, invalidates, viteNodeServerOptions); } if (nuxt.options.experimental.viteEnvironmentApi) resolveServer(clientServer); else nuxt.hook("vite:serverCreated", (ssrServer, ctx) => ctx.isServer ? resolveServer(ssrServer) : void 0); nuxt.hook("close", cleanupSocket); const client = nuxt.options.experimental.viteEnvironmentApi ? clientServer.environments.client : clientServer; nuxt.hook("app:templatesGenerated", (_app, changedTemplates) => { for (const template of changedTemplates) { const mods = client.moduleGraph.getModulesByFile(`virtual:nuxt:${encodeURIComponent(template.dst)}`); for (const mod of mods || []) markInvalidate(mod); } }); clientServer.watcher.on("all", (_event, file) => { invalidates.add(file); markInvalidates(clientServer.moduleGraph.getModulesByFile(normalize(file))); }); }, async buildEnd() { await cleanupSocket(); } }; } let _node; function getNode(server) { return _node ||= new ViteNodeServer(server, { transformMode: { ssr: [/.*/], web: [] } }); } function createViteNodeSocketServer(nuxt, ssrServer, clientServer, invalidates, config) { const server = net.createServer((socket) => { const INITIAL_BUFFER_SIZE = 64 * 1024; const MAX_BUFFER_SIZE = 1024 * 1024 * 1024; let buffer = Buffer.alloc(INITIAL_BUFFER_SIZE); let writeOffset = 0; let readOffset = 0; socket.setNoDelay(true); socket.setKeepAlive(true, 0); async function processMessage(request) { try { switch (request.type) { case "manifest": { const manifestData = getManifest(nuxt, ssrServer, resolveClientEntry(clientServer.config)); sendResponse(socket, request.id, manifestData); return; } case "invalidates": { const responsePayload = Array.from(invalidates); invalidates.clear(); sendResponse(socket, request.id, responsePayload); return; } case "resolve": { const { id: resolveId, importer } = request.payload; if (!resolveId) throw { status: 400, message: "Missing id for resolve" }; const resolvedResult = await (nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.ssr.pluginContainer : getNode(ssrServer)).resolveId(resolveId, importer).catch(() => null); sendResponse(socket, request.id, resolvedResult); return; } case "module": { if (request.payload.moduleId === "/") throw { status: 400, message: "Invalid moduleId" }; const response = await (nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.ssr : getNode(ssrServer)).fetchModule(request.payload.moduleId).catch(async (err) => { const errorData = { code: "VITE_ERROR", id: request.payload.moduleId, stack: err.stack || "", message: err.message || "" }; if (err.frame) errorData.frame = err.frame; if (!errorData.frame && err.code === "PARSE_ERROR") try { errorData.frame = await (nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.client : getNode(ssrServer)).transformRequest(request.payload.moduleId).then((res) => `${err.message || ""}\n${res?.code}`).catch(() => void 0); } catch {} throw { data: errorData, message: err.message || "Error fetching module" }; }); sendResponse(socket, request.id, response); return; } default: throw { status: 400, message: `Unknown request type: ${request.type}` }; } } catch (error) { sendError(socket, request.id, error); } } const resetBuffer = () => { writeOffset = 0; readOffset = 0; }; const compactBuffer = () => { if (readOffset > 0) { const remainingData = writeOffset - readOffset; if (remainingData > 0) buffer.copy(buffer, 0, readOffset, writeOffset); writeOffset = remainingData; readOffset = 0; } }; const ensureBufferCapacity = (additionalBytes) => { const requiredSize = writeOffset + additionalBytes; if (requiredSize > MAX_BUFFER_SIZE) throw new Error(`Buffer size limit exceeded: ${requiredSize} > ${MAX_BUFFER_SIZE}`); if (requiredSize > buffer.length) { compactBuffer(); if (writeOffset + additionalBytes > buffer.length) { const newSize = Math.min(Math.max(buffer.length * 2, requiredSize), MAX_BUFFER_SIZE); const newBuffer = Buffer.alloc(newSize); buffer.copy(newBuffer, 0, 0, writeOffset); buffer = newBuffer; } } }; socket.on("data", (data) => { try { ensureBufferCapacity(data.length); data.copy(buffer, writeOffset); writeOffset += data.length; while (writeOffset - readOffset >= 4) { const totalLength = 4 + buffer.readUInt32BE(readOffset); if (writeOffset - readOffset < totalLength) break; const messageJSON = buffer.subarray(readOffset + 4, readOffset + totalLength).toString("utf-8"); readOffset += totalLength; try { const request = JSON.parse(messageJSON); processMessage(request).catch((error) => { sendError(socket, request?.id || "unknown", error); }); } catch (parseError) { const errorMessage = parseError instanceof Error ? parseError.message : "Unknown parse error"; socket.destroy(/* @__PURE__ */ new Error(`Invalid JSON in message: ${errorMessage}`)); return; } } if (readOffset > buffer.length / 2) compactBuffer(); } catch (error) { socket.destroy(error instanceof Error ? error : /* @__PURE__ */ new Error("Buffer management error")); } }); socket.on("error", () => { resetBuffer(); }); socket.on("close", () => { resetBuffer(); }); }); const currentSocketPath = config.socketPath; if (!currentSocketPath) throw new Error("Socket path not configured for ViteNodeSocketServer."); if (!currentSocketPath.startsWith("\\\\.\\pipe\\")) try { fs.unlinkSync(currentSocketPath); } catch (unlinkError) { if (unlinkError.code !== "ENOENT") {} } server.listen(currentSocketPath); server.on("error", () => {}); return server; } function sendResponse(socket, id, data) { try { const response = { id, type: "response", data }; const responseJSON = JSON.stringify(response); const messageBuffer = Buffer.from(responseJSON, "utf-8"); const messageLength = messageBuffer.length; const fullMessage = Buffer.alloc(4 + messageLength); fullMessage.writeUInt32BE(messageLength, 0); messageBuffer.copy(fullMessage, 4); socket.write(fullMessage, (err) => { if (err) {} }); } catch (error) { sendError(socket, id, error); } } function sendError(socket, id, error) { const errorResponse = { id, type: "error", error: { message: error.message, stack: error.stack, status: error.status, statusText: error.statusText, data: error.data } }; const responseJSON = JSON.stringify(errorResponse); const messageBuffer = Buffer.from(responseJSON, "utf-8"); const messageLength = messageBuffer.length; const fullMessage = Buffer.alloc(4 + messageLength); fullMessage.writeUInt32BE(messageLength, 0); messageBuffer.copy(fullMessage, 4); socket.write(fullMessage, (err) => { if (err) {} }); } async function writeDevServer(nuxt) { const serverResolvedPath = resolveModulePath("#vite-node-entry", { from: import.meta.url }); const fetchResolvedPath = resolveModulePath("#vite-node", { from: import.meta.url }); const serverDist = join(nuxt.options.buildDir, "dist/server"); await mkdir(serverDist, { recursive: true }); await Promise.all([ writeFile(join(serverDist, "server.mjs"), `export { default } from ${JSON.stringify(pathToFileURL(serverResolvedPath).href)}`), writeFile(join(serverDist, "client.precomputed.mjs"), `export default undefined`), writeFile(join(serverDist, "client.manifest.mjs"), ` import { viteNodeFetch } from ${JSON.stringify(pathToFileURL(fetchResolvedPath))} export default () => viteNodeFetch.getManifest() `) ]); } const PREFIX = "virtual:public?"; const PREFIX_RE = /^virtual:public\?/; const CSS_URL_RE = /url\((\/[^)]+)\)/g; const CSS_URL_SINGLE_RE = /url\(\/[^)]+\)/; const RENDER_CHUNK_RE = /(?<= = )['"`]/; const PublicDirsPlugin = (options) => { const { resolveFromPublicAssets } = useResolveFromPublicAssets(); let sourcemap; return [{ name: "nuxt:vite-public-dir-resolution-dev", apply() { return !!options.dev && !!options.baseURL && options.baseURL !== "/"; }, transform(code, id) { if (!isCSSRequest(id) || !CSS_URL_SINGLE_RE.test(code)) return; const s = new MagicString(code); for (const [full, url] of code.matchAll(CSS_URL_RE)) if (url && resolveFromPublicAssets(url)) s.replace(full, `url(${options.baseURL}${url})`); if (s.hasChanged()) return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } }, { name: "nuxt:vite-public-dir-resolution", configResolved(config) { sourcemap = !!config.build.sourcemap; }, load: { order: "pre", filter: { id: PREFIX_RE }, handler(id) { return `import { publicAssetsURL } from '#internal/nuxt/paths';export default publicAssetsURL(${JSON.stringify(decodeURIComponent(id.slice(15)))})`; } }, resolveId: { order: "post", filter: { id: { exclude: [ /^\/__skip_vite$/, /^[^/]/, /^\/@fs/ ] } }, handler(id) { if (resolveFromPublicAssets(id)) return PREFIX + encodeURIComponent(id); } }, renderChunk(code, chunk) { if (!chunk.facadeModuleId?.includes("?inline&used")) return; const s = new MagicString(code); const q = code.match(RENDER_CHUNK_RE)?.[0] || "\""; for (const [full, url] of code.matchAll(CSS_URL_RE)) if (url && resolveFromPublicAssets(url)) s.replace(full, `url(${q} + publicAssetsURL(${q}${url}${q}) + ${q})`); if (s.hasChanged()) { s.prepend(`import { publicAssetsURL } from '#internal/nuxt/paths';`); return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; } }, generateBundle(_outputOptions, bundle) { for (const [file, chunk] of Object.entries(bundle)) { if (!file.endsWith(".css") || chunk.type !== "asset") continue; let css = chunk.source.toString(); let wasReplaced = false; for (const [full, url] of css.matchAll(CSS_URL_RE)) if (url && resolveFromPublicAssets(url)) { const relativeURL = relative(withLeadingSlash(dirname(file)), url); css = css.replace(full, `url(${relativeURL})`); wasReplaced = true; } if (wasReplaced) chunk.source = css; } } }]; }; const PUBLIC_ASSETS_RE = /[?#].*$/; function useResolveFromPublicAssets() { const nitro = useNitro(); function resolveFromPublicAssets(id) { for (const dir of nitro.options.publicAssets) { if (!id.startsWith(withTrailingSlash(dir.baseURL || "/"))) continue; if (existsSync(id.replace(PUBLIC_ASSETS_RE, "").replace(withTrailingSlash(dir.baseURL || "/"), withTrailingSlash(dir.dir)))) return id; } } return { resolveFromPublicAssets }; } let duplicateCount = 0; let lastType = null; let lastMsg = null; const logLevelMap = { silent: "silent", info: "info", verbose: "info" }; const logLevelMapReverse = { silent: 0, error: 1, warn: 2, info: 3 }; const RUNTIME_RESOLVE_REF_RE = /^([^ ]+) referenced in/m; function createViteLogger(config, ctx = {}) { const loggedErrors = /* @__PURE__ */ new WeakSet(); const canClearScreen = hasTTY && !isCI && config.clearScreen; const _logger = createLogger(); const relativeOutDir = relative(config.root, config.build.outDir || ""); const clear = () => { _logger.clearScreen("silent"); }; const clearScreen = canClearScreen ? clear : () => {}; const { resolveFromPublicAssets } = useResolveFromPublicAssets(); function output(type, msg, options = {}) { if (typeof msg === "string" && !process.env.DEBUG) { if (msg.startsWith("Sourcemap") && msg.includes("node_modules")) return; if (msg.includes("didn't resolve at build time, it will remain unchanged to be resolved at runtime")) { const id = msg.trim().match(RUNTIME_RESOLVE_REF_RE)?.[1]; if (id && resolveFromPublicAssets(id)) return; } if (type === "info" && ctx.hideOutput && msg.includes(relativeOutDir)) return; } const sameAsLast = lastType === type && lastMsg === msg; if (sameAsLast) { duplicateCount += 1; clearScreen(); } else { duplicateCount = 0; lastType = type; lastMsg = msg; if (options.clear) clearScreen(); } if (options.error) loggedErrors.add(options.error); const prevLevel = logger.level; logger.level = logLevelMapReverse[config.logLevel || "info"]; logger[type](msg + (sameAsLast ? colorize("dim", ` (x${duplicateCount + 1})`) : "")); logger.level = prevLevel; } const warnedMessages = /* @__PURE__ */ new Set(); const viteLogger = { hasWarned: false, info(msg, opts) { output("info", msg, opts); }, warn(msg, opts) { viteLogger.hasWarned = true; output("warn", msg, opts); }, warnOnce(msg, opts) { if (warnedMessages.has(msg)) return; viteLogger.hasWarned = true; output("warn", msg, opts); warnedMessages.add(msg); }, error(msg, opts) { viteLogger.hasWarned = true; output("error", msg, opts); }, clearScreen() { clear(); }, hasErrorLogged(error) { return loggedErrors.has(error); } }; return viteLogger; } function StableEntryPlugin(nuxt) { let sourcemap; let entryFileName; const nitro = useNitro(); nitro.options.virtual ||= {}; nitro.options._config.virtual ||= {}; nitro.options._config.virtual["#internal/entry-chunk.mjs"] = nitro.options.virtual["#internal/entry-chunk.mjs"] = () => `export const entryFileName = ${JSON.stringify(entryFileName)}`; return { name: "nuxt:stable-entry", configResolved(config) { sourcemap = !!config.build.sourcemap; }, apply: () => !nuxt.options.dev && nuxt.options.experimental.entryImportMap, applyToEnvironment(environment) { if (environment.name !== "client") return false; if (environment.config.build.target) { if (!toArray(environment.config.build.target).every(isSupported)) return false; } return toArray(environment.config.build.rollupOptions?.output).some((output) => typeof output?.entryFileNames === "string" && output?.entryFileNames.includes("[hash]")); }, renderChunk(code, chunk, _options, meta) { const entry = Object.values(meta.chunks).find((chunk) => chunk.isEntry && chunk.name === "entry")?.fileName; if (!entry || !chunk.imports.includes(entry)) return; const filename = new RegExp(`(?<=['"])[\\./]*${escapeStringRegexp(basename(entry))}`, "g"); const s = new MagicString(code); s.replaceAll(filename, "#entry"); if (s.hasChanged()) return { code: s.toString(), map: sourcemap ? s.generateMap({ hires: true }) : void 0 }; }, writeBundle(_options, bundle) { let entry = Object.values(bundle).find((chunk) => chunk.type === "chunk" && chunk.isEntry && chunk.name === "entry")?.fileName; const prefix = withoutLeadingSlash(nuxt.options.app.buildAssetsDir); if (entry?.startsWith(prefix)) entry = entry.slice(prefix.length); entryFileName = entry; } }; } const supportedEnvironments = { chrome: 89, edge: 89, firefox: 108, ie: Infinity, ios: 16.4, opera: 75, safari: 16.4 }; function isSupported(target) { const [engine, _version] = target.split(/(?<=[a-z])(?=\d)/); const constraint = supportedEnvironments[engine]; if (!constraint) return true; const version = Number(_version); return Number.isNaN(version) || Number(version) >= constraint; } async function AnalyzePlugin(nuxt) { if (nuxt.options.test) return; const analyzeOptions = defu({}, nuxt.options.build.analyze); if (!analyzeOptions.enabled) return; const { visualizer } = await import("rollup-plugin-visualizer"); return { name: "nuxt:analyze", applyToEnvironment(environment) { if (environment.name !== "client") return false; return [{ name: "nuxt:analyze-minify", async generateBundle(_opts, outputBundle) { for (const _bundleId in outputBundle) { const bundle = outputBundle[_bundleId]; if (!bundle || bundle.type !== "chunk") continue; const minifiedModuleEntryPromises = []; for (const [moduleId, module] of Object.entries(bundle.modules)) minifiedModuleEntryPromises.push(transform(module.code || "", { minify: true }).then((result) => [moduleId, { ...module, code: result.code }])); bundle.modules = Object.fromEntries(await Promise.all(minifiedModuleEntryPromises)); } } }, visualizer({ ...analyzeOptions, filename: "filename" in analyzeOptions && analyzeOptions.filename ? analyzeOptions.filename.replace("{name}", "client") : void 0, title: "Client bundle stats", gzipSize: true, brotliSize: true })]; } }; } function DevServerPlugin(nuxt) { let useViteCors = false; const nitro = useNitro(); return { name: "nuxt:dev-server", async config(config) { for (const item of [ config.optimizeDeps, config.environments?.client?.optimizeDeps, config.environments?.ssr?.optimizeDeps ]) { if (!item) continue; const exclude = new Set(item.exclude ?? []); item.include = item.include?.filter((dep) => !exclude.has(dep)); } if (!nuxt.options.dev && config.server) config.server.hmr = false; useViteCors = config.server?.cors !== void 0; if (!useViteCors) { config.server ??= {}; config.server.cors = false; } if (config.server && config.server.hmr !== false) { const serverDefaults = { hmr: { protocol: nuxt.options.devServer.https ? "wss" : void 0 } }; if (typeof config.server.hmr !== "object" || !config.server.hmr.server) { serverDefaults.hmr ??= {}; const hmrPortDefault = 24678; serverDefaults.hmr.port = await getPort({ verbose: false, portRange: [hmrPortDefault, hmrPortDefault + 20] }); } if (nuxt.options.devServer.https) serverDefaults.https = nuxt.options.devServer.https === true ? {} : nuxt.options.devServer.https; config.server = defu(config.server, serverDefaults); } }, async configureServer(viteServer) { nuxt.hook("app:templatesGenerated", async (_app, changedTemplates) => { await Promise.all(changedTemplates.map(async (template) => { for (const mod of viteServer.moduleGraph.getModulesByFile(`virtual:nuxt:${encodeURIComponent(template.dst)}`) || []) { viteServer.moduleGraph.invalidateModule(mod); await viteServer.reloadModule(mod); } })); }); if (nuxt.options.experimental.viteEnvironmentApi) await nuxt.callHook("vite:serverCreated", viteServer, { isClient: true, isServer: true }); const mw = { route: "", handle: (req, res, next) => { if (req._skip_transform && req.url) req.url = joinURL("/__skip_vite", req.url.replace(/\?.*/, "")); next(); } }; const transformHandler = viteServer.middlewares.stack.findIndex((m) => m.handle instanceof Function && m.handle.name === "viteTransformMiddleware"); if (transformHandler === -1) viteServer.middlewares.stack.push(mw); else viteServer.middlewares.stack.splice(transformHandler, 0, mw); const staticBases = []; for (const folder of nitro.options.publicAssets) if (folder.baseURL && folder.baseURL !== "/" && folder.baseURL.startsWith(nuxt.options.app.buildAssetsDir)) staticBases.push(folder.baseURL.replace(/\/?$/, "/")); const devHandlerRegexes = []; for (const handler of nuxt.options.devServerHandlers) if (handler.route && handler.route !== "/" && handler.route.startsWith(nuxt.options.app.buildAssetsDir)) devHandlerRegexes.push(new RegExp(`^${handler.route.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/:[^/]+/g, "[^/]+").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*")}$`)); let _isProxyPath; function isProxyPath(url) { if (_isProxyPath) return _isProxyPath(url); const proxyConfig = viteServer.config.server.proxy; const proxyPatterns = []; if (proxyConfig) for (const key in proxyConfig) if (key.startsWith("^")) try { proxyPatterns.push({ type: "regex", value: new RegExp(key) }); } catch {} else proxyPatterns.push({ type: "string", value: key }); _isProxyPath = function isProxyPath(path) { for (const pattern of proxyPatterns) if (pattern.type === "regex" && pattern.value.test(path)) return true; else if (pattern.type === "string" && path.startsWith(pattern.value)) return true; return false; }; return _isProxyPath(url); } const viteMiddleware = defineEventHandler(async (event) => { const url = "url" in event ? event.url.pathname + event.url.search + event.url.hash : event.path; let isViteRoute = url.startsWith(viteServer.config.base); if (!isViteRoute) { for (const viteRoute of viteServer.middlewares.stack) if (viteRoute.route.length > 1 && url.startsWith(viteRoute.route)) { isViteRoute = true; break; } isViteRoute ||= isProxyPath(url); } const { req, res } = "runtime" in event ? event.runtime.node : event.node; if (!isViteRoute) req._skip_transform = true; const _originalPath = req.url; await new Promise((resolve, reject) => { viteServer.middlewares.handle(req, res, (err) => { req.url = _originalPath; return err ? reject(err) : resolve(null); }); }); if (url.startsWith(nuxt.options.app.buildAssetsDir) && !staticBases.some((baseURL) => url.startsWith(baseURL)) && !devHandlerRegexes.some((regex) => regex.test(url))) { res.statusCode = 404; res.end("Not Found"); return; } }); await nuxt.callHook("server:devHandler", viteMiddleware, { cors: (url) => { if (useViteCors) return false; if (url.startsWith(viteServer.config.base)) return true; for (const viteRoute of viteServer.middlewares.stack) if (viteRoute.route.length > 1 && url.startsWith(viteRoute.route)) return true; return isProxyPath(url); } }); } }; } function defineEventHandler(handler) { return Object.assign(handler, { __is_handler__: true }); } async function VitePluginCheckerPlugin(nuxt, environment) { if (!nuxt.options.test && (nuxt.options.typescript.typeCheck === true || nuxt.options.typescript.typeCheck === "build" && !nuxt.options.dev)) { const [checker, tsconfigPath] = await Promise.all([import("vite-plugin-checker").then((r) => r.default), resolveTSConfig(nuxt.options.rootDir)]); const supportsProjects = await readTSConfig(tsconfigPath).then((r) => !!r.references?.length); return ["client", nuxt.options.ssr ? "ssr" : void 0].filter((name) => environment ? name === environment : !!name).map((envName) => ({ applyToEnvironment: (environment) => environment.name === envName, ...checker({ vueTsc: { tsconfigPath, buildMode: supportsProjects } }) })); } } function getTranspilePatterns(envs) { const nuxt = useNuxt(); const transpile = []; for (let pattern of nuxt.options.build.transpile) { if (typeof pattern === "function") { const result = pattern(envs); if (result) pattern = result; } if (typeof pattern === "string") transpile.push(new RegExp(escapeStringRegexp(normalize(pattern)))); else if (pattern instanceof RegExp) transpile.push(pattern); } return transpile; } function getTranspileStrings(envs) { const nuxt = useNuxt(); const patterns = []; for (let pattern of nuxt.options.build.transpile) { if (typeof pattern === "function") { const result = pattern(envs); if (result) pattern = result; } if (typeof pattern === "string") patterns.push(normalize(pattern)); } return patterns; } const clientEnvironment = (nuxt, entry) => { return { optimizeDeps: { entries: [entry], include: [], exclude: [ "vue", "@vue/runtime-core", "@vue/runtime-dom", "@vue/reactivity", "@vue/shared", "@vue/devtools-api", "@vue/test-utils", "vue-router", "vue-demi", "nuxt", "nuxt/app", "@nuxt/test-utils", "@unhead/vue", "consola", "defu", "devalue", "get-port-please", "h3", "hookable", "klona", "ofetch", "pathe", "ufo", "unctx", "unenv", "#app-manifest", "#imports", "#app", "#build", "#build/*", "#components", "#head", "virtual:nuxt:", "virtual:nuxt:*", ...getTranspileStrings({ isDev: nuxt.options.dev, isClient: true }) ] }, define: { "process.env.NODE_ENV": JSON.stringify(nuxt.options.vite.mode), "process.server": false, "process.client": true, "process.browser": true, "process.nitro": false, "process.prerender": false, "import.meta.server": false, "import.meta.client": true, "import.meta.browser": true, "import.meta.nitro": false, "import.meta.prerender": false, "module.hot": false, ...nuxt.options.experimental.clientNodeCompat ? { global: "globalThis" } : {} }, build: { sourcemap: nuxt.options.sourcemap.client ? nuxt.options.vite.build?.sourcemap ?? nuxt.options.sourcemap.client : false, manifest: "manifest.json", outDir: resolve(nuxt.options.buildDir, "dist/client"), rollupOptions: { input: { entry } } } }; }; async function buildClient(nuxt, ctx) { const clientConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({ configFile: false, base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : "./", css: { devSourcemap: !!nuxt.options.sourcemap.client }, cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "client"), plugins: [ DevStyleSSRPlugin({ srcDir: nuxt.options.srcDir, buildAssetsURL: joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir) }), RuntimePathsPlugin(), ViteNodePlugin(nuxt), TypeCheckPlugin(nuxt), ModulePreloadPolyfillPlugin(), StableEntryPlugin(nuxt), AnalyzePlugin(nuxt), DevServerPlugin(nuxt), VitePluginCheckerPlugin(nuxt, "client") ], appType: "custom", server: { warmup: { clientFiles: [ctx.entry] }, middlewareMode: true }, ...clientEnvironment(nuxt, ctx.entry) }, nuxt.options.vite.$client || {})); clientConfig.customLogger = createViteLogger(clientConfig); await nuxt.callHook("vite:extendConfig", clientConfig, { isClient: true, isServer: false }); clientConfig.plugins.unshift(vuePlugin(clientConfig.vue), viteJsxPlugin(clientConfig.vueJsx)); await nuxt.callHook("vite:configResolved", clientConfig, { isClient: true, isServer: false }); if (nuxt.options.dev) { const viteServer = await vite.createServer(clientConfig); ctx.clientServer = viteServer; nuxt.hook("close", () => viteServer.close()); await nuxt.callHook("vite:serverCreated", viteServer, { isClient: true, isServer: false }); } else { logger.info("Building client..."); const start = Date.now(); logger.restoreAll(); await vite.build(clientConfig); logger.wrapAll(); await nuxt.callHook("vite:compiled"); logger.success(`Client built in ${Date.now() - start}ms`); } } async function writeManifest(ctx) { const { nuxt } = ctx; const devClientManifest = { "@vite/client": { isEntry: true, file: "@vite/client", css: [], module: true, resourceType: "script" }, ...nuxt.options.features.noScripts === "all" ? {} : { [ctx.entry]: { isEntry: true, file: ctx.entry, module: true, resourceType: "script" } } }; const clientDist = resolve(nuxt.options.buildDir, "dist/client"); const serverDist = resolve(nuxt.options.buildDir, "dist/server"); const manifestFile = resolve(clientDist, "manifest.json"); const clientManifest = nuxt.options.dev ? devClientManifest : JSON.parse(readFileSync(manifestFile, "utf-8")); const manifestEntries = Object.values(clientManifest); const buildAssetsDir = withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir)); const BASE_RE = new RegExp(`^${escapeStringRegexp(buildAssetsDir)}`); for (const entry of manifestEntries) { entry.file &&= entry.file.replace(BASE_RE, ""); for (const item of ["css", "assets"]) entry[item] &&= entry[item].map((i) => i.replace(BASE_RE, "")); } await mkdir(serverDist, { recursive: true }); if (ctx.config.build?.cssCodeSplit === false) { for (const entry of manifestEntries) if (entry.file?.endsWith(".css")) { const key = relative(ctx.config.root, ctx.entry); clientManifest[key].css ||= []; clientManifest[key].css.push(entry.file); break; } } const manifest = normalizeViteManifest(clientManifest); await nuxt.callHook("build:manifest", manifest); const precomputed = precomputeDependencies(manifest); await writeFile(resolve(serverDist, "client.manifest.mjs"), "export default " + serialize(manifest), "utf8"); await writeFile(resolve(serverDist, "client.precomputed.mjs"), "export default " + serialize(precomputed), "utf8"); if (!nuxt.options.dev) await rm(manifestFile, { force: true }); } const SourcemapPreserverPlugin = (nuxt) => { let outputDir; const ids = /* @__PURE__ */ new Set(); if (!nuxt.options.sourcemap.server || nuxt.options.dev) return []; const nitroPlugin = () => ({ name: "nuxt:sourcemap-import", load: { filter: { id: new RegExp("^(\\w:)?" + escapeStringRegexp(outputDir.replace(/\/?$/, "/")).replace(/\//g, "[\\\\/]")) }, async handler(id) { id = resolve(id); if (!ids.has(id)) return; const [code, map] = await Promise.all([readFile(id, "utf-8").catch(() => void 0), readFile(id + ".map.json", "utf-8").catch(() => void 0)]); if (!code) { this.warn("Failed loading file"); return null; } return { code, map }; } } }); nuxt.hook("nitro:build:before", (nitro) => { nitro.options.rollupConfig = defu(nitro.options.rollupConfig, { plugins: [nitroPlugin] }); }); return { name: "nuxt:sourcemap-export", applyToEnvironment: (environment) => { return environment.name === "ssr" && environment.config.isProduction; }, apply(config) { return !!config.build?.sourcemap; }, configResolved(config) { outputDir = config.build.outDir; }, async writeBundle(_options, bundle) { for (const chunk of Object.values(bundle)) { if (chunk.type !== "chunk" || !chunk.map) continue; const id = resolve(outputDir, chunk.fileName); ids.add(id); const dest = id + ".map.json"; await mkdir(dirname(dest), { recursive: true }); await writeFile(dest, JSON.stringify({ file: chunk.map.file, mappings: chunk.map.mappings, names: chunk.map.names, sources: chunk.map.sources, sourcesContent: chunk.map.sourcesContent, version: chunk.map.version })); } } }; }; function VueFeatureFlagsPlugin(nuxt) { return { name: "nuxt:nitro:vue-feature-flags", applyToEnvironment: (environment) => environment.name === "ssr" && environment.config.isProduction, configResolved(config) { for (const key in config.define) if (key.startsWith("__VUE")) nuxt._nitro.options.replace[key] = config.define[key]; } }; } function ssr(nuxt) { return { external: [ "nitro/runtime", "#internal/nitro", "#internal/nitro/utils" ], noExternal: [ ...getTranspilePatterns({ isServer: true, isDev: nuxt.options.dev }), "/__vue-jsx", "#app", /^nuxt(\/|$)/, /(nuxt|nuxt3|nuxt-nightly)\/(dist|src|app)/ ] }; } function ssrEnvironment(nuxt, serverEntry) { return { build: { reportCompressedSize: false, sourcemap: nuxt.options.sourcemap.server ? nuxt.options.vite.build?.sourcemap ?? nuxt.options.sourcemap.server : false, outDir: resolve(nuxt.options.buildDir, "dist/server"), ssr: true, rollupOptions: { input: { server: serverEntry }, external: [ "nitro/runtime", "#internal/nitro", "nitropack/runtime", "#internal/nuxt/paths", "#internal/nuxt/app-config", "#app-manifest", "#shared", new RegExp("^" + escapeStringRegexp(withTrailingSlash(resolve(nuxt.options.rootDir, nuxt.options.dir.shared)))) ], output: { entryFileNames: "[name].mjs", format: "module", ...vite.rolldownVersion ? {} : { generatedCode: { symbols: true, constBindings: true, arrowFunctions: true } } }, onwarn(warning, rollupWarn) { if (warning.code && "UNUSED_EXTERNAL_IMPORT" === warning.code) return; rollupWarn(warning); } } }, define: { "process.server": true, "process.client": false, "process.browser": false, "import.meta.server": true, "import.meta.client": false, "import.meta.browser": false, "window": "undefined", "document": "undefined", "navigator": "undefined", "location": "undefined", "XMLHttpRequest": "undefined" }, optimizeDeps: { noDiscovery: true, include: void 0, exclude: getTranspileStrings({ isDev: nuxt.options.dev, isClient: false }) }, resolve: { conditions: useNitro().options.exportConditions } }; } async function buildServer(nuxt, ctx) { const serverEntry = nuxt.options.ssr ? ctx.entry : await resolvePath(resolve(nuxt.options.appDir, "entry-spa")); const serverConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({ configFile: false, base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : void 0, css: { devSourcemap: !!nuxt.options.sourcemap.server }, plugins: [ VueFeatureFlagsPlugin(nuxt), SourcemapPreserverPlugin(nuxt), VitePluginCheckerPlugin(nuxt, "ssr"), { name: "nuxt:server-hmr-port", async config(serverConfig) { serverConfig.server ||= {}; serverConfig.server.hmr ||= {}; if (nuxt.options.dev && typeof serverConfig.server.hmr !== "boolean") { const hmrPortDefault = 24678; serverConfig.server.hmr.port ||= await getPort({ verbose: false, portRange: [hmrPortDefault, hmrPortDefault + 20] }); } } } ], environments: { ssr: { resolve: { conditions: nuxt._nitro?.options.exportConditions } } }, ssr: ssr(nuxt), cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "server"), server: { warmup: { ssrFiles: [serverEntry] }, preTransformRequests: false, hmr: false }, ...ssrEnvironment(nuxt, serverEntry) }, nuxt.options.vite.$server || {})); serverConfig.customLogger = createViteLogger(serverConfig, { hideOutput: !nuxt.options.dev }); await nuxt.callHook("vite:extendConfig", serverConfig, { isClient: false, isServer: true }); serverConfig.plugins.unshift(vuePlugin(serverConfig.vue), viteJsxPlugin(serverConfig.vueJsx)); await nuxt.callHook("vite:configResolved", serverConfig, { isClient: false, isServer: true }); if (!nuxt.options.dev) { const start = Date.now(); logger.info("Building server..."); logger.restoreAll(); await vite.build(serverConfig); logger.wrapAll(); await writeManifest(ctx); await nuxt.callHook("vite:compiled"); logger.success(`Server built in ${Date.now() - start}ms`); return; } if (!nuxt.options.ssr) { await writeManifest(ctx); await nuxt.callHook("vite:compiled"); return; } const ssrServer = await vite.createServer(serverConfig); ctx.ssrServer = ssrServer; nuxt.hook("close", () => ssrServer.close()); await nuxt.callHook("vite:serverCreated", ssrServer, { isClient: false, isServer: true }); nuxt.hook("app:templatesGenerated", async (_app, changedTemplates) => { await Promise.all(changedTemplates.map(async (template) => { for (const mod of ssrServer.moduleGraph.getModulesByFile(`virtual:nuxt:${encodeURIComponent(template.dst)}`) || []) { ssrServer.moduleGraph.invalidateModule(mod); await ssrServer.reloadModule(mod); } })); }); await ssrServer.pluginContainer.buildStart({}); await writeDevServer(nuxt); } function fileToUrl(file, root) { const url = relative(root, file); if (url[0] === ".") return join("/@fs/", normalize(file)); return "/" + normalize(url); } function normaliseURL(url, base) { url = withoutBase(url, base); if (url.startsWith("/@id/")) url = url.slice(5).replace("__x00__", "\0"); url = url.replace(/[?&]import=?(?:&|$)/, "").replace(/[?&]$/, ""); return url; } async function warmupViteServer(server, entries, isServer) { const warmedUrls = /* @__PURE__ */ new Set(); const warmup = async (url) => { try { url = normaliseURL(url, server.config.base); if (warmedUrls.has(url) || isBuiltin(url)) return; const m = await server.moduleGraph.getModuleByUrl(url, isServer); if (m?.transformResult?.code || m?.ssrTransformResult?.code) return; warmedUrls.add(url); await server.transformRequest(url, { ssr: isServer }); } catch (e) { logger.debug("[nuxt] warmup for %s failed with: %s", url, e); } if (isCSSRequest(url)) return; try { const mod = await server.moduleGraph.getModuleByUrl(url, isServer); const deps = mod?.ssrTransformResult?.deps || (mod?.importedModules.size ? Array.from(mod?.importedModules).map((m) => m.url) : []); await Promise.all(deps.map((m) => warmup(m))); } catch (e) { logger.debug("[warmup] tracking dependencies for %s failed with: %s", url, e); } }; await Promise.all(entries.map((entry) => warmup(fileToUrl(entry, server.config.root)))); } function sortPlugins({ plugins, order }) { const names = Object.keys(plugins); return typeof order === "function" ? order(names) : order || names; } async function resolveCSSOptions(nuxt) { const css = { postcss: { plugins: [] } }; const postcssOptions = nuxt.options.postcss; const jiti = createJiti(nuxt.options.rootDir, { alias: nuxt.options.alias }); for (const pluginName of sortPlugins(postcssOptions)) { const pluginOptions = postcssOptions.plugins[pluginName]; if (!pluginOptions) continue; let pluginFn; for (const parentURL of nuxt.options.modulesDir) { pluginFn = await jiti.import(pluginName, { parentURL: parentURL.replace(/\/node_modules\/?$/, ""), try: true, default: true }); if (typeof pluginFn === "function") { css.postcss.plugins.push(pluginFn(pluginOptions)); break; } } if (typeof pluginFn !== "function") console.warn(`[nuxt] could not import postcss plugin \`${pluginName}\`. Please report this as a bug.`); } return css; } const SUPPORTED_FILES_RE = /\.(?:vue|(?:[cm]?j|t)sx?)$/; const QUERY_RE = /\?.+$/; function SSRStylesPlugin(nuxt) { if (nuxt.options.dev) return; const chunksWithInlinedCSS = /* @__PURE__ */ new Set(); const clientCSSMap = {}; const nitro = useNitro(); nuxt.hook("build:manifest", (manifest) => { const entryIds = /* @__PURE__ */ new Set(); for (const id of chunksWithInlinedCSS) { const chunk = manifest[id]; if (!chunk) continue; if (chunk.isEntry && chunk.src) entryIds.add(chunk.src); else chunk.css &&= []; } nitro.options.virtual["#internal/nuxt/entry-ids.mjs"] = () => `export default ${JSON.stringify(Array.from(entryIds))}`; nitro.options._config.virtual ||= {}; nitro.options._config.virtual["#internal/nuxt/entry-ids.mjs"] = nitro.options.virtual["#internal/nuxt/entry-ids.mjs"]; }); const cssMap = {}; const idRefMap = {}; const options = { shouldInline: nuxt.options.features.inlineStyles, globalCSS: nuxt.options.css }; const relativeCache = /* @__PURE__ */ new Map(); const relativeToSrcDir = (path) => { let cached = relativeCache.get(path); if (cached === void 0) { cached = relative(nuxt.options.srcDir, path); relativeCache.set(path, cached); } return cached; }; const warnCache = /* @__PURE__ */ new Set(); const components = nuxt.apps.default.components || []; const islands = components.filter((component) => component.island || component.mode === "server" && !components.some((c) => c.pascalName === component.pascalName && c.mode === "client")); const islandPaths = new Set(islands.map((c) => c.filePath)); let entry; return { name: "ssr-styles", configResolved(config) { if (!config.build.ssr || nuxt.options.experimental.viteEnvironmentApi) entry = resolveClientEntry(config); }, applyToEnvironment(environment) { return { name: `nuxt:ssr-styles:${environment.name}`, enforce: "pre", resolveId: { order: "pre", filter: { id: { include: [ /^#build\/css$/, /\.vue$/, IS_CSS_RE ] } }, async handler(id, importer, _options) { if (options.shouldInline === false || typeof options.shouldInline === "function" && !options.shouldInline(importer)) return; const res = await this.resolve(id, importer, { ..._options, skipSelf: true }); if (res) return { ...res, moduleSideEffects: false }; } }, generateBundle(outputOptions) { if (environment.name === "client") return; const emitted = {}; for (const [file, { files, inBundle }] of Object.entries(cssMap)) { if (!files.length || !inBundle) continue; const fileName = filename$1(file); const baseDir = dirname(typeof outputOptions.assetFileNames === "string" ? outputOptions.assetFileNames : outputOptions.assetFileNames({ type: "asset", name: `${fileName}-styles.mjs`, names: [`${fileName}-styles.mjs`], originalFileName: `${fileName}-styles.mjs`, originalFileNames: [`${fileName}-styles.mjs`], source: "" })); const cssImports = /* @__PURE__ */ new Set(); const exportNames = /* @__PURE__ */ new Set(); const importStatements = /* @__PURE__ */ new Set(); let i = 0; for (const css of files) { const file = this.getFileName(css); if (cssImports.has(file)) continue; cssImports.add(file); const name = `style_${i++}`; importStatements.add(genImport(`./${relative(baseDir, file)}`, name)); exportNames.add(name); } emitted[file] = this.emitFile({ type: "asset", name: `${fileName}-styles.mjs`, source: [...importStatements, `export default ${genArrayFromRaw([...exportNames])}`].join("\n") }); } for (const key in emitted) chunksWithInlinedCSS.add(key); this.emitFile({ type: "asset", fileName: "styles.mjs", originalFileName: "styles.mjs", source: ["const interopDefault = r => r.default || r || []", `export default ${genObjectFromRawEntries(Object.entries(emitted).map(([key, value]) => [key, `() => import('./${this.getFileName(value)}').then(interopDefault)`]))}`].join("\n") }); }, renderChunk(_code, chunk) { const isEntry = chunk.facadeModuleId === entry; if (isEntry) clientCSSMap[chunk.facadeModuleId] ||= /* @__PURE__ */ new Set(); for (const moduleId of [chunk.facadeModuleId, ...chunk.moduleIds].filter(Boolean)) { if (environment.name === "client") { const moduleMap = clientCSSMap[moduleId] ||= /* @__PURE__ */ new Set(); if (isCSS(moduleId)) { if (isVue(moduleId)) { moduleMap.add(moduleId); const parent = moduleId.replace(/\?.+$/, ""); (clientCSSMap[parent] ||= /* @__PURE__ */ new Set()).add(moduleId); } if (isEntry && chunk.facadeModuleId) (clientCSSMap[chunk.facadeModuleId] ||= /* @__PURE__ */ new Set()).add(moduleId); } continue; } const relativePath = relativeToSrcDir(moduleId); if (relativePath in cssMap) cssMap[relativePath].inBundle = cssMap[relativePath].inBundle ?? (isVue(moduleId) && !!relativePath || isEntry); } return null; }, transform: { filter: { id: { include: environment.name === "client" ? new RegExp("^" + escapeStringRegexp(entry) + "$") : void 0, exclude: environment.name === "client" ? [] : [/\?.*macro=/, /\?.*nuxt_component=/] } }, async handler(code, id) { if (environment.name === "client") { if (id === entry && (options.shouldInline === true || typeof options.shouldInline === "function" && options.shouldInline(id))) { const idClientCSSMap = clientCSSMap[id] ||= /* @__PURE__ */ new Set(); if (!options.globalCSS.length) return; const s = new MagicString(code); for (const file of options.globalCSS) { const resolved = await this.resolve(file) ?? await this.resolve(file, id); const res = await this.resolve(file + "?inline&used") ?? await this.resolve(file + "?inline&used", id); if (!resolved || !res) { if (!warnCache.has(file)) { warnCache.add(file); this.warn(`[nuxt] Cannot extract styles for \`${file}\`. Its styles will not be inlined when server-rendering.`); } s.prepend(`${genImport(file)}\n`); continue; } idClientCSSMap.add(resolved.id); } if (s.hasChanged()) return { code: s.toString(), map: s.generateMap({ hires: true }) }; } return; } const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)); if (!(id in clientCSSMap) && !islandPaths.has(pathname)) return; const query = parseQuery(search); if (query.macro || query.nuxt_component) return; if (!islandPaths.has(pathname)) { if (options.shouldInline === false || typeof options.shouldInline === "function" && !options.shouldInline(id)) return; } const relativeId = relativeToSrcDir(id); const idMap = cssMap[relativeId] ||= { files: [] }; const emittedIds = /* @__PURE__ */ new Set(); const idFilename = filename$1(id); let styleCtr = 0; const ids = clientCSSMap[id] || []; for (const file of ids) { if (emittedIds.has(file)) continue; const fileInline = file + "?inline&used"; const resolved = await this.resolve(file) ?? await this.resolve(file, id); const res = await this.resolve(fileInline) ?? await this.resolve(fileInline, id); if (!resolved || !res) { if (!warnCache.has(file)) { warnCache.add(file); this.warn(`[nuxt] Cannot extract styles for \`${file}\`. Its styles will not be inlined when server-rendering.`); } continue; } emittedIds.add(file); const ref = this.emitFile({ type: "chunk", name: `${idFilename}-styles-${++styleCtr}.mjs`, id: fileInline }); idRefMap[relativeToSrcDir(file)] = ref; idMap.files.push(ref); } if (!SUPPORTED_FILES_RE.test(pathname)) return; for (const i of findStaticImports(code)) { if (!i.specifier.endsWith(".css") && parseQuery(i.specifier).type !== "style") continue; const resolved = await this.resolve(i.specifier, id); if (!resolved) continue; const resolvedIdInline = resolved.id + "?inline&used"; if (!await this.resolve(resolvedIdInline)) { if (!warnCache.has(resolved.id)) { warnCache.add(resolved.id); this.warn(`[nuxt] Cannot extract styles for \`${i.specifier}\`. Its styles will not be inlined when server-rendering.`); } continue; } if (emittedIds.has(resolved.id)) continue; const ref = this.emitFile({ type: "chunk", name: `${idFilename}-styles-${++styleCtr}.mjs`, id: resolvedIdInline }); idRefMap[relativeToSrcDir(resolved.id)] = ref; idMap.files.push(ref); } } } }; } }; } function filename$1(name) { return filename(name.replace(QUERY_RE, "")); } function ReplacePlugin() { return { name: "nuxt:replace", enforce: "post", async applyToEnvironment(environment) { const config = environment.getTopLevelConfig(); const replaceOptions = Object.create(null); for (const define of [config.define || {}, environment.config.define || {}]) for (const key in define) if (key.startsWith("import.meta.")) replaceOptions[key] = define[key]; if (config.isProduction && vite.rolldownVersion) { const { replacePlugin } = await import("rolldown/plugins"); return replacePlugin(replaceOptions, { preventAssignment: true }); } else return replacePlugin({ ...replaceOptions, preventAssignment: true }); } }; } function LayerDepOptimizePlugin(nuxt) { if (!nuxt.options.dev) return; const layerDirs = []; const delimitedRootDir = nuxt.options.rootDir + "/"; for (const dirs of getLayerDirectories(nuxt)) if (dirs.app !== nuxt.options.srcDir && !dirs.app.startsWith(delimitedRootDir)) layerDirs.push(dirs.app); if (layerDirs.length > 0) { layerDirs.sort().reverse(); const dirs = [...layerDirs]; return { name: "nuxt:optimize-layer-deps", enforce: "pre", resolveId: { async handler(source, _importer) { if (!_importer) return; const importer = normalize(_importer); const layerIndex = dirs.findIndex((dir) => importer.startsWith(dir)); if (layerIndex !== -1) { dirs.splice(layerIndex, 1); await this.resolve(source, join(nuxt.options.srcDir, "index.html"), { skipSelf: true }).catch(() => null); } } } }; } } let _distDir = dirname(fileURLToPath(import.meta.url)); if (/(?:chunks|shared)$/.test(_distDir)) _distDir = dirname(_distDir); const distDir = _distDir; function EnvironmentsPlugin(nuxt) { const fileNames = withoutLeadingSlash(join(nuxt.options.app.buildAssetsDir, "[hash].js")); const clientOutputDir = join(useNitro().options.output.publicDir, nuxt.options.app.buildAssetsDir); const clientAliases = { "nitro/runtime": join(nuxt.options.buildDir, "nitro.client.mjs"), "#internal/nitro": join(nuxt.options.buildDir, "nitro.client.mjs"), "nitropack/runtime": join(nuxt.options.buildDir, "nitro.client.mjs"), "#app-manifest": resolveModulePath("mocked-exports/empty", { from: import.meta.url }) }; let viteConfig; return { name: "nuxt:environments", enforce: "pre", config(config) { viteConfig = config; if (!nuxt.options.dev) return { base: "./" }; }, configEnvironment(name, config) { if (!nuxt.options.experimental.viteEnvironmentApi && viteConfig.ssr) { config.optimizeDeps ||= {}; config.optimizeDeps.include = void 0; } if (name === "client") { const outputConfig = config.build?.rollupOptions?.output; return { build: { rollupOptions: { output: { chunkFileNames: outputConfig?.chunkFileNames ?? (nuxt.options.dev ? void 0 : fileNames), entryFileNames: outputConfig?.entryFileNames ?? (nuxt.options.dev ? "entry.js" : fileNames), sourcemapPathTransform: outputConfig?.sourcemapPathTransform ?? ((relativeSourcePath, sourcemapPath) => { if (!isAbsolute(relativeSourcePath)) return relative(clientOutputDir, resolve(dirname(sourcemapPath), relativeSourcePath)); return relativeSourcePath; }) } } } }; } if (name === "ssr") { if (config.build?.rollupOptions?.output && !Array.isArray(config.build.rollupOptions.output)) { config.build.rollupOptions.output.manualChunks = void 0; if (vite.rolldownVersion) config.build.rollupOptions.output.advancedChunks = void 0; } } }, applyToEnvironment(environment) { if (environment.name === "client") return [...nuxt.options.experimental.clientNodeCompat ? [NodeCompatAliasPlugin()] : [], { name: "nuxt:client:aliases", enforce: "post", resolveId: { filter: { id: Object.keys(clientAliases).map((id) => new RegExp("^" + escapeStringRegexp(id) + "$")) }, handler: (source) => clientAliases[source] } }]; else if (environment.name === "ssr") {} return false; } }; } function NodeCompatAliasPlugin() { const nodeCompatAlias = defineEnv({ nodeCompat: true, resolve: true }).env.alias; return { name: "nuxt:client:node-compat-aliases", resolveId: { order: "pre", handler(source) { if (source in nodeCompatAlias) return nodeCompatAlias[source]; } } }; } function ClientManifestPlugin(nuxt) { let clientEntry; let key; let disableCssCodeSplit; return { name: "nuxt:client-manifest", applyToEnvironment: (environment) => environment.name === "ssr", configResolved(config) { clientEntry = resolveClientEntry(config); key = relative(config.root, clientEntry); disableCssCodeSplit = config.build?.cssCodeSplit === false; }, async closeBundle() { const devClientManifest = { "@vite/client": { isEntry: true, file: "@vite/client", css: [], module: true, resourceType: "script" }, ...nuxt.options.features.noScripts === "all" ? {} : { [clientEntry]: { isEntry: true, file: clientEntry, module: true, resourceType: "script" } } }; const clientDist = resolve(nuxt.options.buildDir, "dist/client"); const serverDist = resolve(nuxt.options.buildDir, "dist/server"); const manifestFile = resolve(clientDist, "manifest.json"); const clientManifest = nuxt.options.dev ? devClientManifest : JSON.parse(readFileSync(manifestFile, "utf-8")); const manifestEntries = Object.values(clientManifest); const buildAssetsDir = withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir)); const BASE_RE = new RegExp(`^${escapeStringRegexp(buildAssetsDir)}`); for (const entry of manifestEntries) { entry.file &&= entry.file.replace(BASE_RE, ""); for (const item of ["css", "assets"]) entry[item] &&= entry[item].map((i) => i.replace(BASE_RE, "")); } await mkdir(serverDist, { recursive: true }); if (disableCssCodeSplit) { for (const entry of manifestEntries) if (entry.file?.endsWith(".css")) { clientManifest[key].css ||= []; clientManifest[key].css.push(entry.file); break; } } const manifest = normalizeViteManifest(clientManifest); await nuxt.callHook("build:manifest", manifest); const precomputed = precomputeDependencies(manifest); await writeFile(resolve(serverDist, "client.manifest.mjs"), "export default " + serialize(manifest), "utf8"); await writeFile(resolve(serverDist, "client.precomputed.mjs"), "export default " + serialize(precomputed), "utf8"); if (!nuxt.options.dev) await rm(manifestFile, { force: true }); } }; } const VIRTUAL_RE = /^\0?virtual:(?:nuxt:)?/; function ResolveDeepImportsPlugin(nuxt) { const exclude = [ "virtual:", "\0virtual:", "/__skip_vite", "@vitest/" ]; const conditions = {}; function resolveConditions(environment) { const resolvedConditions = new Set([nuxt.options.dev ? "development" : "production", ...environment.config.resolve.conditions]); if (resolvedConditions.has("browser")) { resolvedConditions.add("web"); resolvedConditions.add("import"); resolvedConditions.add("module"); resolvedConditions.add("default"); } if (environment.config.mode === "test") { resolvedConditions.add("import"); resolvedConditions.add("require"); } return [...resolvedConditions]; } return { name: "nuxt:resolve-bare-imports", enforce: "post", resolveId: { filter: { id: { exclude: [/^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Z]:[/\\]/i, ...exclude.map((e) => new RegExp("^" + escapeStringRegexp(e)))] } }, async handler(id, importer) { if (!importer || !isAbsolute(importer) && !VIRTUAL_RE.test(importer)) return; const normalisedId = resolveAlias(normalize(id), nuxt.options.alias); 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 !== void 0 && res !== null) return res; } } const dir = parseNodeModulePath(normalisedImporter).dir || nuxt.options.appDir; const res = await this.resolve?.(normalisedId, dir, { skipSelf: true }); if (res !== void 0 && res !== null) return res; const environmentConditions = conditions[this.environment.name] ||= resolveConditions(this.environment); const path = resolveModulePath(id, { from: [dir, ...nuxt.options.modulesDir].map((d) => directoryToURL(d)), suffixes: ["", "index"], conditions: environmentConditions, try: true }); if (!path) { logger.debug("Could not resolve id", id, importer); return null; } return normalize(path); } } }; } function ResolveExternalsPlugin(nuxt) { let external = /* @__PURE__ */ new Set(); return { name: "nuxt:resolve-externals", enforce: "pre", config() { external = new Set(nuxt["~runtimeDependencies"]); return { optimizeDeps: { exclude: Array.from(external) } }; }, applyToEnvironment(environment) { if (nuxt.options.dev || environment.name !== "ssr") return false; return { name: "nuxt:resolve-externals:external", resolveId: { filter: { id: [...external].map((dep) => new RegExp("^" + escapeStringRegexp(dep) + "$")) }, async handler(id, importer) { const res = await this.resolve?.(id, importer, { skipSelf: true }); if (res !== void 0 && res !== null) { if (res.id === id) res.id = resolveModulePath(res.id, { try: true, from: importer, extensions: nuxt.options.extensions }) || res.id; return { ...res, external: "absolute" }; } } } }; } }; } const bundle = async (nuxt) => { const useAsyncEntry = nuxt.options.experimental.asyncEntry || nuxt.options.dev; const entry = await resolvePath(resolve(nuxt.options.appDir, useAsyncEntry ? "entry.async" : "entry")); nuxt.options.modulesDir.push(distDir); let allowDirs = [ nuxt.options.appDir, nuxt.options.workspaceDir, ...nuxt.options.modulesDir, ...getLayerDirectories(nuxt).map((d) => d.root), ...Object.values(nuxt.apps).flatMap((app) => [ ...app.components.map((c) => dirname(c.filePath)), ...app.plugins.map((p) => dirname(p.src)), ...app.middleware.map((m) => dirname(m.path)), ...Object.values(app.layouts || {}).map((l) => dirname(l.file)), dirname(nuxt.apps.default.rootComponent), dirname(nuxt.apps.default.errorComponent) ]) ].filter((d) => d && existsSync(d)); for (const dir of allowDirs) allowDirs = allowDirs.filter((d) => !d.startsWith(dir) || d === dir); const { $client, $server, ...viteConfig } = nuxt.options.vite; if (vite.rolldownVersion) { if (viteConfig.esbuild) delete viteConfig.esbuild; if (viteConfig.optimizeDeps?.esbuildOptions) delete viteConfig.optimizeDeps.esbuildOptions; } const mockEmpty = resolveModulePath("mocked-exports/empty", { from: import.meta.url }); const helper = nuxt.options.nitro.imports !== false ? "" : "globalThis."; const isIgnored = createIsIgnored(nuxt); const serverEntry = nuxt.options.ssr ? entry : await resolvePath(resolve(nuxt.options.appDir, "entry-spa")); const config = mergeConfig({ base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : void 0, logLevel: logLevelMap[nuxt.options.logLevel] ?? logLevelMap.info, experimental: { renderBuiltUrl: (filename, { type, hostType, ssr }) => { if (hostType !== "js") return { relative: true }; if (!ssr) { if (type === "asset") return { relative: true }; return { runtime: `globalThis.__publicAssetsURL(${JSON.stringify(filename)})` }; } if (type === "public") return { runtime: `${helper}__publicAssetsURL(${JSON.stringify(filename)})` }; if (type === "asset") { const relativeFilename = filename.replace(withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir)), ""); return { runtime: `${helper}__buildAssetsURL(${JSON.stringify(relativeFilename)})` }; } } }, ...nuxt.options.experimental.viteEnvironmentApi ? { builder: { async buildApp(builder) { const environments = Object.values(builder.environments); for (const environment of environments) { logger.restoreAll(); await builder.build(environment); logger.wrapAll(); await nuxt.callHook("vite:compiled"); } } }, environments: { client: { consumer: "client", keepProcessEnv: false, dev: { warmup: [entry] }, ...clientEnvironment(nuxt, entry) }, ssr: { consumer: "server", dev: { warmup: [serverEntry] }, ...ssrEnvironment(nuxt, serverEntry) } }, ssr: ssr(nuxt) } : {}, resolve: { alias: { [basename(nuxt.options.dir.assets)]: resolve(nuxt.options.srcDir, nuxt.options.dir.assets), ...nuxt.options.alias, "#app": nuxt.options.appDir, "web-streams-polyfill/ponyfill/es2018": mockEmpty, "abort-controller": mockEmpty }, dedupe: ["vue"] }, css: await resolveCSSOptions(nuxt), define: { __NUXT_VERSION__: JSON.stringify(nuxt._version), __NUXT_ASYNC_CONTEXT__: nuxt.options.experimental.asyncContext }, build: { copyPublicDir: false, rollupOptions: { output: { sourcemapIgnoreList: (relativeSourcePath) => { return relativeSourcePath.includes("node_modules") || relativeSourcePath.includes(nuxt.options.buildDir); }, sanitizeFileName: sanitizeFilePath, assetFileNames: nuxt.options.dev ? void 0 : (chunk) => withoutLeadingSlash(join(nuxt.options.app.buildAssetsDir, `${sanitizeFilePath(filename(chunk.names[0]))}.[hash].[ext]`)) } }, watch: vite.rolldownVersion ? { exclude: [...nuxt.options.ignore, /[\\/]node_modules[\\/]/] } : { chokidar: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] }, exclude: nuxt.options.ignore } }, plugins: [ ResolveDeepImportsPlugin(nuxt), ResolveExternalsPlugin(nuxt), ...nuxt.options.experimental.viteEnvironmentApi ? [ vuePlugin(viteConfig.vue), viteJsxPlugin(viteConfig.vueJsx), ViteNodePlugin(nuxt), ClientManifestPlugin(nuxt), DevServerPlugin(nuxt) ] : [], PublicDirsPlugin({ dev: nuxt.options.dev, baseURL: nuxt.options.app.baseURL }), ReplacePlugin(), LayerDepOptimizePlugin(nuxt), SSRStylesPlugin(nuxt), EnvironmentsPlugin(nuxt), ...nuxt.options.experimental.viteEnvironmentApi ? [ VitePluginCheckerPlugin(nuxt), VueFeatureFlagsPlugin(nuxt), SourcemapPreserverPlugin(nuxt), DevStyleSSRPlugin({ srcDir: nuxt.options.srcDir, buildAssetsURL: joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir) }), RuntimePathsPlugin(), TypeCheckPlugin(nuxt), ModulePreloadPolyfillPlugin(), StableEntryPlugin(nuxt), AnalyzePlugin(nuxt) ] : [] ], appType: "custom", server: { middlewareMode: true, watch: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] }, fs: { allow: [...new Set(allowDirs)] } } }, nuxt.options.experimental.viteEnvironmentApi ? { ...viteConfig, environments: { ssr: $server, client: $client } } : viteConfig); if (!nuxt.options.dev) { config.server.watch = void 0; config.build.watch = void 0; } const ctx = { nuxt, entry, config }; await nuxt.callHook("vite:extend", ctx); if (nuxt.options.experimental.viteEnvironmentApi) await handleEnvironments(nuxt, config); else await handleSerialBuilds(nuxt, ctx); }; async function handleEnvironments(nuxt, config) { config.customLogger = createViteLogger(config); config.configFile = false; for (const environment of ["client", "ssr"]) { const environments = { [environment]: config.environments[environment] }; const strippedConfig = { ...config, environments }; const ctx = { isServer: environment === "ssr", isClient: environment === "client" }; await nuxt.hooks.callHook("vite:extendConfig", strippedConfig, ctx); await nuxt.hooks.callHook("vite:configResolved", strippedConfig, ctx); } if (!nuxt.options.dev) { await (await createBuilder(config)).buildApp(); return; } await withLogs(async () => { await (await createServer(config)).environments.ssr.pluginContainer.buildStart({}); }, "Vite dev server built"); await writeDevServer(nuxt); } async function handleSerialBuilds(nuxt, ctx) { nuxt.hook("vite:serverCreated", (server, env) => { if (nuxt.options.vite.warmupEntry !== false) useNitro().hooks.hookOnce("compiled", () => { const start = Date.now(); warmupViteServer(server, [ctx.entry], env.isServer).then(() => logger.info(`Vite ${env.isClient ? "client" : "server"} warmed up in ${Date.now() - start}ms`)).catch(logger.error); }); }); await withLogs(() => buildClient(nuxt, ctx), "Vite client built", nuxt.options.dev); await withLogs(() => buildServer(nuxt, ctx), "Vite server built", nuxt.options.dev); } async function withLogs(fn, message, enabled = true) { if (!enabled) return fn(); const start = performance.now(); await fn(); const duration = performance.now() - start; logger.success(`${message} in ${Math.round(duration)}ms`); } export { bundle };