CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-remix-run--dev

Dev tools and CLI for Remix applications providing build tools, development server, Vite integration, and command-line utilities.

Pending
Overview
Eval results
Files

development-server.mddocs/

Development Server

Development server with live reload, Hot Module Replacement (HMR), and development-time optimizations for efficient Remix application development.

Capabilities

Live Reload

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 Management

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>;
}

Hot Module Replacement

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;
}

Development Middleware

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;
}

File Watching

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;

Development Utilities

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;

Usage Examples

Basic Live Reload Server

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);

Custom Development Server with Express

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);

File Watching Setup

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);

Environment Loading

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);

HMR Client Integration

// 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();
}

Development Server with Custom Port Detection

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

docs

build-system.md

cli-commands.md

configuration.md

development-server.md

index.md

route-management.md

vite-integration.md

tile.json