Dev tools and CLI for Remix applications providing build tools, development server, Vite integration, and command-line utilities.
—
Development server with live reload, Hot Module Replacement (HMR), and development-time optimizations for efficient Remix application development.
Development server with live reload functionality that automatically refreshes the browser when files change.
/**
* Start live reload development server
* @param config - Resolved Remix configuration
* @param options - Live reload options
* @returns Promise that resolves when server stops
*/
namespace devServer {
function liveReload(
config: ResolvedRemixConfig,
options?: LiveReloadOptions
): Promise<void>;
}
interface LiveReloadOptions {
/** Port for live reload server (default: auto-detect) */
port?: number;
/** Host for live reload server (default: localhost) */
host?: string;
/** Whether to include node_modules in file watching */
includeNodeModules?: boolean;
/** Callback called when server starts */
onStart?: (port: number) => void;
/** Callback called when file changes */
onFileChange?: (file: string) => void;
/** Callback called when rebuild starts */
onRebuildStart?: () => void;
/** Callback called when rebuild finishes */
onRebuildFinish?: (success: boolean) => void;
}Environment variable loading and management for development.
/**
* Load environment variables from .env files
* @param rootDirectory - Root directory to search for .env files
* @returns Promise that resolves when environment is loaded
*/
namespace env {
function loadEnv(rootDirectory: string): Promise<void>;
}HMR system for updating modules without full page refresh during development.
/**
* HMR update information
*/
interface Update {
/** Type of update */
type: "js-update" | "css-update" | "full-reload";
/** Timestamp of update */
timestamp: number;
/** Modules that were updated */
modules: string[];
/** Update payload */
payload?: any;
}
/**
* HMR client connection interface
*/
interface HMRClient {
/** Send update to client */
send(update: Update): void;
/** Close client connection */
close(): void;
/** Check if client is connected */
isConnected(): boolean;
}Express-compatible middleware for development features.
/**
* Create development middleware for Express
* @param config - Remix configuration
* @param options - Middleware options
* @returns Express-compatible middleware
*/
function createDevMiddleware(
config: RemixConfig,
options?: DevMiddlewareOptions
): (req: Request, res: Response, next: NextFunction) => void;
interface DevMiddlewareOptions {
/** Enable source map support */
sourceMaps?: boolean;
/** Enable request logging */
logging?: boolean;
/** Custom error handler */
onError?: (error: Error) => void;
}Advanced file watching system for development server functionality.
/**
* File watch cache for efficient file system monitoring
*/
interface FileWatchCache {
/** Start watching files */
start(): Promise<void>;
/** Stop watching files */
stop(): Promise<void>;
/** Check if file has changed */
hasChanged(file: string): boolean;
/** Get file modification time */
getModTime(file: string): Date | undefined;
/** Invalidate cache for file */
invalidate(file: string): void;
}
/**
* Create file watch cache
* @param options - Watch cache options
* @returns File watch cache instance
*/
function createFileWatchCache(options?: {
/** Directories to watch */
watchDirs?: string[];
/** File patterns to ignore */
ignore?: string[];
/** Enable polling mode */
usePolling?: boolean;
/** Polling interval in milliseconds */
pollingInterval?: number;
}): FileWatchCache;Utility functions for development server operations.
/**
* Get available port for development server
* @param preferredPort - Preferred port number
* @param host - Host to bind to
* @returns Promise resolving to available port
*/
function getPort(
preferredPort?: number,
host?: string
): Promise<number>;
/**
* Detect package manager being used
* @returns Package manager name or null if not detected
*/
function detectPackageManager(): "npm" | "yarn" | "pnpm" | null;
/**
* Check if development mode is active
* @returns Whether in development mode
*/
function isDevelopment(): boolean;
/**
* Format development server messages
* @param message - Message to format
* @param type - Message type
* @returns Formatted message
*/
function formatDevMessage(
message: string,
type?: "info" | "warn" | "error"
): string;import { devServer, readConfig } from "@remix-run/dev";
async function startDevServer() {
const config = await readConfig();
await devServer.liveReload(config, {
port: 3001,
host: "localhost",
includeNodeModules: false,
onStart: (port) => {
console.log(`Development server started on port ${port}`);
},
onFileChange: (file) => {
console.log(`File changed: ${file}`);
},
onRebuildStart: () => {
console.log("Rebuilding...");
},
onRebuildFinish: (success) => {
console.log(`Rebuild ${success ? 'completed' : 'failed'}`);
},
});
}
startDevServer().catch(console.error);import express from "express";
import { createDevMiddleware, readConfig } from "@remix-run/dev";
import { createRequestHandler } from "@remix-run/express";
async function createCustomDevServer() {
const app = express();
const config = await readConfig();
// Add development middleware
app.use(createDevMiddleware(config, {
sourceMaps: true,
logging: true,
onError: (error) => {
console.error("Development error:", error);
},
}));
// Add Remix request handler
app.all("*", createRequestHandler({
build: () => import("./build"),
mode: "development",
}));
const port = await getPort(3000);
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
}
createCustomDevServer().catch(console.error);import { createFileWatchCache } from "@remix-run/dev";
async function setupFileWatching() {
const watchCache = createFileWatchCache({
watchDirs: ["app", "public"],
ignore: ["**/node_modules/**", "**/.git/**"],
usePolling: false,
});
await watchCache.start();
// Check for changes periodically
setInterval(() => {
const files = ["app/root.tsx", "app/routes/_index.tsx"];
for (const file of files) {
if (watchCache.hasChanged(file)) {
console.log(`File changed: ${file}`);
console.log(`Modified: ${watchCache.getModTime(file)}`);
// Invalidate cache for this file
watchCache.invalidate(file);
}
}
}, 1000);
// Cleanup on exit
process.on("SIGINT", async () => {
await watchCache.stop();
process.exit(0);
});
}
setupFileWatching().catch(console.error);import { loadEnv } from "@remix-run/dev";
async function setupEnvironment() {
// Load environment variables from .env files
await loadEnv(process.cwd());
console.log("Environment loaded:");
console.log("NODE_ENV:", process.env.NODE_ENV);
console.log("DATABASE_URL:", process.env.DATABASE_URL);
console.log("SESSION_SECRET:", process.env.SESSION_SECRET ? "[REDACTED]" : "Not set");
}
setupEnvironment().catch(console.error);// Client-side HMR integration
interface HMRManager {
connect(): void;
disconnect(): void;
onUpdate(callback: (update: Update) => void): void;
}
const hmrManager: HMRManager = {
connect() {
const ws = new WebSocket("ws://localhost:3001/hmr");
ws.onmessage = (event) => {
const update: Update = JSON.parse(event.data);
switch (update.type) {
case "js-update":
// Handle JavaScript module updates
console.log("Updating JS modules:", update.modules);
break;
case "css-update":
// Handle CSS updates
console.log("Updating CSS modules:", update.modules);
this.reloadCSS();
break;
case "full-reload":
// Full page reload
window.location.reload();
break;
}
};
},
disconnect() {
// Cleanup WebSocket connection
},
onUpdate(callback) {
// Register update callback
},
reloadCSS() {
const links = document.querySelectorAll('link[rel="stylesheet"]');
links.forEach((link: HTMLLinkElement) => {
const href = link.href;
link.href = href + (href.includes("?") ? "&" : "?") + "t=" + Date.now();
});
},
};
// Initialize HMR in development
if (process.env.NODE_ENV === "development") {
hmrManager.connect();
}import { getPort, detectPackageManager } from "@remix-run/dev";
async function smartDevServer() {
// Detect package manager
const packageManager = detectPackageManager() || "npm";
console.log(`Using package manager: ${packageManager}`);
// Find available port
const port = await getPort(3000, "localhost");
console.log(`Starting development server on port ${port}`);
// Start server based on package manager
const command = {
npm: "npm run dev",
yarn: "yarn dev",
pnpm: "pnpm dev",
}[packageManager];
console.log(`Run: ${command} --port ${port}`);
}
smartDevServer().catch(console.error);Install with Tessl CLI
npx tessl i tessl/npm-remix-run--dev