如何在NuxtJS v2.14.12中使用Shared-Workers共享WebSocket连接?
核心思路
Nuxt PWA模块基于Workbox,我们可以通过自定义Workbox配置注入Shared Worker,让同域下的所有标签页复用同一个WebSocket连接,避免重复建立连接造成资源浪费。
具体实现步骤
1. 创建Shared Worker文件
在项目static目录下新建shared-worker.js,实现WebSocket的共享管理逻辑:
let socket = null; const connections = new Set(); // 处理页面连接 self.onconnect = (e) => { const port = e.ports[0]; connections.add(port); port.onmessage = (msg) => { switch(msg.data.type) { case 'INIT': if (!socket) { // 初始化WebSocket连接 socket = new WebSocket('ws://你的后端WebSocket地址'); socket.onopen = () => broadcast({ type: 'CONNECTED' }); socket.onmessage = (event) => broadcast({ type: 'MESSAGE', data: event.data }); socket.onerror = (error) => broadcast({ type: 'ERROR', error: error.message }); socket.onclose = () => { broadcast({ type: 'DISCONNECTED' }); socket = null; }; } else { port.postMessage({ type: 'CONNECTED' }); } break; case 'SEND': if (socket?.readyState === WebSocket.OPEN) { socket.send(msg.data.content); } break; case 'DISCONNECT': connections.delete(port); // 无页面连接时主动关闭WebSocket if (connections.size === 0 && socket) socket.close(); break; } }; port.start(); }; // 广播消息到所有关联页面 function broadcast(message) { connections.forEach(port => { try { port.postMessage(message); } catch(e) { connections.delete(port); } }); }
2. 配置Nuxt PWA的Workbox
修改nuxt.config.js中的pwa配置,将Shared Worker注入到Workbox并配置缓存:
export default { pwa: { workbox: { // 导入Shared Worker脚本 importScripts: [ '/shared-worker.js' ], // 缓存Shared Worker文件 runtimeCaching: [ { urlPattern: '/shared-worker.js', handler: 'CacheFirst', options: { cacheName: 'shared-worker-cache' } } ] } } }
3. 封装页面端WebSocket操作插件
在plugins/websocket.js中封装Shared Worker的调用逻辑,全局注入到Nuxt应用:
class SharedWebSocket { constructor() { this.worker = new SharedWorker('/shared-worker.js'); this.port = this.worker.port; this.listeners = {}; this.port.onmessage = (e) => { const { type, data, error } = e.data; this.listeners[type]?.forEach(callback => callback(data, error)); }; this.port.start(); this.init(); } init() { this.port.postMessage({ type: 'INIT' }); } send(content) { this.port.postMessage({ type: 'SEND', content }); } on(type, callback) { if (!this.listeners[type]) this.listeners[type] = []; this.listeners[type].push(callback); } off(type, callback) { if (this.listeners[type]) { this.listeners[type] = this.listeners[type].filter(cb => cb !== callback); } } disconnect() { this.port.postMessage({ type: 'DISCONNECT' }); this.port.close(); } } export default ({ app }, inject) => { inject('websocket', new SharedWebSocket()); };
接着在nuxt.config.js中注册插件:
export default { plugins: [ '~/plugins/websocket.js' ] }
4. 在组件中使用共享连接
<template> <div> <input v-model="inputMsg" placeholder="输入消息"> <button @click="sendMsg">发送</button> <div class="msg-list"> <div v-for="msg in messages" :key="msg.id"> {{ msg.content }} </div> </div> </div> </template> <script> export default { data() { return { inputMsg: '', messages: [], msgId: 0 }; }, mounted() { this.$websocket.on('CONNECTED', () => console.log('WebSocket已连接')); this.$websocket.on('MESSAGE', (data) => { this.messages.push({ id: this.msgId++, content: data }); }); this.$websocket.on('DISCONNECTED', () => console.log('WebSocket已断开')); }, beforeDestroy() { this.$websocket.disconnect(); }, methods: { sendMsg() { if (this.inputMsg.trim()) { this.$websocket.send(this.inputMsg); this.inputMsg = ''; } } } }; </script>
注意事项
- Shared Worker仅支持同域页面共享,跨域场景无法使用
- 浏览器兼容性:现代主流浏览器均支持Shared Worker,需确认目标运行环境
- 更新Shared Worker代码后,需修改文件名或添加版本号(如
shared-worker.v2.js)触发缓存刷新
内容的提问来源于stack exchange,提问作者Bruno Cardoso
相关产品推荐
相关产品推荐

