Stale compiled output after editing CoffeeScript files when using coffeescript/register
0 reputation · 26 Jan 2021, 05:41 UTC
0 reputation · 26 Jan 2021, 05:41 UTC
When the CoffeeScript Node extension (coffeescript/register) is used, the compiler caches the generated JavaScript in Node's module cache so that subsequent require calls return the same compiled output.
The goal is to determine whether the extension provides a mechanism to automatically refresh this cached JavaScript when the source .coffee file changes, without resorting to a full require‑cache purge that could affect other modules.
Current observations show that edits to the source file are not reflected until the Node process restarts or the specific cache entry is manually removed, but it is unclear if this behavior is intentional, configurable, or a limitation of the underlying module‑caching system.
coffeescript/register to disable or bypass its internal caching?33775 reputation · 26 Jan 2021, 13:25 UTC
The coffeescript/register extension does not provide a built‑in option to disable or bypass its internal caching. To see changes in a CoffeeScript file you must invalidate the corresponding entry in Node’s require.cache (or restart the process).
coffeescript/register hooks into Node’s require system and, the first time a .coffee module is loaded, compiles it to JavaScript and stores the result in require.cache.// Example: recompile ./src/app.coffee on each load
const path = require('path');
const modPath = path.resolve('./src/app.coffee');
// Remove any cached version
if (require.cache[modPath]) delete require.cache[modPath];
// Now require will trigger coffeescript/register to recompile
const app = require(modPath);
console.log(app);
.coffee file changes (e.g., nodemon or node-dev):nodemon --exec 'node -r coffeescript/register' ./src/index.coffee
import statements) the require.cache mechanism does not apply; in that case a process restart is currently the only reliable way to see updates.If you are using a custom module resolver or bundler that alters how require.resolve works, please confirm the exact resolved path of the CoffeeScript file so the cache‑deletion step targets the correct entry.
Use comments to ask for clarification. Post a solution as an answer.
33,775 reputation · 26 Jan 2021, 11:04 UTC
You can avoid a full process restart by pairing a file watcher (e.g., chokidar) with precise require.cache deletion. Resolve the absolute path first, then delete only that entry before re-requiring:
const chokidar = require('chokidar');
const path = require('path');
function refreshCoffeeModule(relativePath) {
const abs = path.resolve(relativePath);
const key = require.resolve(abs); // normalizes to the cached key
if (require.cache[key]) delete require.cache[key];
return require(key); // triggers coffeescript/register recompilation
}
chokidar.watch('src/**/*.coffee').on('change', (file) => {
try { refreshCoffeeModule(file); }
catch (e) { console.error('Recompile failed:', e); }
});
Caveat: If other modules have already imported the compiled version, they will still hold the old exports. This pattern works best when the changed module is a leaf dependency or when you can coordinate a controlled reload of dependents.