版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

365 строки
12 KiB

  1. import { performance } from 'node:perf_hooks';
  2. import { existsSync, promises } from 'node:fs';
  3. import { resolve, join, relative } from 'pathe';
  4. import createDebug from 'debug';
  5. import { isNodeBuiltin, isValidNodeImport } from 'mlly';
  6. import { slash, toArray, normalizeModuleId, toFilePath } from './utils.mjs';
  7. import c from 'picocolors';
  8. import { withInlineSourcemap } from './source-map.mjs';
  9. import 'node:url';
  10. import 'node:path';
  11. const KNOWN_ASSET_TYPES = [
  12. "png",
  13. "jpe?g",
  14. "jfif",
  15. "pjpeg",
  16. "pjp",
  17. "gif",
  18. "svg",
  19. "ico",
  20. "webp",
  21. "avif",
  22. "mp4",
  23. "webm",
  24. "ogg",
  25. "mp3",
  26. "wav",
  27. "flac",
  28. "aac",
  29. "woff2?",
  30. "eot",
  31. "ttf",
  32. "otf",
  33. "webmanifest",
  34. "pdf",
  35. "txt"
  36. ];
  37. const ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/;
  38. const ESM_FOLDER_RE = /\/(es|esm)\/(.*\.js)$/;
  39. const defaultInline = [
  40. /virtual:/,
  41. /\.[mc]?ts$/,
  42. /[?&](init|raw|url|inline)\b/,
  43. new RegExp(`\\.(${KNOWN_ASSET_TYPES.join("|")})$`)
  44. ];
  45. const depsExternal = [
  46. /\.cjs\.js$/,
  47. /\.mjs$/
  48. ];
  49. function guessCJSversion(id) {
  50. if (id.match(ESM_EXT_RE)) {
  51. for (const i of [
  52. id.replace(ESM_EXT_RE, ".mjs"),
  53. id.replace(ESM_EXT_RE, ".umd.js"),
  54. id.replace(ESM_EXT_RE, ".cjs.js"),
  55. id.replace(ESM_EXT_RE, ".js")
  56. ]) {
  57. if (existsSync(i))
  58. return i;
  59. }
  60. }
  61. if (id.match(ESM_FOLDER_RE)) {
  62. for (const i of [
  63. id.replace(ESM_FOLDER_RE, "/umd/$1"),
  64. id.replace(ESM_FOLDER_RE, "/cjs/$1"),
  65. id.replace(ESM_FOLDER_RE, "/lib/$1"),
  66. id.replace(ESM_FOLDER_RE, "/$1")
  67. ]) {
  68. if (existsSync(i))
  69. return i;
  70. }
  71. }
  72. }
  73. const _defaultExternalizeCache = /* @__PURE__ */ new Map();
  74. async function shouldExternalize(id, options, cache = _defaultExternalizeCache) {
  75. if (!cache.has(id))
  76. cache.set(id, _shouldExternalize(id, options));
  77. return cache.get(id);
  78. }
  79. async function _shouldExternalize(id, options) {
  80. if (isNodeBuiltin(id))
  81. return id;
  82. if (id.startsWith("data:"))
  83. return id;
  84. id = patchWindowsImportPath(id);
  85. if ((options == null ? void 0 : options.cacheDir) && id.includes(options.cacheDir))
  86. return id;
  87. if (matchExternalizePattern(id, options == null ? void 0 : options.inline))
  88. return false;
  89. if (matchExternalizePattern(id, options == null ? void 0 : options.external))
  90. return id;
  91. const isNodeModule = id.includes("/node_modules/");
  92. const guessCJS = isNodeModule && (options == null ? void 0 : options.fallbackCJS);
  93. id = guessCJS ? guessCJSversion(id) || id : id;
  94. if (matchExternalizePattern(id, defaultInline))
  95. return false;
  96. if (matchExternalizePattern(id, depsExternal))
  97. return id;
  98. const isDist = id.includes("/dist/");
  99. if ((isNodeModule || isDist) && await isValidNodeImport(id))
  100. return id;
  101. return false;
  102. }
  103. function matchExternalizePattern(id, patterns) {
  104. if (patterns == null)
  105. return false;
  106. if (patterns === true)
  107. return true;
  108. for (const ex of patterns) {
  109. if (typeof ex === "string") {
  110. if (id.includes(`/node_modules/${ex}/`))
  111. return true;
  112. } else {
  113. if (ex.test(id))
  114. return true;
  115. }
  116. }
  117. return false;
  118. }
  119. function patchWindowsImportPath(path) {
  120. if (path.match(/^\w:\\/))
  121. return `file:///${slash(path)}`;
  122. else if (path.match(/^\w:\//))
  123. return `file:///${path}`;
  124. else
  125. return path;
  126. }
  127. function hashCode(s) {
  128. return s.split("").reduce((a, b) => {
  129. a = (a << 5) - a + b.charCodeAt(0);
  130. return a & a;
  131. }, 0);
  132. }
  133. class Debugger {
  134. constructor(root, options) {
  135. this.options = options;
  136. this.externalizeMap = /* @__PURE__ */ new Map();
  137. if (options.dumpModules)
  138. this.dumpDir = resolve(root, options.dumpModules === true ? ".vite-node/dump" : options.dumpModules);
  139. if (this.dumpDir) {
  140. if (options.loadDumppedModules)
  141. console.info(c.gray(`[vite-node] [debug] load modules from ${this.dumpDir}`));
  142. else
  143. console.info(c.gray(`[vite-node] [debug] dump modules to ${this.dumpDir}`));
  144. }
  145. this.initPromise = this.clearDump();
  146. }
  147. async clearDump() {
  148. if (!this.dumpDir)
  149. return;
  150. if (!this.options.loadDumppedModules && existsSync(this.dumpDir))
  151. await promises.rm(this.dumpDir, { recursive: true, force: true });
  152. await promises.mkdir(this.dumpDir, { recursive: true });
  153. }
  154. encodeId(id) {
  155. return `${id.replace(/[^\w@_-]/g, "_").replace(/_+/g, "_")}-${hashCode(id)}.js`;
  156. }
  157. async recordExternalize(id, path) {
  158. if (!this.dumpDir)
  159. return;
  160. this.externalizeMap.set(id, path);
  161. await this.writeInfo();
  162. }
  163. async dumpFile(id, result) {
  164. if (!result || !this.dumpDir)
  165. return;
  166. await this.initPromise;
  167. const name = this.encodeId(id);
  168. return await promises.writeFile(join(this.dumpDir, name), `// ${id.replace(/\0/g, "\\0")}
  169. ${result.code}`, "utf-8");
  170. }
  171. async loadDump(id) {
  172. if (!this.dumpDir)
  173. return null;
  174. await this.initPromise;
  175. const name = this.encodeId(id);
  176. const path = join(this.dumpDir, name);
  177. if (!existsSync(path))
  178. return null;
  179. const code = await promises.readFile(path, "utf-8");
  180. return {
  181. code: code.replace(/^\/\/.*?\n/, ""),
  182. map: void 0
  183. };
  184. }
  185. async writeInfo() {
  186. if (!this.dumpDir)
  187. return;
  188. const info = JSON.stringify({
  189. time: new Date().toLocaleString(),
  190. externalize: Object.fromEntries(this.externalizeMap.entries())
  191. }, null, 2);
  192. return promises.writeFile(join(this.dumpDir, "info.json"), info, "utf-8");
  193. }
  194. }
  195. const debugRequest = createDebug("vite-node:server:request");
  196. class ViteNodeServer {
  197. constructor(server, options = {}) {
  198. this.server = server;
  199. this.options = options;
  200. this.fetchPromiseMap = /* @__PURE__ */ new Map();
  201. this.transformPromiseMap = /* @__PURE__ */ new Map();
  202. this.existingOptimizedDeps = /* @__PURE__ */ new Set();
  203. this.fetchCache = /* @__PURE__ */ new Map();
  204. this.externalizeCache = /* @__PURE__ */ new Map();
  205. var _a, _b;
  206. const ssrOptions = server.config.ssr;
  207. options.deps ?? (options.deps = {});
  208. options.deps.cacheDir = relative(server.config.root, server.config.cacheDir);
  209. if (ssrOptions) {
  210. if (ssrOptions.noExternal === true) {
  211. (_a = options.deps).inline ?? (_a.inline = true);
  212. } else if (options.deps.inline !== true) {
  213. (_b = options.deps).inline ?? (_b.inline = []);
  214. options.deps.inline.push(...toArray(ssrOptions.noExternal));
  215. }
  216. }
  217. if (process.env.VITE_NODE_DEBUG_DUMP) {
  218. options.debug = Object.assign({
  219. dumpModules: !!process.env.VITE_NODE_DEBUG_DUMP,
  220. loadDumppedModules: process.env.VITE_NODE_DEBUG_DUMP === "load"
  221. }, options.debug ?? {});
  222. }
  223. if (options.debug)
  224. this.debugger = new Debugger(server.config.root, options.debug);
  225. }
  226. shouldExternalize(id) {
  227. return shouldExternalize(id, this.options.deps, this.externalizeCache);
  228. }
  229. async ensureExists(id) {
  230. if (this.existingOptimizedDeps.has(id))
  231. return true;
  232. if (existsSync(id)) {
  233. this.existingOptimizedDeps.add(id);
  234. return true;
  235. }
  236. return new Promise((resolve2) => {
  237. setTimeout(() => {
  238. this.ensureExists(id).then(() => {
  239. resolve2(true);
  240. });
  241. });
  242. });
  243. }
  244. async resolveId(id, importer, transformMode) {
  245. if (importer && !importer.startsWith(this.server.config.root))
  246. importer = resolve(this.server.config.root, importer);
  247. const mode = transformMode ?? (importer && this.getTransformMode(importer) || "ssr");
  248. return this.server.pluginContainer.resolveId(id, importer, { ssr: mode === "ssr" });
  249. }
  250. getSourceMap(source) {
  251. var _a, _b;
  252. const fetchResult = (_a = this.fetchCache.get(source)) == null ? void 0 : _a.result;
  253. if (fetchResult == null ? void 0 : fetchResult.map)
  254. return fetchResult.map;
  255. const ssrTransformResult = (_b = this.server.moduleGraph.getModuleById(source)) == null ? void 0 : _b.ssrTransformResult;
  256. return (ssrTransformResult == null ? void 0 : ssrTransformResult.map) || null;
  257. }
  258. async fetchModule(id, transformMode) {
  259. id = normalizeModuleId(id);
  260. if (!this.fetchPromiseMap.has(id)) {
  261. this.fetchPromiseMap.set(
  262. id,
  263. this._fetchModule(id, transformMode).then((r) => {
  264. return this.options.sourcemap !== true ? { ...r, map: void 0 } : r;
  265. }).finally(() => {
  266. this.fetchPromiseMap.delete(id);
  267. })
  268. );
  269. }
  270. return this.fetchPromiseMap.get(id);
  271. }
  272. async transformRequest(id) {
  273. if (!this.transformPromiseMap.has(id)) {
  274. this.transformPromiseMap.set(
  275. id,
  276. this._transformRequest(id).finally(() => {
  277. this.transformPromiseMap.delete(id);
  278. })
  279. );
  280. }
  281. return this.transformPromiseMap.get(id);
  282. }
  283. getTransformMode(id) {
  284. var _a, _b, _c, _d;
  285. const withoutQuery = id.split("?")[0];
  286. if ((_b = (_a = this.options.transformMode) == null ? void 0 : _a.web) == null ? void 0 : _b.some((r) => withoutQuery.match(r)))
  287. return "web";
  288. if ((_d = (_c = this.options.transformMode) == null ? void 0 : _c.ssr) == null ? void 0 : _d.some((r) => withoutQuery.match(r)))
  289. return "ssr";
  290. if (withoutQuery.match(/\.([cm]?[jt]sx?|json)$/))
  291. return "ssr";
  292. return "web";
  293. }
  294. async _fetchModule(id, transformMode) {
  295. var _a, _b;
  296. let result;
  297. const cacheDir = (_a = this.options.deps) == null ? void 0 : _a.cacheDir;
  298. if (cacheDir && id.includes(cacheDir)) {
  299. if (!id.startsWith(this.server.config.root))
  300. id = join(this.server.config.root, id);
  301. const timeout = setTimeout(() => {
  302. throw new Error(`ViteNodeServer: ${id} not found. This is a bug, please report it.`);
  303. }, 5e3);
  304. await this.ensureExists(id);
  305. clearTimeout(timeout);
  306. }
  307. const { path: filePath } = toFilePath(id, this.server.config.root);
  308. const module = this.server.moduleGraph.getModuleById(id);
  309. const timestamp = module ? module.lastHMRTimestamp : null;
  310. const cache = this.fetchCache.get(filePath);
  311. if (timestamp && cache && cache.timestamp >= timestamp)
  312. return cache.result;
  313. const time = Date.now();
  314. const externalize = await this.shouldExternalize(filePath);
  315. let duration;
  316. if (externalize) {
  317. result = { externalize };
  318. (_b = this.debugger) == null ? void 0 : _b.recordExternalize(id, externalize);
  319. } else {
  320. const start = performance.now();
  321. const r = await this._transformRequest(id, transformMode);
  322. duration = performance.now() - start;
  323. result = { code: r == null ? void 0 : r.code, map: r == null ? void 0 : r.map };
  324. }
  325. this.fetchCache.set(filePath, {
  326. duration,
  327. timestamp: time,
  328. result
  329. });
  330. return result;
  331. }
  332. async processTransformResult(result) {
  333. return withInlineSourcemap(result);
  334. }
  335. async _transformRequest(id, customTransformMode) {
  336. var _a, _b, _c, _d;
  337. debugRequest(id);
  338. let result = null;
  339. if ((_a = this.options.debug) == null ? void 0 : _a.loadDumppedModules) {
  340. result = await ((_b = this.debugger) == null ? void 0 : _b.loadDump(id)) ?? null;
  341. if (result)
  342. return result;
  343. }
  344. const transformMode = customTransformMode ?? this.getTransformMode(id);
  345. if (transformMode === "web") {
  346. result = await this.server.transformRequest(id);
  347. if (result)
  348. result = await this.server.ssrTransform(result.code, result.map, id);
  349. } else {
  350. result = await this.server.transformRequest(id, { ssr: true });
  351. }
  352. const sourcemap = this.options.sourcemap ?? "inline";
  353. if (sourcemap === "inline" && result && !id.includes("node_modules"))
  354. result = await this.processTransformResult(result);
  355. if ((_c = this.options.debug) == null ? void 0 : _c.dumpModules)
  356. await ((_d = this.debugger) == null ? void 0 : _d.dumpFile(id, result));
  357. return result;
  358. }
  359. }
  360. export { ViteNodeServer, guessCJSversion, shouldExternalize };