@nuxt/vite-builder-nightly 4.3.0-29430616.754c35a4 → 4.3.0-29430640.29b20b87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +14 -11
- package/dist/vite-node-entry.d.mts +5 -0
- package/dist/vite-node-entry.d.ts +5 -0
- package/dist/vite-node-entry.mjs +91 -0
- package/dist/vite-node.d.mts +34 -0
- package/dist/vite-node.d.ts +34 -0
- package/dist/vite-node.mjs +248 -0
- package/package.json +13 -9
- package/dist/runtime/client.manifest.d.mts +0 -2
- package/dist/runtime/client.manifest.mjs +0 -4
- package/dist/runtime/vite-node-shared.d.mts +0 -10
- package/dist/runtime/vite-node-shared.mjs +0 -322
- package/dist/runtime/vite-node.d.mts +0 -2
- package/dist/runtime/vite-node.mjs +0 -112
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import fs, { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { performance } from 'node:perf_hooks';
|
|
3
3
|
import * as vite from 'vite';
|
|
4
4
|
import { isCSSRequest, createLogger, mergeConfig, createBuilder, createServer } from 'vite';
|
|
5
|
-
import {
|
|
5
|
+
import { normalize, join, relative, dirname, basename, resolve, isAbsolute } from 'pathe';
|
|
6
6
|
import { tryUseNuxt, useNitro, logger, useNuxt, resolvePath, getLayerDirectories, createIsIgnored } from '@nuxt/kit';
|
|
7
7
|
import { findStaticImports, sanitizeFilePath } from 'mlly';
|
|
8
8
|
import viteJsxPlugin from '@vitejs/plugin-vue-jsx';
|
|
@@ -24,7 +24,7 @@ import { provider, hasTTY, isCI } from 'std-env';
|
|
|
24
24
|
import { colorize } from 'consola/utils';
|
|
25
25
|
import escapeStringRegexp from 'escape-string-regexp';
|
|
26
26
|
import { transform } from 'esbuild';
|
|
27
|
-
import defu from 'defu';
|
|
27
|
+
import { defu } from 'defu';
|
|
28
28
|
import { getPort } from 'get-port-please';
|
|
29
29
|
import { resolveTSConfig, readTSConfig } from 'pkg-types';
|
|
30
30
|
import { serialize } from 'seroval';
|
|
@@ -205,12 +205,6 @@ function ModulePreloadPolyfillPlugin() {
|
|
|
205
205
|
};
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
let _distDir = dirname(fileURLToPath(import.meta.url));
|
|
209
|
-
if (/(?:chunks|shared)$/.test(_distDir)) {
|
|
210
|
-
_distDir = dirname(_distDir);
|
|
211
|
-
}
|
|
212
|
-
const distDir = _distDir;
|
|
213
|
-
|
|
214
208
|
function getManifest(nuxt, viteServer, clientEntry) {
|
|
215
209
|
const css = /* @__PURE__ */ new Set();
|
|
216
210
|
const ssrServer = nuxt.options.experimental.viteEnvironmentApi ? viteServer.environments.ssr : viteServer;
|
|
@@ -557,14 +551,17 @@ function sendError(socket, id, error) {
|
|
|
557
551
|
});
|
|
558
552
|
}
|
|
559
553
|
async function writeDevServer(nuxt) {
|
|
560
|
-
const serverResolvedPath =
|
|
561
|
-
const
|
|
554
|
+
const serverResolvedPath = resolveModulePath("#vite-node-entry", { from: import.meta.url });
|
|
555
|
+
const fetchResolvedPath = resolveModulePath("#vite-node", { from: import.meta.url });
|
|
562
556
|
const serverDist = join(nuxt.options.buildDir, "dist/server");
|
|
563
557
|
await mkdir(serverDist, { recursive: true });
|
|
564
558
|
await Promise.all([
|
|
565
559
|
writeFile(join(serverDist, "server.mjs"), `export { default } from ${JSON.stringify(pathToFileURL(serverResolvedPath).href)}`),
|
|
566
560
|
writeFile(join(serverDist, "client.precomputed.mjs"), `export default undefined`),
|
|
567
|
-
writeFile(join(serverDist, "client.manifest.mjs"), `
|
|
561
|
+
writeFile(join(serverDist, "client.manifest.mjs"), `
|
|
562
|
+
import { viteNodeFetch } from ${JSON.stringify(pathToFileURL(fetchResolvedPath))}
|
|
563
|
+
export default () => viteNodeFetch.getManifest()
|
|
564
|
+
`)
|
|
568
565
|
]);
|
|
569
566
|
}
|
|
570
567
|
|
|
@@ -1924,6 +1921,12 @@ function LayerDepOptimizePlugin(nuxt) {
|
|
|
1924
1921
|
}
|
|
1925
1922
|
}
|
|
1926
1923
|
|
|
1924
|
+
let _distDir = dirname(fileURLToPath(import.meta.url));
|
|
1925
|
+
if (/(?:chunks|shared)$/.test(_distDir)) {
|
|
1926
|
+
_distDir = dirname(_distDir);
|
|
1927
|
+
}
|
|
1928
|
+
const distDir = _distDir;
|
|
1929
|
+
|
|
1927
1930
|
function EnvironmentsPlugin(nuxt) {
|
|
1928
1931
|
const fileNames = withoutLeadingSlash(join(nuxt.options.app.buildAssetsDir, "[hash].js"));
|
|
1929
1932
|
const clientOutputDir = join(useNitro().options.output.publicDir, nuxt.options.app.buildAssetsDir);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { performance } from 'node:perf_hooks';
|
|
3
|
+
import { createError } from 'h3';
|
|
4
|
+
import { ViteNodeRunner } from 'vite-node/client';
|
|
5
|
+
import { consola } from 'consola';
|
|
6
|
+
import { viteNodeOptions, viteNodeFetch } from '#vite-node';
|
|
7
|
+
|
|
8
|
+
const runner = createRunner();
|
|
9
|
+
let render;
|
|
10
|
+
const viteNodeEntry = async (ssrContext) => {
|
|
11
|
+
process.server = true;
|
|
12
|
+
import.meta.server = true;
|
|
13
|
+
const invalidates = await viteNodeFetch.getInvalidates();
|
|
14
|
+
const updates = runner.moduleCache.invalidateDepTree(invalidates);
|
|
15
|
+
const start = performance.now();
|
|
16
|
+
render = updates.has(viteNodeOptions.entryPath) || !render ? (await runner.executeFile(viteNodeOptions.entryPath)).default : render;
|
|
17
|
+
if (updates.size) {
|
|
18
|
+
const time = Math.round((performance.now() - start) * 1e3) / 1e3;
|
|
19
|
+
consola.success(`Vite server hmr ${updates.size} files`, time ? `in ${time}ms` : "");
|
|
20
|
+
}
|
|
21
|
+
const result = await render(ssrContext);
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
function createRunner() {
|
|
25
|
+
return new ViteNodeRunner({
|
|
26
|
+
root: viteNodeOptions.root,
|
|
27
|
+
// Equals to Nuxt `srcDir`
|
|
28
|
+
base: viteNodeOptions.base,
|
|
29
|
+
async resolveId(id, importer) {
|
|
30
|
+
return await viteNodeFetch.resolveId(id, importer);
|
|
31
|
+
},
|
|
32
|
+
async fetchModule(id) {
|
|
33
|
+
id = id.replace(/\/\//g, "/");
|
|
34
|
+
return await viteNodeFetch.fetchModule(id).catch((err) => {
|
|
35
|
+
const errorData = err?.data?.data;
|
|
36
|
+
if (!errorData) {
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
let _err;
|
|
40
|
+
try {
|
|
41
|
+
const { message, stack } = formatViteError(errorData, id);
|
|
42
|
+
_err = createError({
|
|
43
|
+
statusMessage: "Vite Error",
|
|
44
|
+
message,
|
|
45
|
+
stack
|
|
46
|
+
});
|
|
47
|
+
} catch (formatError) {
|
|
48
|
+
consola.warn("Internal nuxt error while formatting vite-node error. Please report this!", formatError);
|
|
49
|
+
const message = `[vite-node] [TransformError] ${errorData?.message || "-"}`;
|
|
50
|
+
consola.error(message, errorData);
|
|
51
|
+
throw createError({
|
|
52
|
+
statusMessage: "Vite Error",
|
|
53
|
+
message,
|
|
54
|
+
stack: `${message}
|
|
55
|
+
at ${id}
|
|
56
|
+
` + (errorData?.stack || "")
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
throw _err;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function formatViteError(errorData, id) {
|
|
65
|
+
const errorCode = errorData.name || errorData.reasonCode || errorData.code;
|
|
66
|
+
const frame = errorData.frame || errorData.source || errorData.pluginCode;
|
|
67
|
+
const getLocId = (locObj = {}) => locObj.file || locObj.id || locObj.url || id || "";
|
|
68
|
+
const getLocPos = (locObj = {}) => locObj.line ? `${locObj.line}:${locObj.column || 0}` : "";
|
|
69
|
+
const locId = getLocId(errorData.loc) || getLocId(errorData.location) || getLocId(errorData.input) || getLocId(errorData);
|
|
70
|
+
const locPos = getLocPos(errorData.loc) || getLocPos(errorData.location) || getLocPos(errorData.input) || getLocPos(errorData);
|
|
71
|
+
const loc = locId.replace(process.cwd(), ".") + (locPos ? `:${locPos}` : "");
|
|
72
|
+
const message = [
|
|
73
|
+
"[vite-node]",
|
|
74
|
+
errorData.plugin && `[plugin:${errorData.plugin}]`,
|
|
75
|
+
errorCode && `[${errorCode}]`,
|
|
76
|
+
loc,
|
|
77
|
+
errorData.reason && `: ${errorData.reason}`,
|
|
78
|
+
frame && `<br><pre>${frame.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre><br>`
|
|
79
|
+
].filter(Boolean).join(" ");
|
|
80
|
+
const stack = [
|
|
81
|
+
message,
|
|
82
|
+
`at ${loc}`,
|
|
83
|
+
errorData.stack
|
|
84
|
+
].filter(Boolean).join("\n");
|
|
85
|
+
return {
|
|
86
|
+
message,
|
|
87
|
+
stack
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { viteNodeEntry as default };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Socket } from 'node:net';
|
|
2
|
+
import { PluginContainer } from 'vite';
|
|
3
|
+
import { FetchResult } from 'vite-node';
|
|
4
|
+
import { Manifest } from 'vue-bundle-renderer';
|
|
5
|
+
|
|
6
|
+
type ResolveIdResponse = Awaited<ReturnType<PluginContainer['resolveId']>>;
|
|
7
|
+
interface ViteNodeFetch {
|
|
8
|
+
/** Gets the client manifest. */
|
|
9
|
+
getManifest(): Promise<Manifest>;
|
|
10
|
+
/** Gets the list of invalidated files. */
|
|
11
|
+
getInvalidates(): Promise<string[]>;
|
|
12
|
+
/** Resolves a module ID. */
|
|
13
|
+
resolveId(id: string, importer?: string): Promise<ResolveIdResponse | null>;
|
|
14
|
+
/** Fetches a module. */
|
|
15
|
+
fetchModule(moduleId: string): Promise<FetchResult>;
|
|
16
|
+
/** Ensures the IPC socket is connected. */
|
|
17
|
+
ensureConnected(): Promise<Socket>;
|
|
18
|
+
}
|
|
19
|
+
type ViteNodeServerOptions = {
|
|
20
|
+
baseURL: string;
|
|
21
|
+
socketPath: string;
|
|
22
|
+
root: string;
|
|
23
|
+
entryPath: string;
|
|
24
|
+
base: string;
|
|
25
|
+
maxRetryAttempts?: number;
|
|
26
|
+
baseRetryDelay?: number;
|
|
27
|
+
maxRetryDelay?: number;
|
|
28
|
+
requestTimeout?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
declare const viteNodeOptions: ViteNodeServerOptions;
|
|
32
|
+
declare const viteNodeFetch: ViteNodeFetch;
|
|
33
|
+
|
|
34
|
+
export { viteNodeFetch, viteNodeOptions };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Socket } from 'node:net';
|
|
2
|
+
import { PluginContainer } from 'vite';
|
|
3
|
+
import { FetchResult } from 'vite-node';
|
|
4
|
+
import { Manifest } from 'vue-bundle-renderer';
|
|
5
|
+
|
|
6
|
+
type ResolveIdResponse = Awaited<ReturnType<PluginContainer['resolveId']>>;
|
|
7
|
+
interface ViteNodeFetch {
|
|
8
|
+
/** Gets the client manifest. */
|
|
9
|
+
getManifest(): Promise<Manifest>;
|
|
10
|
+
/** Gets the list of invalidated files. */
|
|
11
|
+
getInvalidates(): Promise<string[]>;
|
|
12
|
+
/** Resolves a module ID. */
|
|
13
|
+
resolveId(id: string, importer?: string): Promise<ResolveIdResponse | null>;
|
|
14
|
+
/** Fetches a module. */
|
|
15
|
+
fetchModule(moduleId: string): Promise<FetchResult>;
|
|
16
|
+
/** Ensures the IPC socket is connected. */
|
|
17
|
+
ensureConnected(): Promise<Socket>;
|
|
18
|
+
}
|
|
19
|
+
type ViteNodeServerOptions = {
|
|
20
|
+
baseURL: string;
|
|
21
|
+
socketPath: string;
|
|
22
|
+
root: string;
|
|
23
|
+
entryPath: string;
|
|
24
|
+
base: string;
|
|
25
|
+
maxRetryAttempts?: number;
|
|
26
|
+
baseRetryDelay?: number;
|
|
27
|
+
maxRetryDelay?: number;
|
|
28
|
+
requestTimeout?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
declare const viteNodeOptions: ViteNodeServerOptions;
|
|
32
|
+
declare const viteNodeFetch: ViteNodeFetch;
|
|
33
|
+
|
|
34
|
+
export { viteNodeFetch, viteNodeOptions };
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import { Buffer } from 'node:buffer';
|
|
4
|
+
import { isTest } from 'std-env';
|
|
5
|
+
|
|
6
|
+
const viteNodeOptions = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS || "{}");
|
|
7
|
+
const pendingRequests = /* @__PURE__ */ new Map();
|
|
8
|
+
let requestIdCounter = 0;
|
|
9
|
+
let clientSocket;
|
|
10
|
+
let currentConnectPromise;
|
|
11
|
+
const MAX_RETRY_ATTEMPTS = viteNodeOptions.maxRetryAttempts ?? 5;
|
|
12
|
+
const BASE_RETRY_DELAY_MS = viteNodeOptions.baseRetryDelay ?? 100;
|
|
13
|
+
const MAX_RETRY_DELAY_MS = viteNodeOptions.maxRetryDelay ?? 2e3;
|
|
14
|
+
const REQUEST_TIMEOUT_MS = viteNodeOptions.requestTimeout ?? 6e4;
|
|
15
|
+
function calculateRetryDelay(attempt) {
|
|
16
|
+
const exponentialDelay = BASE_RETRY_DELAY_MS * Math.pow(2, attempt);
|
|
17
|
+
const jitter = Math.random() * 0.1 * exponentialDelay;
|
|
18
|
+
return Math.min(exponentialDelay + jitter, MAX_RETRY_DELAY_MS);
|
|
19
|
+
}
|
|
20
|
+
function connectSocket() {
|
|
21
|
+
if (clientSocket && !clientSocket.destroyed) {
|
|
22
|
+
return Promise.resolve(clientSocket);
|
|
23
|
+
}
|
|
24
|
+
if (currentConnectPromise) {
|
|
25
|
+
return currentConnectPromise;
|
|
26
|
+
}
|
|
27
|
+
const thisPromise = new Promise((resolve, reject) => {
|
|
28
|
+
if (!viteNodeOptions.socketPath) {
|
|
29
|
+
console.error("vite-node-shared: NUXT_VITE_NODE_OPTIONS.socketPath is not defined.");
|
|
30
|
+
return reject(new Error("Vite Node IPC socket path not configured."));
|
|
31
|
+
}
|
|
32
|
+
const attemptConnection = (attempt = 0) => {
|
|
33
|
+
const socket = net.createConnection(viteNodeOptions.socketPath);
|
|
34
|
+
const INITIAL_BUFFER_SIZE = 64 * 1024;
|
|
35
|
+
const MAX_BUFFER_SIZE = 1024 * 1024 * 1024;
|
|
36
|
+
let buffer = Buffer.alloc(INITIAL_BUFFER_SIZE);
|
|
37
|
+
let writeOffset = 0;
|
|
38
|
+
let readOffset = 0;
|
|
39
|
+
socket.setNoDelay(true);
|
|
40
|
+
socket.setKeepAlive(true, 3e4);
|
|
41
|
+
const cleanup = () => {
|
|
42
|
+
socket.off("connect", onConnect);
|
|
43
|
+
socket.off("data", onData);
|
|
44
|
+
socket.off("error", onError);
|
|
45
|
+
socket.off("close", onClose);
|
|
46
|
+
};
|
|
47
|
+
const resetBuffer = () => {
|
|
48
|
+
writeOffset = 0;
|
|
49
|
+
readOffset = 0;
|
|
50
|
+
};
|
|
51
|
+
const compactBuffer = () => {
|
|
52
|
+
if (readOffset > 0) {
|
|
53
|
+
const remainingData = writeOffset - readOffset;
|
|
54
|
+
if (remainingData > 0) {
|
|
55
|
+
buffer.copy(buffer, 0, readOffset, writeOffset);
|
|
56
|
+
}
|
|
57
|
+
writeOffset = remainingData;
|
|
58
|
+
readOffset = 0;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const ensureBufferCapacity = (additionalBytes) => {
|
|
62
|
+
const requiredSize = writeOffset + additionalBytes;
|
|
63
|
+
if (requiredSize > MAX_BUFFER_SIZE) {
|
|
64
|
+
throw new Error(`Buffer size limit exceeded: ${requiredSize} > ${MAX_BUFFER_SIZE}`);
|
|
65
|
+
}
|
|
66
|
+
if (requiredSize > buffer.length) {
|
|
67
|
+
compactBuffer();
|
|
68
|
+
if (writeOffset + additionalBytes > buffer.length) {
|
|
69
|
+
const newSize = Math.min(
|
|
70
|
+
Math.max(buffer.length * 2, requiredSize),
|
|
71
|
+
MAX_BUFFER_SIZE
|
|
72
|
+
);
|
|
73
|
+
const newBuffer = Buffer.alloc(newSize);
|
|
74
|
+
buffer.copy(newBuffer, 0, 0, writeOffset);
|
|
75
|
+
buffer = newBuffer;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const onConnect = () => {
|
|
80
|
+
clientSocket = socket;
|
|
81
|
+
resolve(socket);
|
|
82
|
+
};
|
|
83
|
+
const onData = (data) => {
|
|
84
|
+
try {
|
|
85
|
+
ensureBufferCapacity(data.length);
|
|
86
|
+
data.copy(buffer, writeOffset);
|
|
87
|
+
writeOffset += data.length;
|
|
88
|
+
while (writeOffset - readOffset >= 4) {
|
|
89
|
+
const messageLength = buffer.readUInt32BE(readOffset);
|
|
90
|
+
if (writeOffset - readOffset < 4 + messageLength) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const message = buffer.subarray(readOffset + 4, readOffset + 4 + messageLength).toString("utf-8");
|
|
94
|
+
readOffset += 4 + messageLength;
|
|
95
|
+
try {
|
|
96
|
+
const response = JSON.parse(message);
|
|
97
|
+
const requestHandlers = pendingRequests.get(response.id);
|
|
98
|
+
if (requestHandlers) {
|
|
99
|
+
const { resolve: resolveRequest, reject: rejectRequest } = requestHandlers;
|
|
100
|
+
if (response.type === "error") {
|
|
101
|
+
const err = new Error(response.error.message);
|
|
102
|
+
err.stack = response.error.stack;
|
|
103
|
+
err.data = response.error.data;
|
|
104
|
+
err.statusCode = response.error.statusCode;
|
|
105
|
+
rejectRequest(err);
|
|
106
|
+
} else {
|
|
107
|
+
resolveRequest(response.data);
|
|
108
|
+
}
|
|
109
|
+
pendingRequests.delete(response.id);
|
|
110
|
+
}
|
|
111
|
+
} catch (parseError) {
|
|
112
|
+
console.warn("vite-node-shared: Failed to parse IPC response:", parseError);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (readOffset > buffer.length / 2) {
|
|
116
|
+
compactBuffer();
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
socket.destroy(error instanceof Error ? error : new Error("Buffer management error"));
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const onError = (err) => {
|
|
123
|
+
cleanup();
|
|
124
|
+
resetBuffer();
|
|
125
|
+
if (attempt < MAX_RETRY_ATTEMPTS) {
|
|
126
|
+
const delay = calculateRetryDelay(attempt);
|
|
127
|
+
setTimeout(() => attemptConnection(attempt + 1), delay);
|
|
128
|
+
} else {
|
|
129
|
+
if (currentConnectPromise === thisPromise) {
|
|
130
|
+
reject(err);
|
|
131
|
+
}
|
|
132
|
+
for (const { reject: rejectRequest } of pendingRequests.values()) {
|
|
133
|
+
rejectRequest(err);
|
|
134
|
+
}
|
|
135
|
+
pendingRequests.clear();
|
|
136
|
+
if (clientSocket === socket) {
|
|
137
|
+
clientSocket = void 0;
|
|
138
|
+
}
|
|
139
|
+
if (currentConnectPromise === thisPromise) {
|
|
140
|
+
currentConnectPromise = void 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const onClose = () => {
|
|
145
|
+
cleanup();
|
|
146
|
+
resetBuffer();
|
|
147
|
+
for (const { reject: rejectRequest } of pendingRequests.values()) {
|
|
148
|
+
rejectRequest(new Error("IPC connection closed"));
|
|
149
|
+
}
|
|
150
|
+
pendingRequests.clear();
|
|
151
|
+
if (clientSocket === socket) {
|
|
152
|
+
clientSocket = void 0;
|
|
153
|
+
}
|
|
154
|
+
if (currentConnectPromise === thisPromise) {
|
|
155
|
+
currentConnectPromise = void 0;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
socket.on("connect", onConnect);
|
|
159
|
+
socket.on("data", onData);
|
|
160
|
+
socket.on("error", onError);
|
|
161
|
+
socket.on("close", onClose);
|
|
162
|
+
};
|
|
163
|
+
attemptConnection();
|
|
164
|
+
});
|
|
165
|
+
currentConnectPromise = thisPromise;
|
|
166
|
+
return currentConnectPromise;
|
|
167
|
+
}
|
|
168
|
+
async function sendRequest(type, payload) {
|
|
169
|
+
const requestId = requestIdCounter++;
|
|
170
|
+
let lastError;
|
|
171
|
+
for (let requestAttempt = 0; requestAttempt <= MAX_RETRY_ATTEMPTS; requestAttempt++) {
|
|
172
|
+
try {
|
|
173
|
+
const socket = await connectSocket();
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const timeoutId = setTimeout(() => {
|
|
176
|
+
pendingRequests.delete(requestId);
|
|
177
|
+
reject(new Error(`Request timeout after ${REQUEST_TIMEOUT_MS}ms for type: ${type}`));
|
|
178
|
+
}, REQUEST_TIMEOUT_MS);
|
|
179
|
+
pendingRequests.set(requestId, {
|
|
180
|
+
resolve: (value) => {
|
|
181
|
+
clearTimeout(timeoutId);
|
|
182
|
+
resolve(value);
|
|
183
|
+
},
|
|
184
|
+
reject: (reason) => {
|
|
185
|
+
clearTimeout(timeoutId);
|
|
186
|
+
reject(reason);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
const message = JSON.stringify({ id: requestId, type, payload });
|
|
190
|
+
const messageBuffer = Buffer.from(message, "utf-8");
|
|
191
|
+
const messageLength = messageBuffer.length;
|
|
192
|
+
const fullMessage = Buffer.alloc(4 + messageLength);
|
|
193
|
+
fullMessage.writeUInt32BE(messageLength, 0);
|
|
194
|
+
messageBuffer.copy(fullMessage, 4);
|
|
195
|
+
try {
|
|
196
|
+
socket.write(fullMessage);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
clearTimeout(timeoutId);
|
|
199
|
+
pendingRequests.delete(requestId);
|
|
200
|
+
reject(error);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
} catch (error) {
|
|
204
|
+
lastError = error;
|
|
205
|
+
if (requestAttempt < MAX_RETRY_ATTEMPTS) {
|
|
206
|
+
const delay = calculateRetryDelay(requestAttempt);
|
|
207
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
208
|
+
if (clientSocket) {
|
|
209
|
+
clientSocket.destroy();
|
|
210
|
+
clientSocket = void 0;
|
|
211
|
+
}
|
|
212
|
+
currentConnectPromise = void 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
throw lastError || new Error("Request failed after all retry attempts");
|
|
217
|
+
}
|
|
218
|
+
const viteNodeFetch = {
|
|
219
|
+
getManifest() {
|
|
220
|
+
return sendRequest("manifest", void 0);
|
|
221
|
+
},
|
|
222
|
+
getInvalidates() {
|
|
223
|
+
return sendRequest("invalidates", void 0);
|
|
224
|
+
},
|
|
225
|
+
resolveId(id, importer) {
|
|
226
|
+
return sendRequest("resolve", { id, importer });
|
|
227
|
+
},
|
|
228
|
+
fetchModule(moduleId) {
|
|
229
|
+
return sendRequest("module", { moduleId });
|
|
230
|
+
},
|
|
231
|
+
ensureConnected() {
|
|
232
|
+
return connectSocket();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
let preConnectAttempted = false;
|
|
236
|
+
function preConnect() {
|
|
237
|
+
if (preConnectAttempted || !viteNodeOptions.socketPath) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
preConnectAttempted = true;
|
|
241
|
+
return connectSocket().catch(() => {
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
if (typeof process !== "undefined" && !isTest) {
|
|
245
|
+
setTimeout(preConnect, 100);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export { viteNodeFetch, viteNodeOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxt/vite-builder-nightly",
|
|
3
|
-
"version": "4.3.0-
|
|
3
|
+
"version": "4.3.0-29430640.29b20b87",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/nuxt/nuxt.git",
|
|
@@ -17,23 +17,27 @@
|
|
|
17
17
|
"import": "./dist/index.mjs"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
+
"imports": {
|
|
21
|
+
"#vite-node": "./dist/vite-node.mjs",
|
|
22
|
+
"#vite-node-entry": "./dist/vite-node-entry.mjs"
|
|
23
|
+
},
|
|
20
24
|
"files": [
|
|
21
25
|
"dist"
|
|
22
26
|
],
|
|
23
27
|
"devDependencies": {
|
|
24
|
-
"@nuxt/schema": "npm:@nuxt/schema-nightly@4.3.0-
|
|
28
|
+
"@nuxt/schema": "npm:@nuxt/schema-nightly@4.3.0-29430640.29b20b87",
|
|
25
29
|
"nitropack": "2.12.9",
|
|
26
|
-
"rolldown": "1.0.0-beta.
|
|
27
|
-
"rollup": "4.53.
|
|
30
|
+
"rolldown": "1.0.0-beta.54",
|
|
31
|
+
"rollup": "4.53.4",
|
|
28
32
|
"unbuild": "3.6.1",
|
|
29
33
|
"vue": "3.5.25"
|
|
30
34
|
},
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@nuxt/kit": "npm:@nuxt/kit-nightly@4.3.0-
|
|
36
|
+
"@nuxt/kit": "npm:@nuxt/kit-nightly@4.3.0-29430640.29b20b87",
|
|
33
37
|
"@rollup/plugin-replace": "^6.0.3",
|
|
34
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
38
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
35
39
|
"@vitejs/plugin-vue-jsx": "^5.1.2",
|
|
36
|
-
"autoprefixer": "^10.4.
|
|
40
|
+
"autoprefixer": "^10.4.23",
|
|
37
41
|
"consola": "^3.4.2",
|
|
38
42
|
"cssnano": "^7.1.2",
|
|
39
43
|
"defu": "^6.1.4",
|
|
@@ -55,13 +59,13 @@
|
|
|
55
59
|
"std-env": "^3.10.0",
|
|
56
60
|
"ufo": "^1.6.1",
|
|
57
61
|
"unenv": "^2.0.0-rc.24",
|
|
58
|
-
"vite": "^7.
|
|
62
|
+
"vite": "^7.3.0",
|
|
59
63
|
"vite-node": "^5.2.0",
|
|
60
64
|
"vite-plugin-checker": "^0.12.0",
|
|
61
65
|
"vue-bundle-renderer": "^2.2.0"
|
|
62
66
|
},
|
|
63
67
|
"peerDependencies": {
|
|
64
|
-
"nuxt": "npm:nuxt-nightly@4.3.0-
|
|
68
|
+
"nuxt": "npm:nuxt-nightly@4.3.0-29430640.29b20b87",
|
|
65
69
|
"rolldown": "^1.0.0-beta.38",
|
|
66
70
|
"vue": "^3.3.4"
|
|
67
71
|
},
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/** @typedef {import('node:net').Socket} Socket */
|
|
2
|
-
/** @typedef {import('../plugins/vite-node').ViteNodeFetch} ViteNodeFetch */
|
|
3
|
-
/** @type {import('../plugins/vite-node').ViteNodeServerOptions} */
|
|
4
|
-
export const viteNodeOptions: import("../plugins/vite-node").ViteNodeServerOptions;
|
|
5
|
-
/**
|
|
6
|
-
* @type {ViteNodeFetch}
|
|
7
|
-
*/
|
|
8
|
-
export const viteNodeFetch: ViteNodeFetch;
|
|
9
|
-
export type Socket = import("node:net").Socket;
|
|
10
|
-
export type ViteNodeFetch = import("../plugins/vite-node").ViteNodeFetch;
|
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import net from 'node:net'
|
|
4
|
-
import { Buffer } from 'node:buffer'
|
|
5
|
-
import { isTest } from 'std-env'
|
|
6
|
-
|
|
7
|
-
/** @typedef {import('node:net').Socket} Socket */
|
|
8
|
-
/** @typedef {import('../plugins/vite-node').ViteNodeFetch} ViteNodeFetch */
|
|
9
|
-
|
|
10
|
-
/** @type {import('../plugins/vite-node').ViteNodeServerOptions} */
|
|
11
|
-
export const viteNodeOptions = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS || '{}')
|
|
12
|
-
|
|
13
|
-
/** @type {Map<number, { resolve: (value: any) => void, reject: (reason?: any) => void }>} */
|
|
14
|
-
const pendingRequests = new Map()
|
|
15
|
-
let requestIdCounter = 0
|
|
16
|
-
/** @type {Socket | undefined} */
|
|
17
|
-
let clientSocket
|
|
18
|
-
/** @type {Promise<Socket> | undefined} */
|
|
19
|
-
let currentConnectPromise
|
|
20
|
-
const MAX_RETRY_ATTEMPTS = viteNodeOptions.maxRetryAttempts ?? 5
|
|
21
|
-
const BASE_RETRY_DELAY_MS = viteNodeOptions.baseRetryDelay ?? 100
|
|
22
|
-
const MAX_RETRY_DELAY_MS = viteNodeOptions.maxRetryDelay ?? 2000
|
|
23
|
-
const REQUEST_TIMEOUT_MS = viteNodeOptions.requestTimeout ?? 60000
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Calculates exponential backoff delay with jitter.
|
|
27
|
-
* @param {number} attempt - The current attempt number (0-based).
|
|
28
|
-
* @returns {number} Delay in milliseconds.
|
|
29
|
-
*/
|
|
30
|
-
function calculateRetryDelay (attempt) {
|
|
31
|
-
const exponentialDelay = BASE_RETRY_DELAY_MS * Math.pow(2, attempt)
|
|
32
|
-
const jitter = Math.random() * 0.1 * exponentialDelay // Add 10% jitter
|
|
33
|
-
return Math.min(exponentialDelay + jitter, MAX_RETRY_DELAY_MS)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Establishes or returns an existing IPC socket connection with retry logic.
|
|
38
|
-
* @returns {Promise<Socket>} A promise that resolves with the connected socket.
|
|
39
|
-
*/
|
|
40
|
-
function connectSocket () {
|
|
41
|
-
if (clientSocket && !clientSocket.destroyed) {
|
|
42
|
-
return Promise.resolve(clientSocket)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (currentConnectPromise) {
|
|
46
|
-
return currentConnectPromise
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const thisPromise = new Promise((resolve, reject) => {
|
|
50
|
-
if (!viteNodeOptions.socketPath) {
|
|
51
|
-
console.error('vite-node-shared: NUXT_VITE_NODE_OPTIONS.socketPath is not defined.')
|
|
52
|
-
return reject(new Error('Vite Node IPC socket path not configured.'))
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const attemptConnection = (attempt = 0) => {
|
|
56
|
-
const socket = net.createConnection(viteNodeOptions.socketPath)
|
|
57
|
-
|
|
58
|
-
const INITIAL_BUFFER_SIZE = 64 * 1024 // 64KB
|
|
59
|
-
const MAX_BUFFER_SIZE = 1024 * 1024 * 1024 // 1GB
|
|
60
|
-
|
|
61
|
-
let buffer = Buffer.alloc(INITIAL_BUFFER_SIZE)
|
|
62
|
-
let writeOffset = 0
|
|
63
|
-
let readOffset = 0
|
|
64
|
-
|
|
65
|
-
// optimize socket for high-frequency IPC
|
|
66
|
-
socket.setNoDelay(true)
|
|
67
|
-
socket.setKeepAlive(true, 30000) // 30s
|
|
68
|
-
|
|
69
|
-
const cleanup = () => {
|
|
70
|
-
socket.off('connect', onConnect)
|
|
71
|
-
socket.off('data', onData)
|
|
72
|
-
socket.off('error', onError)
|
|
73
|
-
socket.off('close', onClose)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const resetBuffer = () => {
|
|
77
|
-
writeOffset = 0
|
|
78
|
-
readOffset = 0
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const compactBuffer = () => {
|
|
82
|
-
if (readOffset > 0) {
|
|
83
|
-
const remainingData = writeOffset - readOffset
|
|
84
|
-
if (remainingData > 0) {
|
|
85
|
-
buffer.copy(buffer, 0, readOffset, writeOffset)
|
|
86
|
-
}
|
|
87
|
-
writeOffset = remainingData
|
|
88
|
-
readOffset = 0
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* @param {number} additionalBytes
|
|
94
|
-
*/
|
|
95
|
-
const ensureBufferCapacity = (additionalBytes) => {
|
|
96
|
-
const requiredSize = writeOffset + additionalBytes
|
|
97
|
-
|
|
98
|
-
if (requiredSize > MAX_BUFFER_SIZE) {
|
|
99
|
-
throw new Error(`Buffer size limit exceeded: ${requiredSize} > ${MAX_BUFFER_SIZE}`)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (requiredSize > buffer.length) {
|
|
103
|
-
// Try compacting first
|
|
104
|
-
compactBuffer()
|
|
105
|
-
|
|
106
|
-
// ... then if we still need more space, grow the buffer
|
|
107
|
-
if (writeOffset + additionalBytes > buffer.length) {
|
|
108
|
-
const newSize = Math.min(
|
|
109
|
-
Math.max(buffer.length * 2, requiredSize),
|
|
110
|
-
MAX_BUFFER_SIZE,
|
|
111
|
-
)
|
|
112
|
-
const newBuffer = Buffer.alloc(newSize)
|
|
113
|
-
buffer.copy(newBuffer, 0, 0, writeOffset)
|
|
114
|
-
buffer = newBuffer
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const onConnect = () => {
|
|
120
|
-
clientSocket = socket
|
|
121
|
-
resolve(socket)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** @param {Buffer} data */
|
|
125
|
-
const onData = (data) => {
|
|
126
|
-
try {
|
|
127
|
-
ensureBufferCapacity(data.length)
|
|
128
|
-
data.copy(buffer, writeOffset)
|
|
129
|
-
writeOffset += data.length
|
|
130
|
-
|
|
131
|
-
while (writeOffset - readOffset >= 4) {
|
|
132
|
-
const messageLength = buffer.readUInt32BE(readOffset)
|
|
133
|
-
|
|
134
|
-
if (writeOffset - readOffset < 4 + messageLength) {
|
|
135
|
-
return // Wait for more data
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const message = buffer.subarray(readOffset + 4, readOffset + 4 + messageLength).toString('utf-8')
|
|
139
|
-
readOffset += 4 + messageLength
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const response = JSON.parse(message)
|
|
143
|
-
const requestHandlers = pendingRequests.get(response.id)
|
|
144
|
-
if (requestHandlers) {
|
|
145
|
-
const { resolve: resolveRequest, reject: rejectRequest } = requestHandlers
|
|
146
|
-
if (response.type === 'error') {
|
|
147
|
-
const err = new Error(response.error.message)
|
|
148
|
-
// @ts-ignore We are augmenting the error object
|
|
149
|
-
err.stack = response.error.stack
|
|
150
|
-
// @ts-ignore
|
|
151
|
-
err.data = response.error.data
|
|
152
|
-
// @ts-ignore
|
|
153
|
-
err.statusCode = response.error.statusCode
|
|
154
|
-
rejectRequest(err)
|
|
155
|
-
} else {
|
|
156
|
-
resolveRequest(response.data)
|
|
157
|
-
}
|
|
158
|
-
pendingRequests.delete(response.id)
|
|
159
|
-
}
|
|
160
|
-
} catch (parseError) {
|
|
161
|
-
console.warn('vite-node-shared: Failed to parse IPC response:', parseError)
|
|
162
|
-
// ignore malformed messages
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// compact buffer periodically to prevent memory waste
|
|
167
|
-
if (readOffset > buffer.length / 2) {
|
|
168
|
-
compactBuffer()
|
|
169
|
-
}
|
|
170
|
-
} catch (error) {
|
|
171
|
-
socket.destroy(error instanceof Error ? error : new Error('Buffer management error'))
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/** @param {Error} err */
|
|
176
|
-
const onError = (err) => {
|
|
177
|
-
cleanup()
|
|
178
|
-
resetBuffer()
|
|
179
|
-
|
|
180
|
-
if (attempt < MAX_RETRY_ATTEMPTS) {
|
|
181
|
-
const delay = calculateRetryDelay(attempt)
|
|
182
|
-
setTimeout(() => attemptConnection(attempt + 1), delay)
|
|
183
|
-
} else {
|
|
184
|
-
if (currentConnectPromise === thisPromise) {
|
|
185
|
-
reject(err)
|
|
186
|
-
}
|
|
187
|
-
for (const { reject: rejectRequest } of pendingRequests.values()) {
|
|
188
|
-
rejectRequest(err)
|
|
189
|
-
}
|
|
190
|
-
pendingRequests.clear()
|
|
191
|
-
if (clientSocket === socket) { clientSocket = undefined }
|
|
192
|
-
if (currentConnectPromise === thisPromise) { currentConnectPromise = undefined }
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const onClose = () => {
|
|
197
|
-
cleanup()
|
|
198
|
-
resetBuffer()
|
|
199
|
-
for (const { reject: rejectRequest } of pendingRequests.values()) {
|
|
200
|
-
rejectRequest(new Error('IPC connection closed'))
|
|
201
|
-
}
|
|
202
|
-
pendingRequests.clear()
|
|
203
|
-
if (clientSocket === socket) { clientSocket = undefined }
|
|
204
|
-
if (currentConnectPromise === thisPromise) { currentConnectPromise = undefined }
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
socket.on('connect', onConnect)
|
|
208
|
-
socket.on('data', onData)
|
|
209
|
-
socket.on('error', onError)
|
|
210
|
-
socket.on('close', onClose)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
attemptConnection()
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
currentConnectPromise = thisPromise
|
|
217
|
-
return currentConnectPromise
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Sends a request over the IPC socket with automatic reconnection.
|
|
222
|
-
* @template {keyof import('../plugins/vite-node').ViteNodeRequestMap} T
|
|
223
|
-
* @param {T} type - The type of the request.
|
|
224
|
-
* @param {import('../plugins/vite-node').ViteNodeRequestMap[T]['request']} [payload] - The payload for the request.
|
|
225
|
-
* @returns {Promise<import('../plugins/vite-node').ViteNodeRequestMap[T]['response']>} A promise that resolves with the response data.
|
|
226
|
-
*/
|
|
227
|
-
async function sendRequest (type, payload) {
|
|
228
|
-
const requestId = requestIdCounter++
|
|
229
|
-
let lastError
|
|
230
|
-
|
|
231
|
-
// retry the entire request (including reconnection) up to MAX_RETRY_ATTEMPTS times
|
|
232
|
-
for (let requestAttempt = 0; requestAttempt <= MAX_RETRY_ATTEMPTS; requestAttempt++) {
|
|
233
|
-
try {
|
|
234
|
-
const socket = await connectSocket()
|
|
235
|
-
|
|
236
|
-
return new Promise((resolve, reject) => {
|
|
237
|
-
const timeoutId = setTimeout(() => {
|
|
238
|
-
pendingRequests.delete(requestId)
|
|
239
|
-
reject(new Error(`Request timeout after ${REQUEST_TIMEOUT_MS}ms for type: ${type}`))
|
|
240
|
-
}, REQUEST_TIMEOUT_MS)
|
|
241
|
-
|
|
242
|
-
pendingRequests.set(requestId, {
|
|
243
|
-
resolve: (value) => {
|
|
244
|
-
clearTimeout(timeoutId)
|
|
245
|
-
resolve(value)
|
|
246
|
-
},
|
|
247
|
-
reject: (reason) => {
|
|
248
|
-
clearTimeout(timeoutId)
|
|
249
|
-
reject(reason)
|
|
250
|
-
},
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
const message = JSON.stringify({ id: requestId, type, payload })
|
|
254
|
-
const messageBuffer = Buffer.from(message, 'utf-8')
|
|
255
|
-
const messageLength = messageBuffer.length
|
|
256
|
-
|
|
257
|
-
// pre-allocate single buffer for length + message to avoid Buffer.concat()
|
|
258
|
-
const fullMessage = Buffer.alloc(4 + messageLength)
|
|
259
|
-
fullMessage.writeUInt32BE(messageLength, 0)
|
|
260
|
-
messageBuffer.copy(fullMessage, 4)
|
|
261
|
-
|
|
262
|
-
try {
|
|
263
|
-
socket.write(fullMessage)
|
|
264
|
-
} catch (error) {
|
|
265
|
-
clearTimeout(timeoutId)
|
|
266
|
-
pendingRequests.delete(requestId)
|
|
267
|
-
reject(error)
|
|
268
|
-
}
|
|
269
|
-
})
|
|
270
|
-
} catch (error) {
|
|
271
|
-
lastError = error
|
|
272
|
-
if (requestAttempt < MAX_RETRY_ATTEMPTS) {
|
|
273
|
-
const delay = calculateRetryDelay(requestAttempt)
|
|
274
|
-
await new Promise(resolve => setTimeout(resolve, delay))
|
|
275
|
-
// clear current connection state to force reconnection
|
|
276
|
-
if (clientSocket) {
|
|
277
|
-
clientSocket.destroy()
|
|
278
|
-
clientSocket = undefined
|
|
279
|
-
}
|
|
280
|
-
currentConnectPromise = undefined
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
throw lastError || new Error('Request failed after all retry attempts')
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* @type {ViteNodeFetch}
|
|
290
|
-
*/
|
|
291
|
-
export const viteNodeFetch = {
|
|
292
|
-
getManifest () {
|
|
293
|
-
return sendRequest('manifest')
|
|
294
|
-
},
|
|
295
|
-
getInvalidates () {
|
|
296
|
-
return sendRequest('invalidates')
|
|
297
|
-
},
|
|
298
|
-
resolveId (id, importer) {
|
|
299
|
-
return sendRequest('resolve', { id, importer })
|
|
300
|
-
},
|
|
301
|
-
fetchModule (moduleId) {
|
|
302
|
-
return sendRequest('module', { moduleId })
|
|
303
|
-
},
|
|
304
|
-
ensureConnected () {
|
|
305
|
-
return connectSocket()
|
|
306
|
-
},
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// attempt to pre-establish the IPC connection to reduce latency on first request
|
|
310
|
-
let preConnectAttempted = false
|
|
311
|
-
function preConnect () {
|
|
312
|
-
if (preConnectAttempted || !viteNodeOptions.socketPath) {
|
|
313
|
-
return
|
|
314
|
-
}
|
|
315
|
-
preConnectAttempted = true
|
|
316
|
-
|
|
317
|
-
return connectSocket().catch(() => {})
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (typeof process !== 'undefined' && !isTest) {
|
|
321
|
-
setTimeout(preConnect, 100)
|
|
322
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import process from 'node:process'
|
|
4
|
-
import { performance } from 'node:perf_hooks'
|
|
5
|
-
import { createError } from 'h3'
|
|
6
|
-
import { ViteNodeRunner } from 'vite-node/client'
|
|
7
|
-
import { consola } from 'consola'
|
|
8
|
-
import { viteNodeFetch, viteNodeOptions } from './vite-node-shared.mjs'
|
|
9
|
-
|
|
10
|
-
const runner = createRunner()
|
|
11
|
-
|
|
12
|
-
/** @type {(ssrContext: import('#app').NuxtSSRContext) => Promise<any>} */
|
|
13
|
-
let render
|
|
14
|
-
|
|
15
|
-
/** @param {import('#app').NuxtSSRContext} ssrContext */
|
|
16
|
-
export default async (ssrContext) => {
|
|
17
|
-
// Workaround for stub mode
|
|
18
|
-
// https://github.com/nuxt/framework/pull/3983
|
|
19
|
-
// eslint-disable-next-line nuxt/prefer-import-meta,@typescript-eslint/no-deprecated
|
|
20
|
-
process.server = true
|
|
21
|
-
import.meta.server = true
|
|
22
|
-
|
|
23
|
-
// Invalidate cache for files changed since last rendering
|
|
24
|
-
const invalidates = await viteNodeFetch.getInvalidates()
|
|
25
|
-
const updates = runner.moduleCache.invalidateDepTree(invalidates)
|
|
26
|
-
|
|
27
|
-
// Execute SSR bundle on demand
|
|
28
|
-
const start = performance.now()
|
|
29
|
-
render = (updates.has(viteNodeOptions.entryPath) || !render) ? (await runner.executeFile(viteNodeOptions.entryPath)).default : render
|
|
30
|
-
if (updates.size) {
|
|
31
|
-
const time = Math.round((performance.now() - start) * 1000) / 1000
|
|
32
|
-
consola.success(`Vite server hmr ${updates.size} files`, time ? `in ${time}ms` : '')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const result = await render(ssrContext)
|
|
36
|
-
return result
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function createRunner () {
|
|
40
|
-
return new ViteNodeRunner({
|
|
41
|
-
root: viteNodeOptions.root, // Equals to Nuxt `srcDir`
|
|
42
|
-
base: viteNodeOptions.base,
|
|
43
|
-
async resolveId (id, importer) {
|
|
44
|
-
return await viteNodeFetch.resolveId(id, importer)
|
|
45
|
-
},
|
|
46
|
-
async fetchModule (id) {
|
|
47
|
-
id = id.replace(/\/\//g, '/') // TODO: fix in vite-node
|
|
48
|
-
return await viteNodeFetch.fetchModule(id).catch((err) => {
|
|
49
|
-
const errorData = err?.data?.data
|
|
50
|
-
if (!errorData) {
|
|
51
|
-
throw err
|
|
52
|
-
}
|
|
53
|
-
let _err
|
|
54
|
-
try {
|
|
55
|
-
const { message, stack } = formatViteError(errorData, id)
|
|
56
|
-
_err = createError({
|
|
57
|
-
statusMessage: 'Vite Error',
|
|
58
|
-
message,
|
|
59
|
-
stack,
|
|
60
|
-
})
|
|
61
|
-
} catch (formatError) {
|
|
62
|
-
consola.warn('Internal nuxt error while formatting vite-node error. Please report this!', formatError)
|
|
63
|
-
const message = `[vite-node] [TransformError] ${errorData?.message || '-'}`
|
|
64
|
-
consola.error(message, errorData)
|
|
65
|
-
throw createError({
|
|
66
|
-
statusMessage: 'Vite Error',
|
|
67
|
-
message,
|
|
68
|
-
stack: `${message}\nat ${id}\n` + (errorData?.stack || ''),
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
throw _err
|
|
72
|
-
})
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @param {any} errorData
|
|
79
|
-
* @param {string} id
|
|
80
|
-
*/
|
|
81
|
-
function formatViteError (errorData, id) {
|
|
82
|
-
const errorCode = errorData.name || errorData.reasonCode || errorData.code
|
|
83
|
-
const frame = errorData.frame || errorData.source || errorData.pluginCode
|
|
84
|
-
|
|
85
|
-
/** @param {{ file?: string, id?: string, url?: string }} locObj */
|
|
86
|
-
const getLocId = (locObj = {}) => locObj.file || locObj.id || locObj.url || id || ''
|
|
87
|
-
/** @param {{ line?: string, column?: string }} locObj */
|
|
88
|
-
const getLocPos = (locObj = {}) => locObj.line ? `${locObj.line}:${locObj.column || 0}` : ''
|
|
89
|
-
const locId = getLocId(errorData.loc) || getLocId(errorData.location) || getLocId(errorData.input) || getLocId(errorData)
|
|
90
|
-
const locPos = getLocPos(errorData.loc) || getLocPos(errorData.location) || getLocPos(errorData.input) || getLocPos(errorData)
|
|
91
|
-
const loc = locId.replace(process.cwd(), '.') + (locPos ? `:${locPos}` : '')
|
|
92
|
-
|
|
93
|
-
const message = [
|
|
94
|
-
'[vite-node]',
|
|
95
|
-
errorData.plugin && `[plugin:${errorData.plugin}]`,
|
|
96
|
-
errorCode && `[${errorCode}]`,
|
|
97
|
-
loc,
|
|
98
|
-
errorData.reason && `: ${errorData.reason}`,
|
|
99
|
-
frame && `<br><pre>${frame.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')}</pre><br>`,
|
|
100
|
-
].filter(Boolean).join(' ')
|
|
101
|
-
|
|
102
|
-
const stack = [
|
|
103
|
-
message,
|
|
104
|
-
`at ${loc}`,
|
|
105
|
-
errorData.stack,
|
|
106
|
-
].filter(Boolean).join('\n')
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
message,
|
|
110
|
-
stack,
|
|
111
|
-
}
|
|
112
|
-
}
|