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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hediet/node-reload

v0.8.0

Published

[![](https://img.shields.io/twitter/follow/hediet_dev.svg?style=social)](https://twitter.com/intent/follow?screen_name=hediet_dev)

Downloads

5,156

Readme

Hot Reloading for NodeJS

A thoughtfully designed library that brings advanced hot reloading to NodeJS.

Features

  • Tracks a dependency graph (files in node_modules and there like can be ignored).
  • Tracked files are watched for changes.
  • If a file has changed, reconcilers try to apply the change to the running app on a module basis.
  • If a reconciler is not successful, the reconcilers of the dependees are asked to apply the change.
  • The Update Reconciler provides functions to propagate reloaded items to the original items.
  • The Steps Execution System implements function level hot reload.

Usage

Installation

yarn add @hediet/node-reload

or

npm install @hediet/node-reload --save

See the ./examples folder for detailed examples. Works best with TypeScript.

Plain Hot Require

hotRequire is the way to go if you just want to watch a module and its dependencies for changes.

import { enableHotReload, hotRequire } from "@hediet/node-reload";

// Call `enableHotReload` to track dependencies and watch for file changes.
enableHotReload();

hotRequire<typeof import("./dep")>(module, "./dep", cur => {
	// Runs immediately or when `dep` (or any dependency of `dep`) changes.
	console.log("value of x: ", cur.x);
});

Hot Require Exported Items

hotRequireExportedFn makes it very easy to track changes of exported functions and classes.

import {
	registerUpdateReconciler,
	hotRequireExportedFn,
	getReloadCount,
	enableHotReload,
} from "@hediet/node-reload";

enableHotReload();
// Call `registerUpdateReconciler` to mark this module as reconcilable.
// If this module (or any dependency that could not be reconciled) changes,
// the `UpdateReconciler` is asked to apply the new module to the old.
// The `UpdateReconciler` powers `getReloadCount`, `hotRequireExportedFn`,
// `runExportedSteps` and other functions.
registerUpdateReconciler(module);

export function foo(arg: string) {
	console.log(arg + " change me");
}

if (getReloadCount(module) === 0) {
	// only cause side effect on initial load as the entire module is run again on each reload
	hotRequireExportedFn(module, foo, { hasFnChanged: "useSource" }, foo => {
		// is called immediately and whenever the source of `foo` changes.
		foo();
		return { dispose: () => console.log("Free any resources from last invocation"); };
	});
}

Hot Reloading Methods

You can use @hotMethod to mark a method of a class as hot, and @hotClass to mark all class methods as hot. Hot methods check before entering and after leaving whether their source has changed. If the source of an hot method changes, the very first caller whose source has changed is restarted.

You can call restartOnReload to check whether the source of any active hot method has changed. If it changed, restartOnReload will throw so it can also restart loops.

Hot methods are especially useful when working with typescripts compiler API.

Demo

import {
	registerUpdateReconciler,
	hotRequireExportedFn,
	getReloadCount,
	enableHotReload,
} from "@hediet/node-reload";

enableHotReload();

// a reconciler must reload the module
registerUpdateReconciler(module);

// Marks every method as hot.
@hotClass(module)
class Test {
	public main(): void {
		console.log("main");
		const r = this.max(10, 14);
		console.log("max is: ", r);
	}

	// internally, `max` is wrapped in `max@hot-wrapper`.
	private max(m: number, n: number): number {
		console.log(`Compute max(${m}, ${n})`);
		let result = m > n ? n : m;
		// Add a breakpoint here and fix the bug
		// while `tsc --watch` and your program are running.
		// Then `max` is executed again
		// and the new result value is return to the caller.
		console.log(`Result is: `, result);
		return result;
	}
}

if (getReloadCount(module) === 0) {
	new Test().main();
	disableHotReload();
}

Vs Code Extension Reloading

With hotRequireExportedFn you can easily make your VS Code Extension really hot. Note how the status bar updates:

import {
	enableHotReload,
	hotRequireExportedFn,
	registerUpdateReconciler,
} from "@hediet/node-reload";
import { Disposable } from "@hediet/std/disposable";
import * as vscode from "vscode";

if (isDevMode()) {
	enableHotReload({ entryModule: module });
}
registerUpdateReconciler(module);

export class Extension {
	public readonly dispose = Disposable.fn();

	constructor() {
		super();

		// Disposables are disposed automatically on reload.
		const item = this.dispose.track(vscode.window.createStatusBarItem());
		item.text = "Hallo Welt";
		item.show();
	}
}

export function activate(context: vscode.ExtensionContext) {
	context.subscriptions.push(
		hotRequireExportedFn(module, Extension, Extension => new Extension())
	);
}

Steps Execution System

The steps execution system is especially useful in connection with puppeteer. See the ./examples folder on how to use this with puppeteer.

The system however is independent from any libraries:

enableHotReload();
registerUpdateReconciler(module);
// Runs the given steps and applies updates by unwinding already executed steps and running the new steps.
// Unchanged last steps are run on initial load,
// unwound when steps before them change, but only run again when they or a step after them changes.
// This way you can edit and hot reload intermediate steps without running all steps again after every change.
runExportedSteps(module, getSteps);

export function getSteps(): Steps {
	return steps(
		{
			id: "start",
			run: async (args, { onRewind }) => {
				await slowLog("start");
				onRewind(() => slowLog("undo start"));
				return { data: 9 };
			},
		},
		{
			id: "continue1",
			run: async (args, { onRewind }) => {
				await slowLog("continue 1");
				onRewind(() => slowLog("undo 1"));
				return { data2: 10, ...args };
			},
		},
		{
			id: "continue2",
			run: async (args, { onRewind }) => {
				await slowLog("continue 2");
				onRewind(() => slowLog("undo 2"));
				return {};
			},
		}
	);
}

There is also the vscode extension "Live Debug" that displays the current executation state when debugging such an application:

Execution state

You can even use vscode to run a specific step:

Move to step

It integrates very well with puppeteer:

Puppeteer Demo

Similar libs

Changelog

  • 0.0.2 - Initial release.
  • 0.4.2 - Implements Live Debug