Hey all,
is there any way to replace a route at runtime? I am changing the code inside the route but if I add it again it won't use the new code.
It would be very convenient to reload a specific route without restarting the whole application.
What is the recommended way to do this?
Thanks in advance.
Cheers
Bene
The simplest way to do this is the following:
let mw = funciton originalFunction (req, res) {}
app.use((req, res, next) => {
mw(req, res, next)
})
setTimeout(() => {
// sometime later
mw = function newfunction (req, res) {}
}, 5000)
Anything that you can route to will work as mw. So could replace a bundle of routes by creating a router instance, adding all the routes, then replacing with mw = routerInstance. Make sense?
To reinterpret what you're asking, I would also say that nodemon might be what you're looking for. @beneiltis
I recommend either installing to dev deps and making a script to run it or installing it globally to skip having to use a package.json script and keeping optional dependencies out of the project.
edit: Great point.
What I'm saying would only be valid for your development cycle. I hope that wouldn't be interpreted to apply to production.
Hey @etisdew, while your proposition would work, it is a bit heavy handed in that it restarts the whole process. This can cause issues depending on your application operations (for example if you do not have another 0-downtime solution requests can be dropped). I would recommend nodemon only if there is some strong reason you would want to restart the whole process.
Is there a slack that would be more appropriate for me to talk to you? I'm interested in getting up to speed and seeing if I can contribute.
I was interested to see if this would work with my application, changing route references on a closure but I wasn't successful in creating this functionality as I set the entire api(s) in one use declaration through a class constructor. Theoretically I could change and add apis to the original declaration using this method if use was referencing the same thing on change but the initial apis remain after overwriting mutation.
This leads me to believe without looking at the code there is an assignment contained behind a function I need to hit again to re set the memory pointer internally. How deep do I need to go to make router reference a specific object after use? Or revoke a use statement?
Hey @etisdew, there is the express gitter but to be honest I don't spend much time in there. There are a bunch of other people there to help though!
If you could post some code for what you are doing I can take a look and help debug why the above approach didn't work for you. But without that I am not sure I can help more.
This is what I have going on. I think rereading this discussion makes it apparent how to handle this though. And to be clear I don't have a problem yet or even a strong need for the feature but it sounds great. And I'm open for input if I can wiggle anything interesting out of this.
The closure would have to occur inside of the Ritual class at middleware declarations. (Something I'm still working out. Probably just a variadic function with check against type array[functions].) This offers a place to inject the functions from the top and presumably I'll handle the function closure at the top.
In my attempt what I did was replace the router as in a = express(), a.use(router), router = another_router. Is there a way to nuke a router and all of its routes in one go durring runtime without taking down the server and replacing it? At this point I'm thinking that this would be the simplest strat.
I would lose api worst case for a moment unless I delegated that to its own port, apache serves the static files as a backup plan.
environment, express v4, no other non-native dependancys:
https://gist.github.com/etisdew/0a1b381e2ac3eca98c7e58aa45ed637a
const express = require('express')
const app = express()
let router
function setupRouter () {
router = new express.Router()
// Setup dynamic routes here (get them from db?)
router.get('/', fnc1)
router.get('/foo', fnc2)
}
setupRouter();
app.use(function replaceableRouter (req, res, next) {
router(req, res, next)
})
// When you are ready to replace the routes, just call setup again
// Every 10 seconds it will refresh in this example
setInterval(setupRouter, 1000 * 10)
Does this help? I was not really able to understand what you were doing in the linked gist, there is alot going on there and I didn't have time to spend figuring it out.
Actually this does help. Thank you its quite clear now. I should have been adding router as an inner function call.
Hey Folks,
thanks for helping me. It works perfectly for me. I just hat to bypass the function internal include()-caching to make it work. Otherwise the file with the routing changes would be loaded correctly.
Thanks to all :-)
Most helpful comment
Does this help? I was not really able to understand what you were doing in the linked gist, there is alot going on there and I didn't have time to spend figuring it out.