iPzard
iPzard

Reputation: 2368

Socket.io not globally available when using Webpack

Everything was working fine before adding webpack. Here's my current config (below). Inside login.js, there's a window.onload function, then shortly after there's a socket.on function, which is now breaking the program. It seems as if "socket" is not globally available to the other files after adding webpack.

Here's the error code I receive in console when running my app:
"login.js:1 Uncaught TypeError: socket.on is not a function at window.onload (login.js:1)"

Any help or insight would be appreciated.

webpack.config

const path = require('path')

module.exports = {
    entry: {
        scripts: './src/scripts.js',
        login: './src/login.js'
    },
    output: {
        path: path.resolve(__dirname, 'public/js'),
        filename: '[name].js'
    }, 
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['env']
                }
            }
        }]
    },
    devServer: {
        contentBase: path.resolve(__dirname, 'public'),
        publicPath: '/js/'
    }
}

Script section of index.html

  <script src="./socket.io/socket.io.js"></script>
  <script src="./js/scripts.js"></script>
  <script src="./js/login.js"></script>
</body>

Worked fine before, so I don't believe there's an issue here:

Server

const http = require('http').Server(app);
const io = require('socket.io')(http);

Client
scripts.js (not in a function, globally declared):

const socket = io();
let socketid;
socket.on('connect', () =>  socketid = socket.io.engine.id);

login.js (inside window.onload function):

socket.on('check email', () => {
        setTimeout(() => refreshPage(), 7500);
        popupbox({
            titletext: 'Verify email', messagetext: 'A verification link has been sent, please verify your email address within 24 hours.', 
            okaytext: 'Okay', okayfunction: () => refreshPage(),
            customcolor: "#007C5B"
        });
    });

Upvotes: 0

Views: 1978

Answers (2)

mzparacha
mzparacha

Reputation: 675

Also you can use global to declare your variables globaly like

global.io = io();

And the use the io variable in other files like

io.on('connect',...)

Might be it would help someone in future

Upvotes: 1

t.niese
t.niese

Reputation: 40842

const socket is local to the module defined by scripts.js and is not a global variable. And as of that it does not exists in login.js.

While it would be possible to make it global, the whole idea of modules and bundlers is to encapsulate your code into small logical parts and that you don't need to pollute the global namespace.

So you need to pass your socket in some way to login.js. How you want to do that depends on the overall structure of the project.

One way could be to export it in your module, and import/require it in your login.js or where ever else you need it.

socket.js

const socket = io();
let socketid;
socket.on('connect', () =>  socketid = socket.io.engine.id);

module.exports.socket = socket; // export the socket

// could also look that way:
// module.exports = socket;
// the require would then look like that:
// const socket = require('./socket.js');

login.js

const socket = require('./socket.js').socket;

socket.on('check email', () => {
        setTimeout(() => refreshPage(), 7500);
        popupbox({
            titletext: 'Verify email', messagetext: 'A verification link has been sent, please verify your email address within 24 hours.', 
            okaytext: 'Okay', okayfunction: () => refreshPage(),
            customcolor: "#007C5B"
        });
    });

Upvotes: 2

Related Questions