UNPKG

@rspack/cli

Version:
182 lines (181 loc) • 9.01 kB
"use strict"; exports.ids = [ '390' ]; exports.modules = { "./src/utils/profile.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { applyProfile: ()=>applyProfile }); var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("node:fs"); var node_fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/ __webpack_require__.n(node_fs__WEBPACK_IMPORTED_MODULE_0__); var node_inspector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("node:inspector"); var node_inspector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/ __webpack_require__.n(node_inspector__WEBPACK_IMPORTED_MODULE_1__); var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("node:path"); var node_path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/ __webpack_require__.n(node_path__WEBPACK_IMPORTED_MODULE_2__); var node_url__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("node:url"); var _rspack_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("@rspack/core"); function _define_property(obj, key, value) { if (key in obj) Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); else obj[key] = value; return obj; } const timestamp = Date.now(); const defaultOutputDirname = node_path__WEBPACK_IMPORTED_MODULE_2___default().resolve(`.rspack-profile-${timestamp}-${process.pid}`); const defaultJSCPUProfileOutput = node_path__WEBPACK_IMPORTED_MODULE_2___default().join(defaultOutputDirname, "./jscpuprofile.json"); const defaultRustTraceChromeOutput = node_path__WEBPACK_IMPORTED_MODULE_2___default().join(defaultOutputDirname, "./trace.json"); const defaultRustTraceLoggerOutput = "stdout"; const defaultRustTraceFilter = "trace"; const defaultRustTraceLayer = "chrome"; const defaultLoggingOutput = node_path__WEBPACK_IMPORTED_MODULE_2___default().join(defaultOutputDirname, "./logging.json"); function resolveProfile(value) { if ("ALL" === value.toUpperCase()) return { TRACE: { filter: defaultRustTraceFilter, layer: defaultRustTraceLayer, output: defaultRustTraceChromeOutput }, JSCPU: { output: defaultJSCPUProfileOutput }, LOGGING: { output: defaultLoggingOutput } }; if (value.startsWith("[") && value.endsWith("]")) return { TRACE: resolveRustTraceOptions(value.slice(1, value.length - 1)), JSCPU: { output: defaultJSCPUProfileOutput }, LOGGING: { output: defaultLoggingOutput } }; return value.split("|").reduce((acc, cur)=>{ const upperCur = cur.toUpperCase(); if (upperCur.startsWith("TRACE")) acc.TRACE = resolveRustTraceOptions(cur.slice(6)); else if (upperCur.startsWith("JSCPU")) acc.JSCPU = resolveJSCPUProfileOptions(cur.slice(6)); else if (upperCur.startsWith("LOGGING")) acc.LOGGING = resolveLoggingOptions(cur.slice(8)); return acc; }, {}); } function resolveJSCPUProfileOptions(value) { if (value.includes("=")) { const parsed = new node_url__WEBPACK_IMPORTED_MODULE_3__.URLSearchParams(value); return { output: parsed.get("output") || defaultJSCPUProfileOutput }; } return { output: value || defaultJSCPUProfileOutput }; } function isSupportedLayer(layer) { const SUPPORTED_LAYERS = [ "chrome", "logger", "otel" ]; return SUPPORTED_LAYERS.includes(layer); } function resolveRustTraceOptions(value) { if (value.includes("=")) { const parsed = new node_url__WEBPACK_IMPORTED_MODULE_3__.URLSearchParams(value); const filter = parsed.get("filter") || defaultRustTraceFilter; const layer = parsed.get("layer") || defaultRustTraceLayer; const output = "chrome" === layer ? parsed.get("output") || defaultRustTraceChromeOutput : parsed.get("output") || defaultRustTraceLoggerOutput; if (!isSupportedLayer(layer)) throw new Error(`${layer} is not a valid layer, should be chrome or logger`); return { filter, layer, output }; } return { filter: value || defaultRustTraceFilter, layer: defaultRustTraceLayer, output: defaultRustTraceChromeOutput }; } function resolveLoggingOptions(value) { if (value.includes("=")) { const parsed = new node_url__WEBPACK_IMPORTED_MODULE_3__.URLSearchParams(value); return { output: parsed.get("output") || defaultLoggingOutput }; } return { output: value || defaultLoggingOutput }; } class RspackProfileJSCPUProfilePlugin { apply(compiler) { const session = new (node_inspector__WEBPACK_IMPORTED_MODULE_1___default()).Session(); session.connect(); session.post("Profiler.enable"); session.post("Profiler.start"); compiler.hooks.done.tapAsync(RspackProfileJSCPUProfilePlugin.name, (_stats, callback)=>{ if (compiler.watchMode) return callback(); session.post("Profiler.stop", (error, param)=>{ if (error) { console.error("Failed to generate JS CPU profile:", error); return; } node_fs__WEBPACK_IMPORTED_MODULE_0___default().writeFileSync(this.output, JSON.stringify(param.profile)); }); return callback(); }); } constructor(output){ _define_property(this, "output", void 0); this.output = output; } } class RspackProfileLoggingPlugin { apply(compiler) { compiler.hooks.done.tapAsync(RspackProfileLoggingPlugin.name, (stats, callback)=>{ if (compiler.watchMode) return callback(); const logging = stats.toJson({ all: false, logging: "verbose", loggingTrace: true }); node_fs__WEBPACK_IMPORTED_MODULE_0___default().writeFileSync(this.output, JSON.stringify(logging)); return callback(); }); } constructor(output){ _define_property(this, "output", void 0); this.output = output; } } async function applyProfile(profileValue, item) { const { asyncExitHook } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "exit-hook")); const entries = Object.entries(resolveProfile(profileValue)); if (entries.length <= 0) return; await node_fs__WEBPACK_IMPORTED_MODULE_0___default().promises.mkdir(defaultOutputDirname); for (const [kind, value] of entries){ await ensureFileDir(value.output); if ("TRACE" === kind && "filter" in value) { await _rspack_core__WEBPACK_IMPORTED_MODULE_4__.rspack.experiments.globalTrace.register(value.filter, value.layer, value.output); asyncExitHook(_rspack_core__WEBPACK_IMPORTED_MODULE_4__.rspack.experiments.globalTrace.cleanup, { wait: 500 }); } else if ("JSCPU" === kind) (item.plugins ??= []).push(new RspackProfileJSCPUProfilePlugin(value.output)); else if ("LOGGING" === kind) (item.plugins ??= []).push(new RspackProfileLoggingPlugin(value.output)); } } async function ensureFileDir(outputFilePath) { const dir = node_path__WEBPACK_IMPORTED_MODULE_2___default().dirname(outputFilePath); await node_fs__WEBPACK_IMPORTED_MODULE_0___default().promises.mkdir(dir, { recursive: true }); return dir; } } };