node-dev
node-dev copied to clipboard
Explicitly watch files?
Is there a way to explicitly monitor files or directories for changes than the ones that were 'require'ed via the entry point?
My use cases would be, I have a 'config.ini' but this file gets loaded via 'ini' package, and not get hooked into node-dev for reload if it changes, and also for other 'require'ed files that only get loaded later, which are also not hooked until needed and the changes to them won't get picked up before they're actually used.
That'd be useful for me too. I'm testing a dataset processing script that takes a bunch of yaml files and transforms them. It'd be great if I could watch those yamls too, just like with nodemon.
PS: I'm using ts-node-dev, which works on top of node-dev.
Temporary workaround:
const filewatcher = require("filewatcher");
const doAll = async () => {
console.log('script logic');
};
(async () => {
const watcher = filewatcher();
watcher.add('/path/to/yamls');
watcher.on("change", () => doAll());
await doAll();
})();
In this case, a change to a yaml file reruns the script logic without triggering a reload in node-dev.
+1, would be great to add some files to the auto reload logic
I would also need this for template files, which are not required in any script but will be cached so need to be refreshed.
+1 I'm working on a GraphQL server and want to reload some .graphqls files that I'm reading with fs.
Another vote for additional entrypoints for dynamically imported / forked modules.
Obviously it would have to be treated differently than simply watching other files for changes. This would just be to eagerly hook into other entrypoints that would normally be invoked by dynamic import() or child_process.fork
// .node-dev.json
// Eagerly hook into modules that may be required later
"include": [
"some/other/module.js"
]
For other files like configurations something could be added that just adds globs to filewatcher a lá @kachkaev 's comment
// .node-dev.json
// Watch non-js files for changes
"watch": [
"config/*.yaml"
]
would be great.
Here's a more general workaround inspired by @kachkaev 's solution but that actually triggers a node-dev restart.
Just import this on server startup (well - and possibly heavily modify based on your project architecture :wink:):
import chokidar from 'chokidar';
import fs from 'fs';
import path from 'path';
import {dummy} from './doServerRestart';
function triggerServerRestart() {
// Use of `dummy` is required for node-dev restart to trigger.
console.log(
'Restarting server due to GraphQL schema change - previous restart @',
new Date(dummy)
);
fs.writeFileSync(
path.join(__dirname, 'doServerRestart.ts'),
`export const dummy = ${Date.now()};`
);
}
if (process.env.NODE_ENV !== 'production') {
const watcher = chokidar.watch(path.join(__dirname, '../**/*.graphql'), {
ignoreInitial: true,
});
watcher
.on('add', triggerServerRestart)
.on('change', triggerServerRestart)
.on('unlink', triggerServerRestart);
}
I found an even easier (but super ugly) workaround to explicitly watch files. This is a crappy kluge and you should not use it.
// Hack to include the '.env' file into the watched file list so that
// node-dev will restart the server whenever .env changes
if (process.env.NODE_ENV !== 'production') {
try {
require('../.env')
} catch (err) {
// Ignore the expected error
}
}
I found a slightly nicer way to implement @s-h-a-d-o-w's code which doesn't leak anything into production and you can put doServerRestart.ts in .gitignore as it'll be created on startup.
import chokidar from 'chokidar';
import fs from 'fs';
import path from 'path';
if (process.env.NODE_ENV !== 'production') {
function updateServerRestartFile(): void {
fs.writeFileSync(
path.join(__dirname, 'doServerRestart.ts'),
`export const dummyDate = ${Date.now()};`,
)
}
updateServerRestartFile()
// Use of `dummyDate` is required for node-dev restart to trigger on GraphQL schema change.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const serverRestart = require('./doServerRestart')
function triggerServerRestart(): void {
console.log(
'Restarting server due to GraphQL schema change - previous restart @',
new Date(serverRestart.dummyDate),
)
updateServerRestartFile()
}
const watcher = chokidar.watch(path.join(__dirname, 'schema.graphql'), {
ignoreInitial: true,
})
watcher
.on('add', triggerServerRestart)
.on('change', triggerServerRestart)
.on('unlink', triggerServerRestart)
}
But also, I just found out that ts-node-dev now has a --watch flag so I could just do ts-node-dev --watch src/schema.graphql --respawn --transpile-only src/index.ts without all this!