【问题标题】:Socket.io not globally available when using Webpack使用 Webpack 时 Socket.io 不全局可用
【发布时间】:2019-01-21 19:36:57
【问题描述】:

在添加 webpack 之前一切正常。这是我当前的配置(下)。在 login.js 中,有一个 window.onload 函数,然后不久之后有一个 socket.on 函数,它现在正在破坏程序。添加 webpack 后,似乎“socket”对其他文件不全局可用。

这是我在运行我的应用程序时在控制台中收到的错误代码:
“login.js:1 Uncaught TypeError: socket.on is not a function at window.onload (login.js:1)”

任何帮助或见解将不胜感激。

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/'
    }
}

index.html 的脚本部分

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

以前工作得很好,所以我认为这里没有问题:

服务器

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

客户
scripts.js(不在函数中,全局声明):

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

login.js(window.onload 函数内):

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"
        });
    });

【问题讨论】:

  • 你必须显示你创建socket io客户端实例的相关代码,你import/require的位置,以及你调用socket.on的位置
  • 我不是指服务器端import/require。我的意思是客户端,你在哪里设置socket变量?
  • 你真的应该在你的规则中exclude: /node_modules/吗?我有一个工作的 socket.io-webpack-combo 没有它,你可能只是打包你的前端而没有 socket.io
  • 这是为了让项目更容易移动和编译更快,因为它们很容易用 npm install 创建,而且不是我要编辑的代码。但我尝试删除该行以查看它是否有效,但我仍然收到错误。

标签: javascript node.js express webpack socket.io


【解决方案1】:

const socketscripts.js 定义的模块的局部变量,不是全局变量。截至目前,它在login.js 中不存在。

虽然可以使其全局化,但模块和捆绑器的整个想法是将您的代码封装成小的逻辑部分,并且您不需要污染全局命名空间。

所以您需要以某种方式将您的socket 传递给login.js。您希望如何做到这一点取决于项目的整体结构。

一种方法是将其导出到您的模块中,并将import/require 导出到您的login.js 或您需要的任何其他位置。

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"
        });
    });

【讨论】:

  • 您有一些拼写错误(moudle),但我能够使用您的建议来克服错误,谢谢一百万!
【解决方案2】:

您也可以使用 global 来像全局一样声明变量

global.io = io();

并且在其他文件中使用 io 变量,例如

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

将来可能会对某人有所帮助

【讨论】:

  • 使用 global 确实可行,但你真的应该只在没有其他方法的情况下使用它们。例如。如果您需要将数据传递给期望将其设置为全局的第 3 方脚本。
猜你喜欢
  • 2021-02-08
  • 1970-01-01
  • 2017-05-07
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
  • 2020-11-29
相关资源
最近更新 更多