Package Exports
- loggerect
- loggerect/babel-plugin
- loggerect/core
- loggerect/hooks
- loggerect/loader
- loggerect/react
- loggerect/unplugin
- loggerect/vite-plugin
Readme
loggerect
A powerful, zero-dependency logger for React and Node.js with full source path tracking, TypeScript decorators, and environment-aware output. See exactly where your logs come from.
โจ Features
- ๐ฏ Accurate Source Tracking - See exact file:line in browser console (via build plugins)
- ๐จ Beautiful Console Output - Styled badges, timestamps, and structured formatting
- ๐ Unified Colors - Server console colors match browser console (ANSI + CSS)
- โ๏ธ React Support - Hooks, HOCs, and decorators for React (optional)
- ๐ฅ๏ธ Node.js Compatible - Works in pure Node.js without React
- ๐ง Highly Configurable - Customize everything from log levels to badge styles
- ๐ Environment-Aware - Different behavior for development vs production
- ๐ฆ Zero Dependencies - Lightweight and fast
- ๐ฅ๏ธ SSR Compatible - Works seamlessly with Next.js, Remix, and other SSR frameworks
- ๐งน Smart Filtering - Automatically filters internal React/Node.js function names
- ๐ Universal Plugin Support - Works with Vite, Webpack, Turbopack, Rollup, and esbuild
๐ฆ Installation
npm install loggerect๐ Quick Start
Basic Usage (Node.js & React)
import { logger, configure } from "loggerect";
// Configure (optional - has sensible defaults)
configure({
level: "debug",
timestamps: true,
});
// Log messages
logger.trace("Detailed trace information");
logger.debug("Debug information");
logger.info("General information");
logger.warn("Warning message");
logger.error("Error occurred", { details: "error info" });Node.js Usage
// Pure Node.js - no React needed!
const { logger } = require("loggerect");
// or
import { logger } from "loggerect";
// Use in any Node.js application
logger.info("Server started", { port: 3000 });
logger.debug("Processing request", { method: "GET", path: "/api/users" });
// Component-scoped logging (works in Node.js too!)
const apiLogger = logger.forComponent("API").withTags("http", "rest");
apiLogger.info("Request received", { userId: 123 });
// Performance timing
logger.time("databaseQuery");
await queryDatabase();
logger.timeEnd("databaseQuery"); // Logs: โฑ๏ธ databaseQuery: 45.23msReact Hooks
import { useLogger, useLifecycleLogger } from "loggerect";
function MyComponent() {
const log = useLogger("MyComponent");
useLifecycleLogger("MyComponent"); // Auto-logs mount/unmount
const handleClick = () => {
log.info("Button clicked!");
};
return <button onClick={handleClick}>Click me</button>;
}๐ Source Tracking Setup
For accurate source file:line tracking in the browser console, add one of the build plugins:
Vite
// vite.config.ts
import { defineConfig } from "vite";
import logrectPlugin from "loggerect/vite-plugin";
export default defineConfig({
plugins: [logrectPlugin()],
});Next.js (Turbopack)
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
turbopack: {
rules: {
"*.{ts,tsx,js,jsx}": {
loaders: ["loggerect/loader"],
},
},
},
};
export default nextConfig;Next.js (Webpack)
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
webpack: (config, { dev }) => {
if (dev) {
const logrectPlugin = require("loggerect/unplugin");
config.plugins.push(logrectPlugin.webpack());
}
return config;
},
};
export default nextConfig;Webpack
// webpack.config.js
const logrectPlugin = require("loggerect/unplugin");
module.exports = {
plugins: [logrectPlugin.webpack()],
};Rollup
// rollup.config.js
import logrectPlugin from "loggerect/unplugin";
export default {
plugins: [logrectPlugin.rollup()],
};esbuild
// esbuild.config.js
const logrectPlugin = require("loggerect/unplugin");
require("esbuild").build({
plugins: [logrectPlugin.esbuild()],
});Babel (Alternative)
// babel.config.js
module.exports = {
plugins: ["loggerect/babel-plugin"],
};๐ API Reference
Core Logger (Node.js & React)
import { logger } from 'loggerect';
// Log levels
logger.trace(message, data?); // ๐ Most verbose
logger.debug(message, data?); // ๐ Debug info
logger.info(message, data?); // โน๏ธ General info
logger.warn(message, data?); // โ ๏ธ Warnings
logger.error(message, data?); // โ Errors
// Component-scoped logger
const componentLogger = logger.forComponent('MyComponent');
componentLogger.info('Scoped to MyComponent');
// With tags and metadata
const taggedLogger = logger
.forComponent('MyComponent')
.withTags('auth', 'api')
.withMetadata({ userId: 123 });
// Performance timing
logger.time('fetchData');
await fetchData();
logger.timeEnd('fetchData'); // Logs: โฑ๏ธ fetchData: 156.78ms
// Lifecycle helpers
logger.mount('ComponentName'); // ๐ Mounted
logger.unmount('ComponentName'); // ๐ค Unmounted
logger.render('ComponentName', 1, 2.5); // ๐จ Render #1 (2.5ms)React Hooks
useLogger(componentName, options?)
Creates a component-scoped logger instance.
function MyComponent() {
const log = useLogger("MyComponent");
useEffect(() => {
log.info("Component ready");
log.debug("Fetching data...", { endpoint: "/api/users" });
}, []);
return <div>Hello</div>;
}useLifecycleLogger(componentName, options?)
Automatically logs component mount and unmount events.
function MyComponent() {
useLifecycleLogger("MyComponent");
// Logs: ๐ Mounted (on mount)
// Logs: ๐ค Unmounted (lifetime: 5234.12ms) (on unmount)
return <div>Hello</div>;
}useRenderLogger(componentName, options?)
Tracks and logs every render with timing.
function MyComponent() {
useRenderLogger("MyComponent");
// Logs: ๐จ Render #1 (2.34ms)
// Logs: ๐จ Render #2 (1.12ms)
return <div>Hello</div>;
}useStateLogger<T>(componentName, stateName, initialValue, options?)
useState replacement that logs state changes.
function Counter() {
const [count, setCount] = useStateLogger("Counter", "count", 0);
// Logs: ๐๏ธ State "count" changed { prev: 0, next: 1 }
return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
}usePropChangeLogger<T>(componentName, props, options?)
Logs whenever props change with diff information.
function UserProfile({ user, theme }) {
usePropChangeLogger("UserProfile", { user, theme });
// Logs: ๐ฆ Props changed { user: { prev: {...}, next: {...} } }
return <div>{user.name}</div>;
}useEffectLogger(componentName, effectName, effect, deps, options?)
useEffect replacement that logs effect execution.
function DataFetcher({ userId }) {
useEffectLogger(
"DataFetcher",
"fetchUser",
() => {
fetchUser(userId);
},
[userId]
);
// Logs: โถ๏ธ Effect "fetchUser" running
// Logs: โน๏ธ Effect "fetchUser" cleanup
return <div>...</div>;
}useCallbackLogger<T>(componentName, callbackName, callback, deps, options?)
useCallback replacement that logs callback executions.
function Form() {
const handleSubmit = useCallbackLogger(
"Form",
"handleSubmit",
(data) => {
submitForm(data);
},
[]
);
// Logs: ๐ Callback "handleSubmit" called (2.34ms)
return <form onSubmit={handleSubmit}>...</form>;
}useMemoLogger<T>(componentName, memoName, factory, deps, options?)
useMemo replacement that logs when values are recomputed.
function ExpensiveList({ items }) {
const sortedItems = useMemoLogger(
"ExpensiveList",
"sortedItems",
() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
},
[items]
);
// Logs: ๐งฎ Memo "sortedItems" computed (5.67ms)
return (
<ul>
{sortedItems.map((item) => (
<li>{item.name}</li>
))}
</ul>
);
}useTimer(componentName, options?)
Manual performance timing within components.
function DataLoader() {
const timer = useTimer("DataLoader");
const loadData = async () => {
timer.start("loadData");
const data = await fetchData();
timer.end("loadData"); // Logs: โฑ๏ธ loadData: 234.56ms
return data;
};
return <button onClick={loadData}>Load</button>;
}useWhyDidYouRender<T>(componentName, props, options?)
Debug tool to understand why a component re-rendered.
function MyComponent(props) {
useWhyDidYouRender("MyComponent", props);
// Logs detailed information about what caused the re-render
return <div>...</div>;
}Higher-Order Component (HOC)
import { withLogger } from "loggerect";
const MyComponent = ({ name }) => <div>Hello {name}</div>;
// Basic usage
export default withLogger(MyComponent);
// With options
export default withLogger(MyComponent, {
trackRenders: true,
trackPropChanges: true,
logLifecycle: true,
displayName: "MyAwesomeComponent",
level: "debug",
tags: ["ui", "feature"],
});TypeScript Decorators
Note: Requires
experimentalDecorators: truein tsconfig.json
import { Log, LogClass, Trace, Debug, Info, Warn, Error } from "loggerect";
class UserService {
@Log()
async fetchUser(id: string) {
// Logs: โ fetchUser() { args: ["123"] }
// Logs: โ fetchUser() (156.78ms)
return await api.getUser(id);
}
@Log({ logArgs: false, logTime: true })
processData(data: any) {
// Custom options
}
@Debug()
debugMethod() {
/* ... */
}
@Info()
infoMethod() {
/* ... */
}
@Warn()
warnMethod() {
/* ... */
}
@Error()
errorMethod() {
/* ... */
}
}
// Log entire class
@LogClass()
class MyService {
// All methods will be logged
}๐จ Log Levels & Badge Colors
loggerect uses styled badges with consistent colors for each log level:
Visual demonstration:
| Level | Badge | Background Color | Text Color | Description |
|---|---|---|---|---|
| TRACE | ๐ TRACE | rgba(107, 114, 128, 0.2) (Gray) |
#9CA3AF |
Most verbose, detailed tracing |
| DEBUG | ๐ DEBUG | rgba(34, 197, 94, 0.2) (Green) |
#22c55e |
Debug information |
| INFO | โน๏ธ INFO | rgba(59, 130, 246, 0.2) (Blue) |
#3b82f6 |
General information |
| WARN | โ ๏ธ WARN | rgba(234, 179, 8, 0.2) (Yellow) |
#eab308 |
Warnings |
| ERROR | โ ERROR | rgba(239, 68, 68, 0.2) (Red) |
#ef4444 |
Errors |
Additional Badges
| Badge | Usage |
|---|---|
| ๐ | Component mount |
| ๐ค | Component unmount |
| ๐จ | Component render |
| ๐ | Component update |
| ๐ฆ | Prop changes |
| ๐๏ธ | State changes |
| โฑ๏ธ | Performance timing |
All badges use a semi-transparent background (20% opacity) with matching text colors for a modern, readable console appearance.
โ๏ธ Configuration
import { configure } from "loggerect";
configure({
// Environment & Level
environment: "development", // 'development' | 'production' | 'test'
level: "debug", // 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent'
// Formatting
format: "pretty", // 'pretty' | 'json' | 'minimal' | 'detailed'
timestamps: true,
timestampFormat: "locale", // 'locale' | 'iso' | 'unix' | 'relative'
colors: true,
// Source Tracking
includeSourcePath: "auto", // true | false | 'auto'
includeStackTrace: true,
// React-specific
trackRenders: true,
trackPropChanges: true,
trackStateChanges: true,
// Performance
performance: true,
// Output Control
groupLogs: true,
collapseGroups: true,
maxDepth: 4,
maxArrayLength: 100,
maxStringLength: 1000,
// Persistence (experimental)
persist: false,
storageKey: "loggerect_logs",
maxPersistedLogs: 1000,
// Custom Styles (defaults shown below)
styles: {
// TRACE: Gray background (rgba(107, 114, 128, 0.2)), Gray text (#9CA3AF)
trace:
"background: rgba(107, 114, 128, 0.2); color: #9CA3AF; padding: 2px 8px; border-radius: 4px; font-weight: 600;",
// DEBUG: Green background (rgba(34, 197, 94, 0.2)), Green text (#22c55e)
debug:
"background: rgba(34, 197, 94, 0.2); color: #22c55e; padding: 2px 8px; border-radius: 4px; font-weight: 600;",
// INFO: Blue background (rgba(59, 130, 246, 0.2)), Blue text (#3b82f6)
info: "background: rgba(59, 130, 246, 0.2); color: #3b82f6; padding: 2px 8px; border-radius: 4px; font-weight: 600;",
// WARN: Yellow background (rgba(234, 179, 8, 0.2)), Yellow text (#eab308)
warn: "background: rgba(234, 179, 8, 0.2); color: #eab308; padding: 2px 8px; border-radius: 4px; font-weight: 600;",
// ERROR: Red background (rgba(239, 68, 68, 0.2)), Red text (#ef4444)
error:
"background: rgba(239, 68, 68, 0.2); color: #ef4444; padding: 2px 8px; border-radius: 4px; font-weight: 600;",
},
// Custom Badges
badges: {
trace: "๐",
debug: "๐",
info: "โน๏ธ",
warn: "โ ๏ธ",
error: "โ",
render: "๐จ",
mount: "๐",
unmount: "๐ค",
props: "๐ฆ",
state: "๐๏ธ",
time: "โฑ๏ธ",
},
});Environment-Specific Configuration
configure({
// Auto-detected, or set manually
environment: process.env.NODE_ENV,
// Different levels per environment
level: process.env.NODE_ENV === "production" ? "warn" : "trace",
// Disable source paths in production
includeSourcePath: process.env.NODE_ENV !== "production",
// Minimal format in production
format: process.env.NODE_ENV === "production" ? "minimal" : "pretty",
});๐ค Entry Points
loggerect provides multiple entry points for different use cases:
// Main entry - SSR-safe (no React dependencies)
// Use in server components, API routes, and utility functions
import { logger, configure, isServer, isClient } from "loggerect";
// React hooks (client components only)
import { useLogger, useLifecycleLogger, useStateLogger } from "loggerect/hooks";
// React HOCs (client components only)
import { withLogger, withLoggerRef } from "loggerect/react";
// Core only (alternative SSR entry point)
import { logger, configure } from "loggerect/core";When to Use Which Entry Point
loggerect(main): Use in server components, API routes, and any SSR contextloggerect/hooks: Use in client components that need React hooksloggerect/react: Use in client components that need HOCsloggerect/core: Alternative SSR entry point (same as main)
๐ SSR Support
loggerect is fully SSR-compatible with separate entry points for server and client code. The main loggerect package is SSR-safe and can be used directly in server components:
// Next.js Server Component (SSR-safe)
import { logger, isServer } from "loggerect";
export default async function Page() {
if (isServer()) {
const log = logger
.forComponent("Page")
.withTags("server", "page");
log.info("Rendering page on server");
}
return <div>Hello World</div>;
}Entry Points for SSR
// Main entry - SSR-safe (no React dependencies)
import { logger, configure, isServer, isClient } from "loggerect";
// React hooks (client components only)
import { useLogger, useLifecycleLogger } from "loggerect/hooks";
// React HOCs (client components only)
import { withLogger } from "loggerect/react";Server Console Colors
loggerect automatically matches console colors between server and browser:
- Server console: Uses ANSI color codes (RGB) matching CSS colors exactly
- Browser console: Uses CSS styling with matching colors
- Badge styling: Same background and text colors on both server and client
- Component names: Automatically extracted and filtered from stack traces
- Smart filtering: Filters out internal React/Node.js function names and minified code
The server console output will look identical to the browser console, with matching badge colors and spacing.
๐ Console Output Examples
Pretty Format (Development)
The console output uses styled badges with colors matching each log level. Colors are consistent between server and browser consoles. Here's what they look like:
Example log entries with colored badges:
[4:25:51 AM] โน๏ธ INFO | Navbar.useLifecycleLogger.useEffect() โ ๐ Mounted @ src/components/Navbar.tsx:9 [4:25:51 AM] ๐ DEBUG | Navbar.Navbar.useEffect() โ Scroll listener attached @ src/components/Navbar.tsx:8 [4:25:51 AM] ๐ DEBUG | ๐ [Navbar].Navbar.useEffect() Data: @ src/components/Navbar.tsx:8 { scrollY: 0 } [4:25:52 AM] โ ๏ธ WARN | DataService.fetchData() โ Rate limit approaching @ src/services/DataService.ts:45 [4:25:53 AM] โ ERROR | AuthService.login() โ Authentication failed @ src/services/AuthService.ts:23 [4:25:50 AM] ๐ TRACE | Component.render() โ Rendering child components @ src/components/Component.tsx:15
Badge colors reference:
- ๐ TRACE - Gray badge (
rgba(107, 114, 128, 0.2)bg,#9CA3AFtext) - ๐ DEBUG - Green badge (
rgba(34, 197, 94, 0.2)bg,#22c55etext) - โน๏ธ INFO - Blue badge (
rgba(59, 130, 246, 0.2)bg,#3b82f6text) - โ ๏ธ WARN - Yellow badge (
rgba(234, 179, 8, 0.2)bg,#eab308text) - โ ERROR - Red badge (
rgba(239, 68, 68, 0.2)bg,#ef4444text)
JSON Format (Production/Logging Services)
{
"timestamp": "2024-01-15T04:25:51.000Z",
"level": "info",
"component": "Navbar",
"message": "๐ Mounted"
}Minimal Format
[INFO] Navbar: ๐ Mounted๐ง TypeScript Support
loggerect is written in TypeScript and provides full type definitions:
import type {
LogLevel,
LogrectConfig,
HOCOptions,
DecoratorOptions,
} from "loggerect";
// All hooks and functions are fully typed
const log = useLogger<{ userId: string }>("MyComponent", {
metadata: { userId: "123" },
});๐ License
MIT ยฉ loggerect
See exactly where your logs come from.
Website ยท
GitHub ยท
npm