vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
155 lines (154 loc) • 6.76 kB
JavaScript
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);
}