UNPKG

vike

Version:

(Replaces Next.js/Nuxt) 🔨 Composable framework to build advanced applications with flexibility and stability.

162 lines (161 loc) • 7.05 kB
export { interceptViteLogs }; export { processStartupLog }; export { swallowViteLogForceOptimization_enable }; export { swallowViteLogForceOptimization_disable }; export { swallowViteLogConnected }; export { swallowViteLogConnected_clean }; import { isDebugError } from '../../../utils/debug.js'; import { removeEmptyLines } from '../../../utils/removeEmptyLines.js'; import { trimWithAnsi, trimWithAnsiTrailOnly } from '../../../utils/trimWithAnsi.js'; import { assert } from '../../../utils/assert.js'; import { getGlobalObject } from '../../../utils/getGlobalObject.js'; import { getRequestId_withAsyncHook } from '../../../server/runtime/asyncHook.js'; import { logErrorServerDev, logVite } from './loggerDev.js'; import '../assertEnvVite.js'; const globalObject = getGlobalObject('vite/shared/loggerDev.ts', { processStartupLog_isCompact: null, processStartupLog_hasViteLoggedStartup: null, processStartupLog_hasViteLoggedHelpShortcut: null, swallowViteLogForceOptimization_enabled: false, swallowViteLogConnected_originalConsoleLog: undefined, }); function interceptViteLogs(config) { if (isDebugError()) return; intercept('info', config); intercept('warn', config); intercept('error', config); } function intercept(loggerType, config) { let isBeginning = true; setTimeout(() => (isBeginning = false), 10 * 1000); config.logger[loggerType] = (msg, options = {}) => { assert(!isDebugError()); if (swallowViteLogForceOptimization(msg)) return; if (!!options.timestamp) { msg = trimWithAnsi(msg); } else { // No timestamp => no "[vite]" tag prepended => we don't trim the beginning of the message msg = trimWithAnsiTrailOnly(msg); } if (isBeginning) { msg = processStartupLog_onViteLog(msg, config); } if (options.error) { // Vite does a poor job of handling errors. // - It doesn't format error code snippets. // - It only shows error.message which means that crucial information such as error.id isn't shown to the user. logErrorServerDev(options.error, null, true); // We swallow Vite's message: it doesn't seem to add any value. // - It can even be confusing, such as the following: // ``` // Error when evaluating SSR module virtual:vike:page-entry:server:/pages/abort: failed to import "/pages/abort/+Page.mdx" // ``` assert(!isDebugError()); return; } const requestId = getRequestId_withAsyncHook(); // Vite's default logger preprends the "[vite]" tag if and only if options.timestamp is true const prependViteTag = options.timestamp || typeof requestId === 'number'; // If it's an actual error => options.error is set => it's handled with logErrorServerDev() above logVite(msg, loggerType, requestId, prependViteTag); }; } // - Clears screen if zero previous log // - Manages new lines function processStartupLog(firstLine, config, veryCompact) { const shouldClear = processStartupLog_shouldClear(config); if (shouldClear) { config.logger.clearScreen('info'); } else { // Remove leading new line (for both Vite and Vike's startup log) firstLine = removeEmptyLines(firstLine); } return { firstLine, isCompact: veryCompact || !shouldClear }; } function processStartupLog_shouldClear(config) { const hasLoggedBefore = process.stdout.bytesWritten !== 0 || process.stderr.bytesWritten !== 0; const notDisabled = config.clearScreen !== false; const shouldClear = notDisabled && !hasLoggedBefore; return shouldClear; } function processStartupLog_onViteLog(msg, config) { { const isFirstVitLog = msg.includes('VITE') && msg.includes('ready'); if (isFirstVitLog && !globalObject.processStartupLog_hasViteLoggedStartup) { globalObject.processStartupLog_hasViteLoggedStartup = true; let { firstLine, isCompact } = processStartupLog(msg, config); globalObject.processStartupLog_isCompact = isCompact; if (!isCompact) firstLine += '\n'; return firstLine; } } { const isViteHelpShortcutLog = msg.includes('press') && msg.includes('to show help'); if (isViteHelpShortcutLog && !globalObject.processStartupLog_hasViteLoggedHelpShortcut) { globalObject.processStartupLog_hasViteLoggedHelpShortcut = true; if (globalObject.processStartupLog_hasViteLoggedStartup && globalObject.processStartupLog_isCompact === false) { return msg + '\n'; } } } return msg; } function swallowViteLogForceOptimization(msg) { if (!globalObject.swallowViteLogForceOptimization_enabled) { return false; } if (msg.toLowerCase().includes('forced') && msg.toLowerCase().includes('optimization')) { assert(msg === 'Forced re-optimization of dependencies', msg); // assertion fails => Vite changed its message => update this function return true; } return false; } function swallowViteLogForceOptimization_enable() { if (isDebugError()) return; globalObject.swallowViteLogForceOptimization_enabled = true; } function swallowViteLogForceOptimization_disable() { globalObject.swallowViteLogForceOptimization_enabled = false; } // Swallow message `[vite] connected.` function swallowViteLogConnected() { if (isDebugError()) return; if (globalObject.swallowViteLogConnected_originalConsoleLog) return; globalObject.swallowViteLogConnected_originalConsoleLog = console.log; // The message `[vite] connected.` doesn't go through Vite's logger thus we must monkey patch console.log() console.log = swallowViteLogConnected_logPatch; setTimeout(swallowViteLogConnected_clean, 3000); } // Remove console.log() monkey patch function swallowViteLogConnected_clean() { if (isDebugError()) { assert(globalObject.swallowViteLogConnected_originalConsoleLog === undefined); return; } if (globalObject.swallowViteLogConnected_originalConsoleLog === null) return; // already cleaned assert(globalObject.swallowViteLogConnected_originalConsoleLog); // Don't remove console.log() patches from other libraries (e.g. instrumentation) if (console.log !== swallowViteLogConnected_logPatch) return; console.log = globalObject.swallowViteLogConnected_originalConsoleLog; globalObject.swallowViteLogConnected_originalConsoleLog = null; } function swallowViteLogConnected_logPatch(...args) { const originalConsoleLog = globalObject.swallowViteLogConnected_originalConsoleLog; assert(originalConsoleLog); const msg = args.join(' '); if (msg === '[vite] connected.') { swallowViteLogConnected_clean(); return; // swallow } originalConsoleLog.apply(console, args); }