From 4a1240b2dbe8644e78ef5ae2653cae9f6c69e5b4 Mon Sep 17 00:00:00 2001 From: Max G Date: Wed, 4 Oct 2023 11:50:53 +0530 Subject: [PATCH] fix(robot): fallback in case shared worker not supported (#963) * fix(backend): fallback in case shared worker not supproted * refact(workers); tiny refactoring for callback * refact(workers); reuse expose method for fallback BL * refact(workers): simplify fallback --- package.json | 3 +- .../backend/workers/background/service.ts | 14 ++++--- .../backend/workers/background/worker.ts | 7 ++-- src/services/backend/workers/db/service.ts | 14 ++++--- src/services/backend/workers/db/worker.ts | 7 ++-- src/services/backend/workers/workerUtils.ts | 28 ++++++++++++++ webpack.config.common.js | 5 ++- webpack.config.dev.js | 3 ++ webpack.config.prod.js | 3 +- webpack/BundleInfoPlugin.js | 38 +++++++++++++++++++ yarn.lock | 5 +++ 11 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 src/services/backend/workers/workerUtils.ts create mode 100644 webpack/BundleInfoPlugin.js diff --git a/package.json b/package.json index cc23909dc..8eba65352 100644 --- a/package.json +++ b/package.json @@ -234,7 +234,8 @@ "ts-jest-resolver": "^2.0.1", "videostream": "^3.2.2", "web3": "1.2.4", - "web3-utils": "^1.2.4" + "web3-utils": "^1.2.4", + "worker-url": "^1.1.0" }, "prec-commit": [ "lint" diff --git a/src/services/backend/workers/background/service.ts b/src/services/backend/workers/background/service.ts index 2efd18c6f..b0e214e1a 100644 --- a/src/services/backend/workers/background/service.ts +++ b/src/services/backend/workers/background/service.ts @@ -1,8 +1,12 @@ -import { wrap } from 'comlink'; +import { WorkerUrl } from 'worker-url'; import { BackendWorkerApi } from './worker'; +import { createWorker } from '../workerUtils'; -const worker = new SharedWorker(new URL('./worker.ts', import.meta.url), { - name: 'cyb~backend', -}); +const workerUrl = new WorkerUrl(new URL('./worker.ts', import.meta.url)); -export const backendApi = wrap(worker.port); +export const { apiProxy: backendApi } = createWorker( + workerUrl, + 'cyb~backend' +); + +// export const backendApi; diff --git a/src/services/backend/workers/background/worker.ts b/src/services/backend/workers/background/worker.ts index 8c46d7ab5..b5fb9189c 100644 --- a/src/services/backend/workers/background/worker.ts +++ b/src/services/backend/workers/background/worker.ts @@ -1,4 +1,3 @@ -import { expose } from 'comlink'; import { AppIPFS, IPFSContent } from 'src/utils/ipfs/ipfs'; import { IpfsOptsType } from 'src/contexts/ipfs'; @@ -27,6 +26,7 @@ import { PlainCyberLink, importCyberlinks as importCyberlinks_, } from './importers/links'; +import { exposeWorker, onConnect } from '../workerUtils'; const backendApiFactory = () => { let ipfsNode: AppIPFS | undefined; @@ -153,6 +153,5 @@ const backendApi = backendApiFactory(); export type BackendWorkerApi = typeof backendApi; -// Expose the API to the main thread -// expose(backendApi); -onconnect = (e) => expose(backendApi, e.ports[0]); +// Expose the API to the main thread as shared/regular worker +exposeWorker(self, backendApi); diff --git a/src/services/backend/workers/db/service.ts b/src/services/backend/workers/db/service.ts index b193f0153..e89a613b7 100644 --- a/src/services/backend/workers/db/service.ts +++ b/src/services/backend/workers/db/service.ts @@ -1,12 +1,16 @@ -import { wrap, proxy } from 'comlink'; +import { proxy } from 'comlink'; import { waitUntil } from 'src/utils/async/utils'; +import { WorkerUrl } from 'worker-url'; import { DbWorkerApi } from './worker'; +import { createWorker } from '../workerUtils'; -const worker = new SharedWorker(new URL('./worker.ts', import.meta.url), { - name: 'cyb~cozodb', -}); -const dbApiProxy = wrap(worker.port); +const workerUrl = new WorkerUrl(new URL('./worker.ts', import.meta.url)); + +const { apiProxy: dbApiProxy } = createWorker( + workerUrl, + 'cyb~cozodb' +); function dbServiceApi() { let isInitialized = false; diff --git a/src/services/backend/workers/db/worker.ts b/src/services/backend/workers/db/worker.ts index dad1e35d9..ea2cf4bf3 100644 --- a/src/services/backend/workers/db/worker.ts +++ b/src/services/backend/workers/db/worker.ts @@ -1,6 +1,6 @@ -import { expose } from 'comlink'; import BcChannel from 'src/services/backend/channels/BroadcastChannel'; import cozoDb from 'src/services/CozoDb/cozoDb'; +import { exposeWorker } from '../workerUtils'; const dbApiFactory = () => { console.log('----dbApi worker constructor!'); @@ -69,6 +69,5 @@ const dbApi = dbApiFactory(); export type DbWorkerApi = typeof dbApi; -// Expose the \API to the main thread -// expose(api); -onconnect = (e) => expose(dbApi, e.ports[0]); +// Expose the API to the main thread as shared/regular worker +exposeWorker(self, dbApi); diff --git a/src/services/backend/workers/workerUtils.ts b/src/services/backend/workers/workerUtils.ts new file mode 100644 index 000000000..cf83edf78 --- /dev/null +++ b/src/services/backend/workers/workerUtils.ts @@ -0,0 +1,28 @@ +import { wrap, Remote, expose } from 'comlink'; + +type WorkerType = SharedWorker | Worker; + +// Create Shared Worker with fallback to usual Worker(in case of DEV too) +// eslint-disable-next-line import/prefer-default-export +export function createWorker( + workerUrl: URL, + workerName: string +): { worker: WorkerType; apiProxy: Remote } { + const isSharedWorkersSupported = typeof SharedWorker !== 'undefined'; + + if (isSharedWorkersSupported && !process.env.IS_DEV) { + const worker = new SharedWorker(workerUrl, { name: workerName }); + return { worker, apiProxy: wrap(worker.port) }; + } + + const worker = new Worker(workerUrl); + return { worker, apiProxy: wrap(worker) }; +} + +export function exposeWorker(worker: WorkerType, api: T) { + if (typeof worker.onconnect !== 'undefined') { + worker.onconnect = (e) => expose(api, e.ports[0]); + } else { + expose(api); + } +} diff --git a/webpack.config.common.js b/webpack.config.common.js index e7068a6b0..b2e9f8bb3 100644 --- a/webpack.config.common.js +++ b/webpack.config.common.js @@ -4,8 +4,8 @@ const webpack = require('webpack'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HTMLWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); const BootloaderPlugin = require('./src/components/loader/webpack-loader'); +const WorkerUrlPlugin = require('worker-url/plugin'); require('dotenv').config(); @@ -60,6 +60,7 @@ const config = { }, }, plugins: [ + new WorkerUrlPlugin(), new NodePolyfillPlugin(), new webpack.NormalModuleReplacementPlugin(/node:/, (resource) => { const mod = resource.request.replace(/^node:/, ''); @@ -78,7 +79,7 @@ const config = { new BootloaderPlugin(HTMLWebpackPlugin, { script: './src/components/loader/loader.js', }), - new ReactRefreshWebpackPlugin(), + new HTMLWebpackPlugin({ template: path.join(__dirname, 'src', 'index.html'), favicon: 'src/image/favicon.ico', diff --git a/webpack.config.dev.js b/webpack.config.dev.js index 901e175da..821bf30db 100644 --- a/webpack.config.dev.js +++ b/webpack.config.dev.js @@ -1,5 +1,7 @@ const webpack = require('webpack'); const { merge } = require('webpack-merge'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); + const commonConfig = require('./webpack.config.common'); module.exports = merge(commonConfig, { @@ -25,5 +27,6 @@ module.exports = merge(commonConfig, { ).definitions, 'process.env.IS_DEV': JSON.stringify(true), }), + new ReactRefreshWebpackPlugin(), ], }); diff --git a/webpack.config.prod.js b/webpack.config.prod.js index 656f4c87f..0bc60a0ad 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -3,6 +3,7 @@ const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const CompressionWebpackPlugin = require('compression-webpack-plugin'); const commonConfig = require('./webpack.config.common'); +const BundleInfoPlugin = require('./webpack/BundleInfoPlugin.js'); module.exports = merge(commonConfig, { mode: 'production', @@ -36,7 +37,7 @@ module.exports = merge(commonConfig, { new CompressionWebpackPlugin({ filename: '[path][base].gz', algorithm: 'gzip', - test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/, + test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg+$|\.wasm?.+$/, threshold: 10240, minRatio: 0.8, }), diff --git a/webpack/BundleInfoPlugin.js b/webpack/BundleInfoPlugin.js new file mode 100644 index 000000000..b47c21a35 --- /dev/null +++ b/webpack/BundleInfoPlugin.js @@ -0,0 +1,38 @@ +class BundleInfoPlugin { + constructor(options) { + // you can define options if needed + this.options = options || {}; + } + + apply(compiler) { + compiler.hooks.emit.tapAsync( + 'BundleInfoPlugin', + (compilation, callback) => { + let result = {}; + + for (let filename in compilation.assets) { + let size = compilation.assets[filename].size(); + result[filename] = size; + } + + // Convert the result object to JSON format + let jsonResult = JSON.stringify(result, null, 2); + + // Add the JSON to the compilation's assets for output + compilation.assets['bundle_info.json'] = { + source: function () { + return jsonResult; + }, + size: function () { + return jsonResult.length; + }, + }; + + // Continue with the build process + callback(); + } + ); + } +} + +module.exports = BundleInfoPlugin; diff --git a/yarn.lock b/yarn.lock index 50cf1e47f..f2c4a66af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28359,6 +28359,11 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== +worker-url@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/worker-url/-/worker-url-1.1.0.tgz#607b92f36822061dca8363d9208fea3dec6a0bcb" + integrity sha512-HDLF1ZcIsb9gGGUgYkvOmr4AJVkLLuWCdpJ4/xyETDYCQMuqmp3DvKkj7EGepQXvowaETg32lENI6Dmqq59ywA== + world-calendars@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/world-calendars/-/world-calendars-1.0.3.tgz#b25c5032ba24128ffc41d09faf4a5ec1b9c14335"