react-starter-kit: Can't find the way to integrate socket.io and redux-socket.io
Hello, I can’t find the way to establish a communication with a socket.io port… it works on the build but i have some kind of conflict with Browser-sync, i tried different configurations, but it doesn’t establish the connection. In some cases i receive a 404 error page from express.
Here is the code, please help me on how to revolve this issue or how te remove or deactivate browser-sync, is not critic for my project. But when i tried to remove the dev version stop to works, I don’t know how to replace Browser-sync, to keep the dev environment with HMR operational.
Please I’ll appreciate any orientation, I’ve invested a lot of time in this issue and it surpasses me.
CLIENT SIDE // /src/store/configureStore.js
import createSocketIoMiddleware from 'redux-socket.io';
import { createSocket, registerListenersSocket } from '../lib/functions';
...
let socketIoMiddleware, socket;
if (process.env.BROWSER) {
socket = createSocket();
console.log('socket', socket);
const socketDebug = (action, emit, next, dispatch ) => {
console.log('socket middleware: ', { action, emit, next, dispatch });
next();
};
socketIoMiddleware = createSocketIoMiddleware(socket, 'server/', socketDebug);
}
export default function configureStore(initialState, helpersConfig) {
...
const middleware = [];
const sagaMiddleware = createSagaMiddleware();
middleware.push(sagaMiddleware);
if (process.env.BROWSER) {
console.log('adding socket middleware');
middleware.push(socketIoMiddleware);
}
let enhancer;
if (__DEV__) {
middleware.push(createLogger());
// https://github.com/zalmoxisus/redux-devtools-extension#redux-devtools-extension
let devToolsExtension = f => f;
if (process.env.BROWSER && window.devToolsExtension) {
devToolsExtension = window.devToolsExtension();
}
enhancer = compose(applyMiddleware(...middleware), devToolsExtension);
} else {
enhancer = applyMiddleware(...middleware);
}
// See https://github.com/rackt/redux/releases/tag/v3.1.0
const store = createStore(rootReducer, initialState, enhancer);
if (process.env.BROWSER) {
registerListenersSocket(socket, store);
}
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
if (__DEV__ && module.hot) {
module.hot.accept('../reducers', () =>
// eslint-disable-next-line global-require
store.replaceReducer(require('../reducers').default),
);
}
store.runSaga = sagaMiddleware.run;
store.close = () => store.dispatch(END);
return store;
}
/src/lib/functions.js
import io from 'socket.io-client';
import {
socketConnect,
socketReconnect,
socketDisconnect,
socketConnectionError,
} from '../actions/server';
export const calcProgress = (dateStr, limit) => {
const date = new Date(dateStr);
const now = new Date(Date.now());
const days = Math.floor((Date.now() - date) / (3600000 * 24));
return {
days,
percent: Math.round(Math.min(100, days / limit * 100)),
};
};
export function createSocket() {
// todo: access configuration by conf.
const serverURL = process.env.SOCKET_SERVER;
console.log('connecting socket on: ');
return io();
}
export function registerListenersSocket(socket, store) {
socket.on('connect', () => store.dispatch(socketConnect()));
socket.on('connect_timeout', () => store.dispatch(socketConnectionError()));
socket.on('connect_error', () =>
store.dispatch(
socketConnectionError(new Error('Error al conectar el socket.')),
),
);
socket.on('reconnect_error', () =>
store.dispatch(
socketConnectionError(new Error('Error al reconectar el socket.')),
),
);
socket.on('disconnect', () => store.dispatch(socketDisconnect()));
socket.on('reconnect', () => store.dispatch(socketReconnect()));
}

SERVER SIDE /src/server.js
...
import socket from './lib/socket';
const app = express();
app.server = http.createServer(app);
socket(app, process);
...
/src/lib/socket
import SocketIO from 'socket.io';
...
export default function socketConnection (app, process) {
...
/** SOCKET CONNECTION */
console.log('** socket connection');
const { server } = app;
const sockets = {};
const io = new SocketIO(server);
io.on('connection', socket => {
console.log('socket connected'); /** <-- I never get this **/
sockets[socket.id] = socket; // socket table.
console.log('sending hello acknowledge');
socket.emit('action', {type: 'server/HELLO', payload: {message: 'socket connected', code: 1} });
socket.on('action', (action) => {
console.log('socket action:', action);
switch (action.type) {
case 'server/CALL': {
const {source, target, leadId, agentId} = action.payload;
console.log('call');
console.log('source', source);
console.log('target', target);
crmami.call(source, target, {
socketId: socket.id,
leadId,
agentId
},
(error) => {
socket.emit('action', {
type: 'server/CALL_FAIL',
payload: { error }
})
});
}
}
});
socket.on('disconnect', () => {
delete sockets[socket.id];
});
});
process.on('exit', () => {
crmami.disconnect();
crmami.destroy();
})
}
/tools/start.js
...
await new Promise((resolve, reject) =>
browserSync.create().init(
{
socket: {
path: '/bs/socket.io',
clientPath: '/browser-sync',
namespace: '/bs',
domain: undefined,
port: undefined,
'clients.heartbeatTimeout': 5000
},
// // socket: {
// // namespace: `http://localhost:3000/bs`
// // },
server: 'src/server.js',
port: config.port,
middleware: [server],
open: !process.argv.includes('--silent'),
...(isDebug ? {} : { notify: false, ui: false }),
},
(error, bs) => (error ? reject(error) : resolve(server)),
)
);
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 17 (1 by maintainers)
@alvaroqt, Hey you can integrate Socket IO server for prod build by replacing this code in
src/server.jswith this
Hypothetically speaking, I’d try to make a
socket.jsfile undersrc, add a socket section in the webpack config and then mimic the server creation steps in/tools/start.jsfor the socket server. The socket should be it’s own entity just like the current server and in a production build, be separable so you could slap it on it’s own machine. Then adding in the ws apollo link is pretty self explanatoryI’ve been playing around with this…
The biggest problem I can see is dealing with auth. you could use something like
socket-jwt-authbut that relies on passing the jwt as a query string. Alternatively you can implement some sort of authentication exchange after a socket connects like thisI also had trouble with the server reloading, like at first glance I can’t see how react-starter-kit decides what to kill when you save a file, so on every reload my
src/servertries to spawn another socket server but collides with the previous one still listening on that port.I’ve created a new server with a new port and it works… I’m not sure if it’s the best way, but it works, any comment will be appreciated.
CLIENT SIDE /src/lib/functions
SERVER SIDE /src/lib/socket