Move terser off of the main thread
This commit is contained in:
parent
844164bda9
commit
f23e0417ed
7 changed files with 206 additions and 4 deletions
|
|
@ -19,6 +19,7 @@
|
|||
"@sveltejs/kit": "^2.5.7",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.0",
|
||||
"@types/node": "^20.12.7",
|
||||
"@types/sharedworker": "^0.0.115",
|
||||
"glob": "^10.3.12",
|
||||
"mdsvex": "^0.11.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
|
|
|
|||
48
packages/website/src/lib/workers/terser.ts
Normal file
48
packages/website/src/lib/workers/terser.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import type { MinifyOptions, MinifyOutput } from "terser";
|
||||
import { recieveMessageData, sendMessageData } from "./util";
|
||||
|
||||
export function init() {
|
||||
|
||||
let worker: SharedWorker;
|
||||
let currentId = 0;
|
||||
let terserModule: typeof import("terser");
|
||||
let promises: { [id: number]: [(value: MinifyOutput | PromiseLike<MinifyOutput>) => void, (reason?: any) => void] } = {};
|
||||
return {
|
||||
minify: async function minify(files: string | string[] | {
|
||||
[file: string]: string;
|
||||
}, options?: MinifyOptions): Promise<MinifyOutput> {
|
||||
|
||||
if (!!window.SharedWorker) {
|
||||
if (!worker) {
|
||||
worker = new SharedWorker(new URL('./terserWorker.ts', import.meta.url), { type: "module" })
|
||||
worker.port.onmessage = (e: MessageEvent<any>) => {
|
||||
// invoke the promise's resolve() or reject() depending on whether there was an error.
|
||||
promises[e.data[recieveMessageData.MessageId]][e.data[recieveMessageData.MessageType]](e.data[recieveMessageData.Return]);
|
||||
|
||||
// ... then delete the promise controller
|
||||
delete promises[e.data[recieveMessageData.MessageId]];
|
||||
|
||||
}
|
||||
}
|
||||
worker.port.start()
|
||||
return new Promise((resolve, reject) => {
|
||||
promises[++currentId] = [resolve, reject];
|
||||
|
||||
let data = {
|
||||
[sendMessageData.MessageId]: currentId,
|
||||
[sendMessageData.Parameters]: [files, options
|
||||
]
|
||||
}
|
||||
worker.port.postMessage(data)
|
||||
});
|
||||
|
||||
} else {
|
||||
if (!terserModule) {
|
||||
terserModule = await import("terser")
|
||||
}
|
||||
return await terserModule.minify(files, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
packages/website/src/lib/workers/terserWorker.ts
Normal file
35
packages/website/src/lib/workers/terserWorker.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { minify, type MinifyOptions } from "terser";
|
||||
import { recieveMessageTypes, sendMessageData } from "./util";
|
||||
|
||||
/// <reference lib="sharedworker " />
|
||||
declare var self: SharedWorkerGlobalScope;
|
||||
|
||||
self.onconnect = function (event) {
|
||||
const port = event.ports[0];
|
||||
port.onmessage = function (e: MessageEvent<{
|
||||
[sendMessageData.MessageId]: number,
|
||||
[sendMessageData.Parameters]: [string | string[] | {
|
||||
[file: string]: string;
|
||||
}, MinifyOptions?
|
||||
]
|
||||
}>) {
|
||||
minify(...e.data[sendMessageData.Parameters]).then(
|
||||
// success handler - callback(id, SUCCESS(0), result)
|
||||
// if `d` is transferable transfer zero-copy
|
||||
d => {
|
||||
|
||||
port.postMessage([e.data[0], recieveMessageTypes.RESOLVE, d],
|
||||
// @ts-ignore
|
||||
[d].filter(x => (
|
||||
(x instanceof ArrayBuffer) ||
|
||||
(x instanceof MessagePort)
|
||||
// || (self.ImageBitmap && x instanceof ImageBitmap)
|
||||
)));
|
||||
},
|
||||
// error handler - callback(id, ERROR(1), error)
|
||||
er => { postMessage([e.data[0], recieveMessageTypes.REJECT, '' + er]); }
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
105
packages/website/src/lib/workers/util.ts
Normal file
105
packages/website/src/lib/workers/util.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
export type FunctionMap = { [x: string]: Function }
|
||||
|
||||
export enum sendMessageData {
|
||||
MessageId,
|
||||
Function,
|
||||
Parameters
|
||||
}
|
||||
|
||||
export interface sendMessageMap <T> {
|
||||
[sendMessageData.MessageId]: number,
|
||||
[sendMessageData.Function]: number,
|
||||
[sendMessageData.Parameters]: T[],
|
||||
}
|
||||
|
||||
export enum recieveMessageTypes {
|
||||
RESOLVE, // OK
|
||||
REJECT // ERROR
|
||||
}
|
||||
|
||||
|
||||
export enum recieveMessageData {
|
||||
MessageId,
|
||||
MessageType,
|
||||
Return
|
||||
}
|
||||
|
||||
export interface recieveMessageMap <T> {
|
||||
[recieveMessageData.MessageId]: number,
|
||||
[recieveMessageData.MessageType]: recieveMessageTypes,
|
||||
[recieveMessageData.Return]: T,
|
||||
}
|
||||
|
||||
|
||||
// // worker
|
||||
// import { recieveMessageTypes, type FunctionMap } from "./util";
|
||||
|
||||
// function makeMessageHandler(functions: FunctionMap) {
|
||||
|
||||
// return (e) => {
|
||||
// // Invoking within then() captures exceptions in the supplied async function as rejections
|
||||
// Promise.resolve(e.data[1]).then(
|
||||
// v => $$.apply($$, v)
|
||||
// ).then(
|
||||
// // success handler - callback(id, SUCCESS(0), result)
|
||||
// // if `d` is transferable transfer zero-copy
|
||||
// d => {
|
||||
// postMessage([e.data[0], recieveMessageTypes.SUCCESS, d], [d].filter(x => (
|
||||
// (x instanceof ArrayBuffer) ||
|
||||
// (x instanceof MessagePort) ||
|
||||
// (self.ImageBitmap && x instanceof ImageBitmap)
|
||||
// )));
|
||||
// },
|
||||
// // error handler - callback(id, ERROR(1), error)
|
||||
// er => { postMessage([e.data[0], recieveMessageTypes.ERROR, '' + er]); }
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// // host
|
||||
// import { recieveMessageData, recieveMessageTypes, sendMessageData, type recieveMessageMap, type sendMessageMap } from "./util";
|
||||
|
||||
// function makeHostHandler(worker: Worker) {
|
||||
|
||||
// let currentId = 0;
|
||||
|
||||
// // Outward-facing promises store their "controllers" (`[request, reject]`) here:
|
||||
// const promises: { [id: number]: { [t: number]: IArguments } } = {}
|
||||
// ;
|
||||
// /** Handle RPC results/errors coming back out of the worker.
|
||||
// * Messages coming from the worker take the form `[id, status, result]`:
|
||||
// * id - counter-based unique ID for the RPC call
|
||||
// * status - 0 for success, 1 for failure
|
||||
// * result - the result or error, depending on `status`
|
||||
// */
|
||||
// worker.onmessage = (e: MessageEvent<recieveMessageMap>) => {
|
||||
// // invoke the promise's resolve() or reject() depending on whether there was an error.
|
||||
// promises[e.data[0]][e.data[1]](e.data[2]);
|
||||
|
||||
// // ... then delete the promise controller
|
||||
// promises[e.data[0]] = null;
|
||||
// };
|
||||
|
||||
// // Return a proxy function that forwards calls to the worker & returns a promise for the result.
|
||||
// return function () {
|
||||
// let args = [].slice.call(arguments);
|
||||
// return new Promise(function () {
|
||||
// // Add the promise controller to the registry
|
||||
// promises[++currentId] = arguments;
|
||||
|
||||
// // Send an RPC call to the worker - call(id, params)
|
||||
// // The filter is to provide a list of transferables to send zero-copy
|
||||
// let data: sendMessageMap<any> = {
|
||||
// [sendMessageData.MessageId]: currentId,
|
||||
// [sendMessageData.Function]: 1,
|
||||
// [sendMessageData.Parameters]: args
|
||||
// }
|
||||
// worker.postMessage(data, args.filter(x => (
|
||||
// (x instanceof ArrayBuffer) ||
|
||||
// (x instanceof MessagePort) ||
|
||||
// (self.ImageBitmap && x instanceof ImageBitmap)
|
||||
// )));
|
||||
// });
|
||||
// };
|
||||
|
||||
// }
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
import SvelteSeo from "svelte-seo";
|
||||
import { bookmarkify, parseMeta } from "./bookmarklets";
|
||||
import type { Config } from "./config";
|
||||
|
||||
import { init } from "$lib/workers/terser";
|
||||
import { SITE_URL } from '$lib/metadata';
|
||||
|
||||
/** @type {import('./$types').Snapshot<string>} */
|
||||
|
|
@ -12,12 +12,14 @@
|
|||
restore: (v: string) => (value = v),
|
||||
};
|
||||
|
||||
let minify = init().minify
|
||||
|
||||
let value = "";
|
||||
let output = "";
|
||||
let options: Config = {};
|
||||
async function process(str: string) {
|
||||
options = await parseMeta(str);
|
||||
let res = await bookmarkify(str, options);
|
||||
let res = await bookmarkify(str, options, minify);
|
||||
if (typeof res == "string") {
|
||||
output = res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@
|
|||
|
||||
import MagicString from "magic-string";
|
||||
import { Parser } from "acorn";
|
||||
import { minify } from "terser";
|
||||
import { type MinifyOptions, type MinifyOutput } from "terser";
|
||||
|
||||
let sourceMap = false;
|
||||
|
||||
import { configSchema } from "./config.schema";
|
||||
import type { Config } from "./config";
|
||||
// console.log(configSchema)
|
||||
export async function bookmarkify(code: string, options: Config) {
|
||||
export async function bookmarkify(code: string, options: Config, minify: (files: string | string[] | {
|
||||
[file: string]: string;
|
||||
}, options?: MinifyOptions | undefined) => Promise<MinifyOutput>
|
||||
) {
|
||||
|
||||
// try {
|
||||
if (options.script) {
|
||||
|
|
|
|||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
|
@ -101,6 +101,9 @@ importers:
|
|||
'@types/node':
|
||||
specifier: ^20.12.7
|
||||
version: 20.12.7
|
||||
'@types/sharedworker':
|
||||
specifier: ^0.0.115
|
||||
version: 0.0.115
|
||||
glob:
|
||||
specifier: ^10.3.12
|
||||
version: 10.3.12
|
||||
|
|
@ -872,6 +875,9 @@ packages:
|
|||
'@types/resolve@1.20.2':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@types/sharedworker@0.0.115':
|
||||
resolution: {integrity: sha512-istxrCv9mbZQt7kXMVMsc4U+dbxG5y+ae5N+9f6pM9VOJmclF7FBWtTog9SMT16s1pZUTjga7ewaMVgqhDpTOg==}
|
||||
|
||||
'@types/unist@2.0.10':
|
||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||
|
||||
|
|
@ -2841,6 +2847,8 @@ snapshots:
|
|||
|
||||
'@types/resolve@1.20.2': {}
|
||||
|
||||
'@types/sharedworker@0.0.115': {}
|
||||
|
||||
'@types/unist@2.0.10': {}
|
||||
|
||||
'@types/unist@3.0.2': {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue