Skip to main content
This covers problems that occur in Sonamu’s Hot Module Replacement (HMR) system and how to solve them.

HMR Not Working

Symptoms

The server doesn’t automatically restart when you modify files.
# Nothing happens after file modification

Causes

  1. HMR boundary not properly configured
  2. File watcher not detecting file changes
  3. HMR failure due to circular dependencies

Solutions

1. Restart Development Server

# Stop with Ctrl+C and restart
pnpm dev

2. Check HMR Boundary

HMR boundary is configured in hmr-hook-register.ts:
// src/bin/hmr-hook-register.ts
if (process.env.HOT === "yes" && process.env.API_ROOT_PATH) {
  const { hot } = await import("@sonamu-kit/hmr-hook");

  await hot.init({
    rootDirectory: process.env.API_ROOT_PATH,
    boundaries: [`./src/**/*.ts`],  // All .ts files
  });

  console.log("πŸ”₯ HMR-hook initialized");
}
Modify this file to change HMR boundaries.

3. Increase File Watcher Limit (Linux/macOS)

# Linux
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# macOS - Usually not needed

4. Check .gitignore Patterns

Performance issues can occur if HMR watches directories like node_modules or dist.

Error After File Change

Symptoms

HMR works when you modify files but errors occur:
Error: Cannot import module /src/application/user/user.model.ts

Causes

  1. Circular dependency
  2. Dynamic import not properly handled
  3. ESM/CommonJS mixing

Solutions

1. Check Circular Dependencies

# Install madge
pnpm add -D madge

# Check circular dependencies
pnpm madge --circular --extensions ts src/
Remove discovered circular dependencies:
// ❌ Circular dependency
// user.model.ts
import { PostModel } from "../post/post.model";

// post.model.ts
import { UserModel } from "../user/user.model";

// βœ… Solution: Import types only
// user.model.ts
import type { PostModel } from "../post/post.model";

// Or create common types file
// types.ts
export type { UserModel } from "./user/user.model";
export type { PostModel } from "./post/post.model";

2. Check Dynamic Imports

Avoid dynamic imports within HMR boundaries:
// ❌ Dynamic import within HMR boundary
class UserModelClass extends BaseModel {
  async getRelated() {
    const { PostModel } = await import("../post/post.model");
    return PostModel.findMany();
  }
}

// βœ… Use static import
import { PostModel } from "../post/post.model";

class UserModelClass extends BaseModel {
  async getRelated() {
    return PostModel.findMany();
  }
}

Type Error After HMR

Symptoms

TypeScript type errors occur after HMR runs:
Property 'newMethod' does not exist on type 'UserModel'

Cause

TypeScript server didn’t recognize HMR changes.

Solutions

1. Restart TypeScript Server

VSCode:
Command Palette (Cmd+Shift+P or Ctrl+Shift+P)
> TypeScript: Restart TS Server

2. Restart Editor

Command Palette
> Developer: Reload Window

3. Check tsconfig.json

{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo"
  }
}

HMR Performance Degradation

Symptoms

HMR is slow or server freezes every time you save a file.

Causes

  1. Too many files included in HMR boundary
  2. Heavy computations running at module loading time
  3. Memory leak

Solutions

1. Optimize HMR Boundary

Modify boundary pattern in hmr-hook-register.ts:
// src/bin/hmr-hook-register.ts
if (process.env.HOT === "yes" && process.env.API_ROOT_PATH) {
  const { hot } = await import("@sonamu-kit/hmr-hook");

  await hot.init({
    rootDirectory: process.env.API_ROOT_PATH,
    boundaries: [
      // Include only frequently changed files
      `./src/application/**/*.model.ts`,
      `./src/application/**/*.helper.ts`
    ],
  });
}

2. Optimize Module Initialization

Use lazy loading for heavy computations:
// ❌ Execute immediately on module load
const heavyData = processLargeDataset();

export class UserModelClass extends BaseModel {
  // ...
}

// βœ… Execute only when needed
let heavyData: any;

export class UserModelClass extends BaseModel {
  private getHeavyData() {
    if (!heavyData) {
      heavyData = processLargeDataset();
    }
    return heavyData;
  }
}

3. Memory Profiling

# Check Node.js memory usage
node --expose-gc --inspect node_modules/.bin/sonamu dev

# Memory profiling in Chrome DevTools
chrome://inspect

HMR Boundary Configuration Error

Symptoms

Error: HMR boundary pattern is invalid: /src/**/*.model.ts

Cause

HMR boundary pattern is incorrect.

Solution

Use correct glob patterns in hmr-hook-register.ts:
// src/bin/hmr-hook-register.ts
await hot.init({
  rootDirectory: process.env.API_ROOT_PATH,
  boundaries: [
    // βœ… Correct patterns (relative paths)
    `./src/application/**/*.model.ts`,
    `./src/application/**/*.helper.ts`,

    // ❌ Invalid patterns
    // "/src/**/*.ts",  // Absolute paths don't work
    // "./src/**/*.{ts,js}",  // Brace expansion not supported
  ],
});

HMR Not Working for Specific Files

Symptoms

HMR works fine for most files, but specific files don’t restart when changed.

Causes

  1. File doesn’t match HMR boundary pattern
  2. File is explicitly excluded
  3. File is cached by other modules

Solutions

1. Check If File Is Included in Boundary

# Enable HMR logging
DEBUG=hmr:* pnpm dev
Check logs when saving file:
hmr:boundary /src/application/user/user.model.ts matched +0ms
hmr:reload Reloading module: user.model +5ms

2. Clear Cache

// Restart server if there's a module cache issue

3. Check Filename Pattern

// Change filename to match HMR boundary
// user-service.ts β†’ user.helper.ts

ESM/CommonJS Mixing Issues

Symptoms

Error [ERR_REQUIRE_ESM]: require() of ES Module not supported

Cause

HMR system tried to load ESM module as CommonJS.

Solutions

1. package.json Configuration

{
  "type": "module"
}

2. Specify File Extension

// ❌
import { UserModel } from "./user.model";

// βœ…
import { UserModel } from "./user.model.js";  // Use .js for ESM

3. tsconfig.json Configuration

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}