npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@karinjs/node-hmr

v1.0.1

Published

Node.js ESM-HMR工具,自动注入--expose-internals参数

Readme

Node.js 纯 ESM 热模块替换 (HMR)

一个轻量级的 纯 ESM Node.js 热模块替换(HMR)工具,可以在不重启应用的情况下重新加载修改的 ES 模块。

English | 中文

特点

  • 纯 ESM 实现 - 专为 ES 模块设计
  • 自动注入 --expose-internals 参数,无需手动添加
  • 支持 TypeScript 和 JavaScript 文件
  • 简单易用的 API
  • 提供命令行工具

安装

# 使用 pnpm
pnpm add @karinjs/node-hmr

# 使用 npm
npm install @karinjs/node-hmr

# 使用 yarn
yarn add @karinjs/node-hmr

命令行使用

安装后,你可以使用 hmr 命令来运行你的应用,它会自动注入所需的 --expose-internals 参数:

# 运行 JavaScript 文件
hmr ./src/app.js

# 使用 tsx 运行 TypeScript 文件
hmr ./src/app.ts --tsx

# 传递其他参数
hmr ./src/server.js --port 3000

手动使用

如果你不想使用命令行工具,可以直接使用 Node.js 运行:

# 对于 JavaScript 文件
node --expose-internals ./your-file.js

# 对于 TypeScript 文件
node --expose-internals --import tsx ./your-file.ts

API 使用

你也可以在代码中直接使用 HMR API:

import { HMRModule } from "@karinjs/node-hmr";

// 创建 HMR 实例,监听文件变化
const hmr = new HMRModule("./src", {
  // 排除node_modules和test目录中的模块
  exclude: ['node_modules', 'test']
});

// 监听文件变更事件
hmr.on("change", async (fileUrl, isCached) => {
  console.log(`文件变更: ${fileUrl}`);
  if (isCached) {
    console.log("模块已从缓存中删除,可以重新导入");

    try {
      // 重新导入模块
      const module = await import(fileUrl);
      console.log("重新导入成功:", Object.keys(module));
    } catch (error) {
      console.error("重新导入失败:", error);
    }
  }
});

// 监听其他事件
hmr.on("add", (fileUrl) => {
  console.log(`文件添加: ${fileUrl}`);
});

hmr.on("unlink", (fileUrl) => {
  console.log(`文件删除: ${fileUrl}`);
});

// 获取所有被监控的文件
console.log(hmr.getWatched());

注意:API 方式使用时,仍然需要使用 --expose-internals 参数启动 Node.js。推荐使用命令行方式运行,它会自动处理这个问题。

API 参考

HMRModule

HMRModule 类继承自 EventEmitter,提供以下方法和属性:

构造函数

constructor(files: string | string[], options?: ChokidarOptions & { exclude?: string[] })
  • files: 要监控的文件路径,支持 glob 模式
  • options: chokidar 监听选项,默认值为 { ignoreInitial: true, ignored: /(^|[/\\])\./ }
    • exclude: 排除的模块路径数组,这些模块不会被包含在热更新的依赖分析中

方法

  • add(filePath: string | string[]): this - 添加监控文件
  • unwatch(filePath: string | string[]): this - 取消监控文件
  • close(): Promise<void> - 关闭监控
  • getWatched(): Record<string, string[]> - 获取所有被监控的文件

属性

  • closed: boolean - 监控是否已关闭

事件

  • 'change' - 文件内容变更时触发,参数:(fileUrl: string, isCached: boolean)
  • 'add' - 添加新文件时触发,参数:(fileUrl: string, isCached: boolean)
  • 'unlink' - 删除文件时触发,参数:(fileUrl: string, isCached: boolean)
  • 其他 chokidar 事件

实现原理

本工具专为 ES 模块 (ESM) 设计,通过 --expose-internals 标志访问 Node.js 的内部 ESM 模块缓存。当文件变更时,它会从缓存中清除相应的模块,允许重新导入更新后的代码。

工作流程如下:

  1. 工具使用 chokidar 库监控文件变化
  2. 当文件变更时,它将文件路径转换为文件 URL 格式(ESM 使用的格式)
  3. 检查模块是否存在于 ESM 模块缓存中
  4. 如果找到,则从缓存中删除模块
  5. 应用程序可以重新导入模块以获取更新后的代码

仅支持 ESM

本工具专为 ES 模块设计,不适用于 CommonJS 模块。你的项目应该在 package.json 中使用 "type": "module" 或使用 .mjs 文件扩展名。

致谢

实现思路来自于 Sylphy (QQ: 1393***348),感谢其提供的宝贵思路和技术支持。

警告

⚠️ 本工具使用 Node.js 内部 API,请勿在生产环境使用!

⚠️ 内部 API 可能随 Node.js 版本变化而变化,可能导致兼容性问题!

要求

  • Node.js 18+
  • ES 模块(不兼容 CommonJS)

许可

MIT