UNPKG

vike

Version:

The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.

155 lines (154 loc) 6.76 kB
import '../assertEnvVite.js'; 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'; const globalObject = getGlobalObject('vite/shared/loggerDev.ts', { processStartupLog_isCompact: null, processStartupLog_hasViteLoggedStartup: null, processStartupLog_hasViteLoggedHelpShortcut: null, swallowViteLogForceOptimization_enabled: false, swallowViteLogConnected_originalConsoleLog: null, }); 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) { 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: !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; } // Suppress "[vite] connected." message. (It doesn't go through Vite's logger thus we must monkey patch the console.log() function.) function swallowViteLogConnected() { if (isDebugError()) return; if (globalObject.swallowViteLogConnected_originalConsoleLog) return; globalObject.swallowViteLogConnected_originalConsoleLog = console.log; console.log = swallowViteLogConnected_logPatch; setTimeout(swallowViteLogConnected_clean, 3000); } // Remove console.log() monkey patch function swallowViteLogConnected_clean() { // Don't remove console.log() patches from other libraries (e.g. instrumentation) if (console.log === swallowViteLogConnected_logPatch) return; assert(globalObject.swallowViteLogConnected_originalConsoleLog); 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); }