I have a app.js
const express = require('express');
const app = express();
const server = require('./server.js');
// app.use
const io = require('socket.io').listen(server);
io.on('connection', function (socket) {
...
});
module.exports = app;
And a server.js
const app = require('./app');
const server = app.listen(5000 || process.env.PORT, () => {
console.log('App listening on port 5000!');
})
module.exports = server;
If I put the server in a separated file the socket is not working, but if I start the server inside the app.js
the socket works.
What I'm doing wrong?
The issue here is that you have a circular dependency where app.js
is loading server.js
and server.js
is loading app.js
. You can't do that for this type of code.
It has an issue because you're trying to load server.js
from within app.js
and then in the process of loading server.js
, it attempts to load app.js
and get its exports, but app.js
hasn't finished loading yet and thus hasn't even returned its exports yet. So, the loader either thinks there are no exports or recognizes the circular request (I'm not sure which), but in either case the exports from app.js
don't work because of the circular requires.
There are several different ways to solve this. The two most common ways are:
Break some code into a common third module that each of these can load and only have one of these load the other.
Rather than having server.js
load app
to get the app
object, have app.js
pass the app
object to server.js
in a constructor function rather than trying to execute at module load time.
Here's how the constructor function idea would work:
app.js
const express = require('express');
const app = express();
// load server.js and call it's constructor, passing the app object
// that module constructor function will return the server object
const server = require('./server.js')(app);
// app.use
const io = require('socket.io').listen(server);
io.on('connection', function (socket) {
...
});
module.exports = app;
server.js
// export constructor function that must be called to initialize this module
module.exports = function(app) {
const server = app.listen(5000 || process.env.PORT, () => {
console.log('App listening on port 5000!');
});
return server;
};
So, rather than server.js
trying to load the app.js
module to get the app
object, the app
object is "pushed" to it with a constructor function. This prevents the circular dependency.