mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
ui: use sharedworker for messages conn
This commit is contained in:
1 parent
b0f1c0d52c
commit
a2d5996311
8 files changed
+102
-13
No files matched your search
+4
-4
@@ -28,15 +28,15 @@
|
|||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cross-spawn": "^6.0.2",
|
"@types/cross-spawn": "^6.0.2",
|
||||||
"@types/node": "^16.11.21",
|
"@types/node": "^16.11.22",
|
||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
"@typescript-eslint/eslint-plugin": "5.10.0",
|
"@typescript-eslint/eslint-plugin": "5.10.2",
|
||||||
"@typescript-eslint/parser": "5.10.0",
|
"@typescript-eslint/parser": "5.10.2",
|
||||||
"cac": "^6.7.12",
|
"cac": "^6.7.12",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
"esbuild": "0.14.3",
|
"esbuild": "0.14.3",
|
||||||
"eslint": "^8.7.0",
|
"eslint": "^8.8.0",
|
||||||
"eslint-config-airbnb-typescript": "12.3.1",
|
"eslint-config-airbnb-typescript": "12.3.1",
|
||||||
"eslint-import-resolver-typescript": "2.5.0",
|
"eslint-import-resolver-typescript": "2.5.0",
|
||||||
"eslint-plugin-import": "2.25.4",
|
"eslint-plugin-import": "2.25.4",
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ export default function (env = {}) {
|
|||||||
{ from: root('static') },
|
{ from: root('static') },
|
||||||
{ from: root(`${dirname(require.resolve('vditor/package.json'))}`), to: 'vditor/' },
|
{ from: root(`${dirname(require.resolve('vditor/package.json'))}`), to: 'vditor/' },
|
||||||
{ from: `${dirname(require.resolve('monaco-themes/package.json'))}/themes`, to: 'monaco/themes/' },
|
{ from: `${dirname(require.resolve('monaco-themes/package.json'))}/themes`, to: 'monaco/themes/' },
|
||||||
|
{ from: root('.build/sharedworker.js'), to: 'sharedworker.js' },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import cac from 'cac';
|
import cac from 'cac';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
|
import esbuild from 'esbuild';
|
||||||
import WebpackDevServer from 'webpack-dev-server';
|
import WebpackDevServer from 'webpack-dev-server';
|
||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import log from 'fancy-log';
|
import log from 'fancy-log';
|
||||||
@@ -13,9 +14,18 @@ import webpackConfig from './config/webpack';
|
|||||||
|
|
||||||
const argv = cac().parse();
|
const argv = cac().parse();
|
||||||
|
|
||||||
function runWebpack({
|
async function runWebpack({
|
||||||
watch, production, measure, dev,
|
watch, production, measure, dev,
|
||||||
}) {
|
}) {
|
||||||
|
const result = esbuild.build({
|
||||||
|
bundle: true,
|
||||||
|
format: 'iife',
|
||||||
|
entryPoints: [root('sharedworker.ts')],
|
||||||
|
outfile: root('.build/sharedworker.js'),
|
||||||
|
watch: dev || watch,
|
||||||
|
minify: production,
|
||||||
|
});
|
||||||
|
if (!dev && !watch) await result;
|
||||||
const compiler = webpack(webpackConfig({ watch, production, measure }));
|
const compiler = webpack(webpackConfig({ watch, production, measure }));
|
||||||
if (dev) {
|
if (dev) {
|
||||||
const server = new WebpackDevServer(compiler, {
|
const server = new WebpackDevServer(compiler, {
|
||||||
@@ -23,9 +33,9 @@ function runWebpack({
|
|||||||
hot: true,
|
hot: true,
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
stats: 'none',
|
stats: 'none',
|
||||||
index: '',
|
index: root('public'),
|
||||||
proxy: {
|
proxy: {
|
||||||
context: () => true,
|
context: (path) => !path.includes('sharedworker.js'),
|
||||||
target: 'http://localhost:2333',
|
target: 'http://localhost:2333',
|
||||||
ws: true,
|
ws: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const messagePage = new AutoloadPage('messagePage', (pagename) => {
|
|||||||
|
|
||||||
const { default: SockJs } = await import('../socket');
|
const { default: SockJs } = await import('../socket');
|
||||||
|
|
||||||
const sock = new SockJs('/home/messages-conn');
|
const sock = new SockJs('/home/messages-conn', true, true);
|
||||||
sock.onmessage = (message) => {
|
sock.onmessage = (message) => {
|
||||||
const msg = JSON.parse(message.data);
|
const msg = JSON.parse(message.data);
|
||||||
console.log('Received message', msg);
|
console.log('Received message', msg);
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ function remove() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class Sock {
|
export default class Sock {
|
||||||
constructor(url, showNotification = true) {
|
constructor(url, showNotification = true, useShared = false) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.shared = false;
|
||||||
this.isreconnect = false;
|
this.isreconnect = false;
|
||||||
this.retryCount = 0;
|
this.retryCount = 0;
|
||||||
this.init();
|
if (useShared && window.SharedWorker) this.initShared();
|
||||||
|
else this.init();
|
||||||
this.showNotification = showNotification;
|
this.showNotification = showNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,12 +62,25 @@ export default class Sock {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initShared() {
|
||||||
|
this.shared = true;
|
||||||
|
const worker = new SharedWorker('/sharedworker.js', { name: 'Hydro Shared Connections Worker' });
|
||||||
|
worker.port.start();
|
||||||
|
const path = `${new URL(this.url, window.location.href).href.replace('http', 'ws')}/websocket`;
|
||||||
|
worker.port.postMessage({ type: 'sharedConn', path, cookie: document.cookie });
|
||||||
|
worker.port.onmessage = (e) => {
|
||||||
|
if (e.data.type === 'message') this.onmessage({ data: e.data.payload });
|
||||||
|
};
|
||||||
|
this.worker = worker;
|
||||||
|
}
|
||||||
|
|
||||||
send(data) {
|
send(data) {
|
||||||
this.sock.send(data);
|
if (this.shared) this.worker.port.postMessage({ type: 'message', path: this.url, payload: data });
|
||||||
|
else this.sock.send(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.closed = true;
|
this.closed = true;
|
||||||
this.sock.close();
|
if (!this.shared) this.sock.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
"lib": [
|
||||||
|
"ES2020"
|
||||||
|
],
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"paths": {
|
"paths": {
|
||||||
"vj/*": [
|
"vj/*": [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.30.11",
|
"version": "4.31.0",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"@types/katex": "^0.11.1",
|
"@types/katex": "^0.11.1",
|
||||||
"@types/qrcode": "^1.4.2",
|
"@types/qrcode": "^1.4.2",
|
||||||
"@types/redux-logger": "^3.0.9",
|
"@types/redux-logger": "^3.0.9",
|
||||||
|
"@types/sharedworker": "^0.0.64",
|
||||||
"@types/sockjs-client": "^1.5.1",
|
"@types/sockjs-client": "^1.5.1",
|
||||||
"@undefined-moe/monaco-yaml": "^2.5.1",
|
"@undefined-moe/monaco-yaml": "^2.5.1",
|
||||||
"ansi_up": "^5.1.0",
|
"ansi_up": "^5.1.0",
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
"react-split-pane": "^0.1.92",
|
"react-split-pane": "^0.1.92",
|
||||||
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"redux": "^4.1.2",
|
"redux": "^4.1.2",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"redux-promise-middleware": "^6.1.2",
|
"redux-promise-middleware": "^6.1.2",
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import ReconnectingWebsocket from 'reconnecting-websocket';
|
||||||
|
|
||||||
|
console.log('SharedWorker init');
|
||||||
|
|
||||||
|
const sharedConnections: Record<string, [ReconnectingWebsocket, MessagePort[]]> = {};
|
||||||
|
interface RequestInitSharedConnPayload {
|
||||||
|
type: 'sharedConn';
|
||||||
|
cookie: any;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
interface RequestSendMessagePayload {
|
||||||
|
type: 'message';
|
||||||
|
path: string;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
type RequestPayload = RequestInitSharedConnPayload | RequestSendMessagePayload;
|
||||||
|
|
||||||
|
function broadcastMsg(ports: MessagePort[], message: any) {
|
||||||
|
for (const p of ports) p.postMessage(message);
|
||||||
|
}
|
||||||
|
function initSharedConn(path: string, port: MessagePort, cookie: any) {
|
||||||
|
if (!sharedConnections[path]) {
|
||||||
|
console.log('Init connection for', path);
|
||||||
|
const sock = new ReconnectingWebsocket(path);
|
||||||
|
const ports: MessagePort[] = [];
|
||||||
|
sharedConnections[path] = [sock, ports];
|
||||||
|
|
||||||
|
sock.onopen = () => sock.send(cookie);
|
||||||
|
sock.onmessage = (message) => {
|
||||||
|
if (process.env.NODE_ENV !== 'production') console.log('SharedWorker.port.onmessage: ', message);
|
||||||
|
const payload = JSON.parse(message.data);
|
||||||
|
if (payload.event === 'auth') {
|
||||||
|
if (['PermissionError', 'PrivilegeError'].includes(payload.error)) {
|
||||||
|
broadcastMsg(ports, { type: 'close', path, error: payload.error });
|
||||||
|
} else {
|
||||||
|
console.log('Connected to', path);
|
||||||
|
broadcastMsg(ports, { type: 'open', path });
|
||||||
|
}
|
||||||
|
} else broadcastMsg(ports, { type: 'message', path, payload: message.data });
|
||||||
|
};
|
||||||
|
sock.onerror = () => broadcastMsg(ports, { type: 'error', path });
|
||||||
|
sock.onclose = (ev) => broadcastMsg(ports, { type: 'close', path, error: ev.reason });
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedConnections[path][1].push(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
onconnect = function (e) {
|
||||||
|
const port = e.ports[0];
|
||||||
|
|
||||||
|
port.addEventListener('message', (msg: { data: RequestPayload }) => {
|
||||||
|
if (msg.data.type === 'sharedConn') initSharedConn(msg.data.path, port, msg.data.cookie);
|
||||||
|
if (msg.data.type === 'message') sharedConnections[msg.data.path]?.[0].send(msg.data.payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
port.start();
|
||||||
|
};
|
||||||
Reference in new issue
Block a user