Skip to content

Instantly share code, notes, and snippets.

@deepak1556
Created March 21, 2025 16:46
Show Gist options
  • Save deepak1556/81e2cd4dd2c3f1b2c23f9c721671f67a to your computer and use it in GitHub Desktop.
Save deepak1556/81e2cd4dd2c3f1b2c23f9c721671f67a to your computer and use it in GitHub Desktop.
service worker and worker clients with chromium plzdedicatedworker
console.log('worker sub resource');
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<!-- You can also require other files to run in this process -->
<script src="renderer.js"></script>
</body>
</html>
// Modules to control application life and create native browser window
const { app, BrowserWindow, protocol } = require('electron')
const path = require('node:path')
protocol.registerSchemesAsPrivileged([
{
scheme: 'app',
privileges: {
standard: true,
secure: true,
allowServiceWorkers: true,
supportFetchAPI: true
}
}
])
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
sandbox: true
}
})
mainWindow.webContents.session.protocol.registerFileProtocol('app', (request, cb) => {
const resource = request.url.slice('app://host/'.length)
cb({ path: path.join(__dirname, resource)});
})
// and load the index.html of the app.
mainWindow.loadURL('app://host/index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
var registration;
navigator.serviceWorker.register('sw.js')
.catch(function() {
console.error('register should not fail');
})
navigator.serviceWorker.addEventListener('controllerchange', () => {
console.log('Starting window fetch..')
fetch('clientId')
.then(function(response) {
return response.text();
})
.then(function(text) {
console.log(`Fetch from window ${text}`);
console.log('Starting dedicated worker...');
var w = new Worker('worker.js');
w.postMessage({cmd:'GetClientId'});
return new Promise((resolve) => {
w.onmessage = e => resolve(e.data);
});
})
.then(function(data) {
console.log(`Fetch from worker ${data.result}`);
console.log('Starting dedicated blob worker...');
const fetchURL = new URL('clientId', window.location).href;
const workerScript =
`self.onmessage = async (e) => {
if (e.data.cmd == 'GetClientId') {
const response = await fetch(e.data.url);
const text = await response.text();
self.postMessage({"result": text});
}
};`;
const blob = new Blob([workerScript], { type: 'text/javascript' });
const blobUrl = URL.createObjectURL(blob);
var w = new Worker(blobUrl);
w.postMessage({cmd:'GetClientId', url: fetchURL});
return new Promise((resolve) => {
w.onmessage = e => resolve(e.data);
});
})
.then(function(data) {
console.log(`Fetch from blob worker ${data.result}`);
});
});
self.onfetch = async function(e) {
console.log(`Fetch clientID: ${e.clientId} for url : ${e.request.url}`);
if (/\/clientId$/.test(e.request.url)) {
return e.respondWith(processRequest(e));
}
};
async function processRequest(e) {
const client = await self.clients.get(e.clientId);
if (!client) {
const workerClients = await self.clients.matchAll({type: 'worker'});
const filteredClients = workerClients.filter(workerClient => {
return workerClient.id === e.clientId;
});
if (filteredClients.length != 1) {
return new Response('Not Found', { status: 404, });
}
return new Response(`Found blob worker client : ${filteredClients[0].url}`, { status: 200, });
}
return new Response('Found', { status: 200, });
}
self.oninstall = function(e) {
e.waitUntil(self.skipWaiting()); // Activate worker immediately
};
self.onactivate = function(e) {
e.waitUntil(self.clients.claim()); // Become available to all pages
};
importScripts('child.js');
onmessage = function(e) {
if (e.data.cmd == 'GetClientId') {
fetch('clientId')
.then(function(response) {
return response.text();
})
.then(function(text) {
self.postMessage({"result": text});
});
}
};
@deepak1556
Copy link
Author

With the feature enabled

[41401:0322/014424.417761:INFO:CONSOLE(8)] "Starting window fetch..", source: app://host/renderer.js (8)
[41401:0322/014424.418114:INFO:CONSOLE(2)] "Fetch clientID: e6f66aff-6dc4-4464-a1de-59abfdc79901 for url : app://host/clientId", source: app://host/sw.js (2)
[41401:0322/014424.418815:INFO:CONSOLE(14)] "Fetch from window Found", source: app://host/renderer.js (14)
[41401:0322/014424.418835:INFO:CONSOLE(15)] "Starting dedicated worker...", source: app://host/renderer.js (15)
[41401:0322/014424.419286:INFO:CONSOLE(2)] "Fetch clientID: e6f66aff-6dc4-4464-a1de-59abfdc79901 for url : app://host/worker.js", source: app://host/sw.js (2)
[41401:0322/014424.422433:INFO:CONSOLE(2)] "Fetch clientID: 859be7c0-8890-4603-bc43-d571ea5adb00 for url : app://host/child.js", source: app://host/sw.js (2)
[41401:0322/014424.423320:INFO:CONSOLE(1)] "worker sub resource", source: app://host/child.js (1)
[41401:0322/014424.423589:INFO:CONSOLE(2)] "Fetch clientID: 859be7c0-8890-4603-bc43-d571ea5adb00 for url : app://host/clientId", source: app://host/sw.js (2)
[41401:0322/014424.424296:INFO:CONSOLE(23)] "Fetch from worker Found", source: app://host/renderer.js (23)
[41401:0322/014424.424314:INFO:CONSOLE(24)] "Starting dedicated blob worker...", source: app://host/renderer.js (24)
[41401:0322/014424.428384:INFO:CONSOLE(2)] "Fetch clientID: 3117866b-479d-465e-a291-dcc26d4fe6f0 for url : app://host/clientId", source: app://host/sw.js (2)
[41401:0322/014424.429133:INFO:CONSOLE(43)] "Fetch from blob worker Found blob worker client : blob:app://host/fa8bb2ce-fca0-41e1-bb64-9970e811d3d8", source: app://host/renderer.js (43)

@deepak1556
Copy link
Author

With feature disabled

[42081:0322/015043.813315:INFO:CONSOLE(2)] "Fetch clientID: 12fafb25-871d-4799-a744-5a104e6645e6 for url : app://host/clientId", source: app://host/sw.js (2)
[42081:0322/015043.816422:INFO:CONSOLE(14)] "Fetch from window Found", source: app://host/renderer.js (14)
[42081:0322/015043.816446:INFO:CONSOLE(15)] "Starting dedicated worker...", source: app://host/renderer.js (15)
[42081:0322/015043.817050:INFO:CONSOLE(2)] "Fetch clientID: 12fafb25-871d-4799-a744-5a104e6645e6 for url : app://host/worker.js", source: app://host/sw.js (2)
[42081:0322/015043.820273:INFO:CONSOLE(2)] "Fetch clientID: 12fafb25-871d-4799-a744-5a104e6645e6 for url : app://host/child.js", source: app://host/sw.js (2)
[42081:0322/015043.821257:INFO:CONSOLE(1)] "worker sub resource", source: app://host/child.js (1)
[42081:0322/015043.821609:INFO:CONSOLE(2)] "Fetch clientID: 12fafb25-871d-4799-a744-5a104e6645e6 for url : app://host/clientId", source: app://host/sw.js (2)
[42081:0322/015043.822254:INFO:CONSOLE(23)] "Fetch from worker Found", source: app://host/renderer.js (23)
[42081:0322/015043.822269:INFO:CONSOLE(24)] "Starting dedicated blob worker...", source: app://host/renderer.js (24)
[42081:0322/015043.825886:INFO:CONSOLE(2)] "Fetch clientID: 12fafb25-871d-4799-a744-5a104e6645e6 for url : app://host/clientId", source: app://host/sw.js (2)
[42081:0322/015043.826976:INFO:CONSOLE(43)] "Fetch from blob worker Found", source: app://host/renderer.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment