diff --git a/lib/client-bundle-plugin.js b/lib/client-bundle-plugin.js index 40fd6b31..06b69615 100644 --- a/lib/client-bundle-plugin.js +++ b/lib/client-bundle-plugin.js @@ -20,7 +20,6 @@ const allSrcPlaceholder = 'CLIENT_BUNDLE_PLUGIN_ALL_SRC'; export function getDependencies(clientOutput, item) { const crawlDependencies = new Set([item.fileName]); - const referencedFiles = new Set(); for (const fileName of crawlDependencies) { const chunk = clientOutput.find((v) => v.fileName === fileName); @@ -28,24 +27,11 @@ export function getDependencies(clientOutput, item) { for (const dep of chunk.imports) { crawlDependencies.add(dep); } - - for (const dep of chunk.referencedFiles) { - referencedFiles.add(dep); - } } // Don't add self as dependency crawlDependencies.delete(item.fileName); - // Merge referencedFiles as regular deps. They need to be in the same Set as - // some JS files might appear in both lists and need to be deduped too. - // - // Didn't do this as part of the main loop since their `chunk` can't have - // nested deps and sometimes might be missing altogether, depending on type. - for (const dep of referencedFiles) { - crawlDependencies.add(dep); - } - return [...crawlDependencies]; } @@ -153,9 +139,9 @@ export default function (inputOptions, outputOptions, resolveFileUrl) { if (property.startsWith(allSrcPlaceholder)) { const allModules = [ clientEntry, - ...dependencies - .map((name) => clientOutput.find((item) => item.fileName === name)) - .filter((item) => item.code), + ...dependencies.map((name) => + clientOutput.find((item) => item.fileName === name), + ), ]; const inlineDefines = [ diff --git a/lib/entry-data-plugin.js b/lib/entry-data-plugin.js index f4bc86c5..5316438e 100644 --- a/lib/entry-data-plugin.js +++ b/lib/entry-data-plugin.js @@ -17,14 +17,10 @@ const prefix = 'entry-data:'; const mainNamePlaceholder = 'ENTRY_DATA_PLUGIN_MAIN_NAME'; const dependenciesPlaceholder = 'ENTRY_DATA_PLUGIN_DEPS'; const placeholderRe = /(ENTRY_DATA_PLUGIN_(?:MAIN_NAME|DEPS))(\d+)/g; - -/** @param {string} fileName */ -export function fileNameToURL(fileName) { - return fileName.replace(/^static\//, '/'); -} +const filenamePrefix = 'static/'; export default function entryDataPlugin() { - /** @type {number} */ + /** @type {string} */ let exportCounter; /** @type {Map} */ let counterToIdMap; @@ -73,11 +69,15 @@ export default function entryDataPlugin() { if (!chunk) throw Error(`Cannot find ${id}`); if (placeholder === mainNamePlaceholder) { - return JSON.stringify(fileNameToURL(chunk.fileName)); + return JSON.stringify( + chunk.fileName.slice(filenamePrefix.length), + ); } return JSON.stringify( - getDependencies(chunks, chunk).map((filename) => fileNameToURL(filename)), + getDependencies(chunks, chunk).map((item) => + item.slice(filenamePrefix.length), + ), ); }, ); diff --git a/missing-types.d.ts b/missing-types.d.ts index 2adaaa15..0444a321 100644 --- a/missing-types.d.ts +++ b/missing-types.d.ts @@ -44,11 +44,6 @@ declare module 'data-url:*' { export default url; } -declare module 'service-worker:*' { - const url: string; - export default url; -} - declare var ga: { (...args: any[]): void; q: any[]; diff --git a/package-lock.json b/package-lock.json index 1729b2ff..fca4c250 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8976,9 +8976,9 @@ } }, "@surma/rollup-plugin-off-main-thread": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.2.tgz", - "integrity": "sha512-dOD6nGZ79RmWKDRQuC7SOGXMvDkkLwBogu+epfVFMKiy2kOUtLZkb8wV/ettuMt37YJAJKYCKUmxSbZL2LkUQg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.1.tgz", + "integrity": "sha512-7OU8wfyv18YPWVmecg2/0Jh+pm3lQbvPhIWHd1YQpoxPKPW/vsDNGBaCnMKsZbz29RjgCoXKugAjyagPncgdEw==", "dev": true, "requires": { "ejs": "^3.1.6", @@ -15980,9 +15980,9 @@ "dev": true }, "wasm-feature-detect": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.2.11.tgz", - "integrity": "sha512-HUqwaodrQGaZgz1lZaNioIkog9tkeEJjrM3eq4aUL04whXOVDRc/o2EGb/8kV0QX411iAYWEqq7fMBmJ6dKS6w==" + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.2.9.tgz", + "integrity": "sha512-2E9/gtLVLpv2wnZDyYv8WY2dR9gHbmyv5uhZsnOcMSzqc78aGZpKQORPNcnrPwAU23nFUo7GAwKuoTAWRgsJ7Q==" }, "which": { "version": "2.0.2", diff --git a/package.json b/package.json index fbc99ee4..241dfda6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-node-resolve": "^11.1.0", "@rollup/plugin-replace": "^2.3.4", - "@surma/rollup-plugin-off-main-thread": "^2.2.2", + "@surma/rollup-plugin-off-main-thread": "^2.2.1", "@types/dedent": "^0.7.0", "@types/mime-types": "^2.1.0", "@types/node": "^14.14.7", @@ -58,6 +58,6 @@ "*.rs": "rustfmt" }, "dependencies": { - "wasm-feature-detect": "^1.2.11" + "wasm-feature-detect": "^1.2.9" } } diff --git a/rollup.config.js b/rollup.config.js index 394b4277..8fc5a13e 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -18,7 +18,6 @@ import commonjs from '@rollup/plugin-commonjs'; import { terser } from 'rollup-plugin-terser'; import OMT from '@surma/rollup-plugin-off-main-thread'; import replace from '@rollup/plugin-replace'; -import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets'; import simpleTS from './lib/simple-ts'; import clientBundlePlugin from './lib/client-bundle-plugin'; @@ -32,11 +31,11 @@ import featurePlugin from './lib/feature-plugin'; import initialCssPlugin from './lib/initial-css-plugin'; import serviceWorkerPlugin from './lib/sw-plugin'; import dataURLPlugin from './lib/data-url-plugin'; -import entryDataPlugin, { fileNameToURL } from './lib/entry-data-plugin'; import dedent from 'dedent'; +import entryDataPlugin from './lib/entry-data-plugin'; function resolveFileUrl({ fileName }) { - return JSON.stringify(fileNameToURL(fileName)); + return JSON.stringify(fileName.replace(/^static\//, '/')); } function resolveImportMetaUrlInStaticBuild(property, { moduleId }) { @@ -71,7 +70,7 @@ export default async function ({ watch }) { await del('.tmp/build'); - const isProduction = !watch; + const isProduction = !watch && !process.env.DEBUG; const tsPluginInstance = simpleTS('.', { watch, @@ -119,7 +118,6 @@ export default async function ({ watch }) { plugins: [ { resolveFileUrl }, OMT({ loader: await omtLoaderPromise }), - importMetaAssets(), serviceWorkerPlugin({ output: 'static/serviceworker.js', }), diff --git a/src/client/missing-types.d.ts b/src/client/missing-types.d.ts index bad86b28..d25cdf43 100644 --- a/src/client/missing-types.d.ts +++ b/src/client/missing-types.d.ts @@ -19,4 +19,9 @@ interface Navigator { declare module 'add-css:*' {} +declare module 'service-worker:*' { + const url: string; + export default url; +} + declare module 'preact/debug' {} diff --git a/src/features/decoders/avif/worker/avifDecode.ts b/src/features/decoders/avif/worker/avifDecode.ts index 5e70be21..acb6a252 100644 --- a/src/features/decoders/avif/worker/avifDecode.ts +++ b/src/features/decoders/avif/worker/avifDecode.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import type { AVIFModule } from 'codecs/avif/dec/avif_dec'; +import wasmUrl from 'url:codecs/avif/dec/avif_dec.wasm'; import { initEmscriptenModule, blobToArrayBuffer } from 'features/worker-utils'; let emscriptenModule: Promise; @@ -18,7 +19,7 @@ let emscriptenModule: Promise; export default async function decode(blob: Blob): Promise { if (!emscriptenModule) { const decoder = await import('codecs/avif/dec/avif_dec'); - emscriptenModule = initEmscriptenModule(decoder.default); + emscriptenModule = initEmscriptenModule(decoder.default, wasmUrl); } const [module, data] = await Promise.all([ diff --git a/src/features/decoders/jxl/worker/jxlDecode.ts b/src/features/decoders/jxl/worker/jxlDecode.ts index 6a8f96e7..1df498b9 100644 --- a/src/features/decoders/jxl/worker/jxlDecode.ts +++ b/src/features/decoders/jxl/worker/jxlDecode.ts @@ -11,13 +11,14 @@ * limitations under the License. */ import jxlDecoder, { JXLModule } from 'codecs/jxl/dec/jxl_dec'; +import wasmUrl from 'url:codecs/jxl/dec/jxl_dec.wasm'; import { initEmscriptenModule, blobToArrayBuffer } from 'features/worker-utils'; let emscriptenModule: Promise; export default async function decode(blob: Blob): Promise { if (!emscriptenModule) { - emscriptenModule = initEmscriptenModule(jxlDecoder); + emscriptenModule = initEmscriptenModule(jxlDecoder, wasmUrl); } const [module, data] = await Promise.all([ diff --git a/src/features/decoders/webp/worker/webpDecode.ts b/src/features/decoders/webp/worker/webpDecode.ts index 29bd4e43..3026be51 100644 --- a/src/features/decoders/webp/worker/webpDecode.ts +++ b/src/features/decoders/webp/worker/webpDecode.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import type { WebPModule } from 'codecs/webp/dec/webp_dec'; +import wasmUrl from 'url:codecs/webp/dec/webp_dec.wasm'; import { initEmscriptenModule, blobToArrayBuffer } from 'features/worker-utils'; let emscriptenModule: Promise; @@ -18,7 +19,7 @@ let emscriptenModule: Promise; export default async function decode(blob: Blob): Promise { if (!emscriptenModule) { const decoder = await import('codecs/webp/dec/webp_dec'); - emscriptenModule = initEmscriptenModule(decoder.default); + emscriptenModule = initEmscriptenModule(decoder.default, wasmUrl); } const [module, data] = await Promise.all([ diff --git a/src/features/decoders/wp2/worker/wp2Decode.ts b/src/features/decoders/wp2/worker/wp2Decode.ts index 7a37f449..a8ed56b2 100644 --- a/src/features/decoders/wp2/worker/wp2Decode.ts +++ b/src/features/decoders/wp2/worker/wp2Decode.ts @@ -11,13 +11,14 @@ * limitations under the License. */ import wp2Decoder, { WP2Module } from 'codecs/wp2/dec/wp2_dec'; +import wasmUrl from 'url:codecs/wp2/dec/wp2_dec.wasm'; import { initEmscriptenModule, blobToArrayBuffer } from 'features/worker-utils'; let emscriptenModule: Promise; export default async function decode(blob: Blob): Promise { if (!emscriptenModule) { - emscriptenModule = initEmscriptenModule(wp2Decoder); + emscriptenModule = initEmscriptenModule(wp2Decoder, wasmUrl); } const [module, data] = await Promise.all([ diff --git a/src/features/encoders/avif/worker/avifEncode.ts b/src/features/encoders/avif/worker/avifEncode.ts index 94f828b7..c5103c2b 100644 --- a/src/features/encoders/avif/worker/avifEncode.ts +++ b/src/features/encoders/avif/worker/avifEncode.ts @@ -12,6 +12,9 @@ */ import type { AVIFModule } from 'codecs/avif/enc/avif_enc'; import type { EncodeOptions } from '../shared/meta'; +import wasmUrlWithoutMT from 'url:codecs/avif/enc/avif_enc.wasm'; +import wasmUrlWithMT from 'url:codecs/avif/enc/avif_enc_mt.wasm'; +import workerUrl from 'omt:codecs/avif/enc/avif_enc_mt.worker.js'; import { initEmscriptenModule } from 'features/worker-utils'; import { threads } from 'wasm-feature-detect'; @@ -20,10 +23,14 @@ let emscriptenModule: Promise; async function init() { if (await threads()) { const avifEncoder = await import('codecs/avif/enc/avif_enc_mt'); - return initEmscriptenModule(avifEncoder.default); + return initEmscriptenModule( + avifEncoder.default, + wasmUrlWithMT, + workerUrl, + ); } const avifEncoder = await import('codecs/avif/enc/avif_enc.js'); - return initEmscriptenModule(avifEncoder.default); + return initEmscriptenModule(avifEncoder.default, wasmUrlWithoutMT); } export default async function encode( diff --git a/src/features/encoders/jxl/worker/jxlEncode.ts b/src/features/encoders/jxl/worker/jxlEncode.ts index 02a0f19c..0378c2a7 100644 --- a/src/features/encoders/jxl/worker/jxlEncode.ts +++ b/src/features/encoders/jxl/worker/jxlEncode.ts @@ -16,19 +16,31 @@ import type { EncodeOptions } from '../shared/meta'; import { initEmscriptenModule } from 'features/worker-utils'; import { threads, simd } from 'wasm-feature-detect'; +import wasmUrl from 'url:codecs/jxl/enc/jxl_enc.wasm'; + +import wasmUrlWithMT from 'url:codecs/jxl/enc/jxl_enc_mt.wasm'; +import workerUrl from 'omt:codecs/jxl/enc/jxl_enc_mt.worker.js'; + +import wasmUrlWithMTAndSIMD from 'url:codecs/jxl/enc/jxl_enc_mt_simd.wasm'; +import workerUrlWithSIMD from 'omt:codecs/jxl/enc/jxl_enc_mt_simd.worker.js'; + let emscriptenModule: Promise; async function init() { if (await threads()) { if (await simd()) { const jxlEncoder = await import('codecs/jxl/enc/jxl_enc_mt_simd'); - return initEmscriptenModule(jxlEncoder.default); + return initEmscriptenModule( + jxlEncoder.default, + wasmUrlWithMTAndSIMD, + workerUrlWithSIMD, + ); } const jxlEncoder = await import('codecs/jxl/enc/jxl_enc_mt'); - return initEmscriptenModule(jxlEncoder.default); + return initEmscriptenModule(jxlEncoder.default, wasmUrlWithMT, workerUrl); } const jxlEncoder = await import('codecs/jxl/enc/jxl_enc'); - return initEmscriptenModule(jxlEncoder.default); + return initEmscriptenModule(jxlEncoder.default, wasmUrl); } export default async function encode( diff --git a/src/features/encoders/mozJPEG/worker/mozjpegEncode.ts b/src/features/encoders/mozJPEG/worker/mozjpegEncode.ts index 949999a9..4cc8b699 100644 --- a/src/features/encoders/mozJPEG/worker/mozjpegEncode.ts +++ b/src/features/encoders/mozJPEG/worker/mozjpegEncode.ts @@ -12,6 +12,7 @@ */ import mozjpeg_enc, { MozJPEGModule } from 'codecs/mozjpeg/enc/mozjpeg_enc'; import { EncodeOptions } from '../shared/meta'; +import wasmUrl from 'url:codecs/mozjpeg/enc/mozjpeg_enc.wasm'; import { initEmscriptenModule } from 'features/worker-utils'; let emscriptenModule: Promise; @@ -21,7 +22,7 @@ export default async function encode( options: EncodeOptions, ): Promise { if (!emscriptenModule) { - emscriptenModule = initEmscriptenModule(mozjpeg_enc); + emscriptenModule = initEmscriptenModule(mozjpeg_enc, wasmUrl); } const module = await emscriptenModule; diff --git a/src/features/encoders/oxiPNG/worker/oxipngEncode.ts b/src/features/encoders/oxiPNG/worker/oxipngEncode.ts index c71525ea..558f5498 100644 --- a/src/features/encoders/oxiPNG/worker/oxipngEncode.ts +++ b/src/features/encoders/oxiPNG/worker/oxipngEncode.ts @@ -10,27 +10,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import initOxiWasmST, { + optimise as optimiseST, +} from 'codecs/oxipng/pkg/squoosh_oxipng'; +import initOxiWasmMT, { + initThreadPool, + optimise as optimiseMT, +} from 'codecs/oxipng/pkg-parallel/squoosh_oxipng'; +import oxiWasmUrlST from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm'; +import oxiWasmUrlMT from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm'; import { EncodeOptions } from '../shared/meta'; import { threads } from 'wasm-feature-detect'; async function initMT() { - const { default: init, initThreadPool, optimise } = await import( - 'codecs/oxipng/pkg-parallel/squoosh_oxipng' - ); - await init(); + await initOxiWasmMT(oxiWasmUrlMT); await initThreadPool(navigator.hardwareConcurrency); - return optimise; + return optimiseMT; } async function initST() { - const { default: init, optimise } = await import( - 'codecs/oxipng/pkg/squoosh_oxipng' - ); - await init(); - return optimise; + await initOxiWasmST(oxiWasmUrlST); + return optimiseST; } -let wasmReady: ReturnType; +let wasmReady: Promise; export default async function encode( data: ArrayBuffer, diff --git a/src/features/encoders/webP/worker/webpEncode.ts b/src/features/encoders/webP/worker/webpEncode.ts index 14d6f755..035c166d 100644 --- a/src/features/encoders/webP/worker/webpEncode.ts +++ b/src/features/encoders/webP/worker/webpEncode.ts @@ -16,15 +16,18 @@ import type { EncodeOptions } from '../shared/meta'; import { initEmscriptenModule } from 'features/worker-utils'; import { simd } from 'wasm-feature-detect'; +import wasmUrl from 'url:codecs/webp/enc/webp_enc.wasm'; +import wasmUrlWithSIMD from 'url:codecs/webp/enc/webp_enc_simd.wasm'; + let emscriptenModule: Promise; async function init() { if (await simd()) { const webpEncoder = await import('codecs/webp/enc/webp_enc_simd'); - return initEmscriptenModule(webpEncoder.default); + return initEmscriptenModule(webpEncoder.default, wasmUrlWithSIMD); } const webpEncoder = await import('codecs/webp/enc/webp_enc'); - return initEmscriptenModule(webpEncoder.default); + return initEmscriptenModule(webpEncoder.default, wasmUrl); } export default async function encode( diff --git a/src/features/encoders/wp2/worker/wp2Encode.ts b/src/features/encoders/wp2/worker/wp2Encode.ts index f6d9c0fd..1c12573b 100644 --- a/src/features/encoders/wp2/worker/wp2Encode.ts +++ b/src/features/encoders/wp2/worker/wp2Encode.ts @@ -16,19 +16,31 @@ import type { EncodeOptions } from '../shared/meta'; import { initEmscriptenModule } from 'features/worker-utils'; import { threads, simd } from 'wasm-feature-detect'; +import wasmUrl from 'url:codecs/wp2/enc/wp2_enc.wasm'; + +import wasmUrlWithMT from 'url:codecs/wp2/enc/wp2_enc_mt.wasm'; +import workerUrl from 'omt:codecs/wp2/enc/wp2_enc_mt.worker.js'; + +import wasmUrlWithMTAndSIMD from 'url:codecs/wp2/enc/wp2_enc_mt_simd.wasm'; +import workerUrlWithSIMD from 'omt:codecs/wp2/enc/wp2_enc_mt_simd.worker.js'; + let emscriptenModule: Promise; async function init() { if (await threads()) { if (await simd()) { const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt_simd'); - return initEmscriptenModule(wp2Encoder.default); + return initEmscriptenModule( + wp2Encoder.default, + wasmUrlWithMTAndSIMD, + workerUrlWithSIMD, + ); } const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt'); - return initEmscriptenModule(wp2Encoder.default); + return initEmscriptenModule(wp2Encoder.default, wasmUrlWithMT, workerUrl); } const wp2Encoder = await import('codecs/wp2/enc/wp2_enc'); - return initEmscriptenModule(wp2Encoder.default); + return initEmscriptenModule(wp2Encoder.default, wasmUrl); } export default async function encode( diff --git a/src/features/processors/quantize/worker/quantize.ts b/src/features/processors/quantize/worker/quantize.ts index 009e360e..c62c02ee 100644 --- a/src/features/processors/quantize/worker/quantize.ts +++ b/src/features/processors/quantize/worker/quantize.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import imagequant, { QuantizerModule } from 'codecs/imagequant/imagequant'; +import wasmUrl from 'url:codecs/imagequant/imagequant.wasm'; import { initEmscriptenModule } from 'features/worker-utils'; import { Options } from '../shared/meta'; @@ -21,7 +22,7 @@ export default async function process( opts: Options, ): Promise { if (!emscriptenModule) { - emscriptenModule = initEmscriptenModule(imagequant); + emscriptenModule = initEmscriptenModule(imagequant, wasmUrl); } const module = await emscriptenModule; diff --git a/src/features/processors/resize/worker/resize.ts b/src/features/processors/resize/worker/resize.ts index dc6c8338..72fc8ab8 100644 --- a/src/features/processors/resize/worker/resize.ts +++ b/src/features/processors/resize/worker/resize.ts @@ -1,6 +1,8 @@ import type { WorkerResizeOptions } from '../shared/meta'; import { getContainOffsets } from '../shared/util'; import initResizeWasm, { resize as wasmResize } from 'codecs/resize/pkg'; +import resizeWasmUrl from 'url:codecs/resize/pkg/squoosh_resize_bg.wasm'; +import hqxWasmUrl from 'url:codecs/hqx/pkg/squooshhqx_bg.wasm'; import initHqxWasm, { resize as wasmHqx } from 'codecs/hqx/pkg'; interface HqxResizeOptions extends WorkerResizeOptions { @@ -61,7 +63,7 @@ async function hqx( opts: HqxResizeOptions, ): Promise { if (!hqxWasmReady) { - hqxWasmReady = initHqxWasm(); + hqxWasmReady = initHqxWasm(hqxWasmUrl); } await hqxWasmReady; @@ -94,7 +96,7 @@ export default async function resize( let input = data; if (!resizeWasmReady) { - resizeWasmReady = initResizeWasm(); + resizeWasmReady = initResizeWasm(resizeWasmUrl); } if (optsIsHqxOpts(opts)) { diff --git a/src/features/worker-utils/index.ts b/src/features/worker-utils/index.ts index 72113d95..793758c5 100644 --- a/src/features/worker-utils/index.ts +++ b/src/features/worker-utils/index.ts @@ -10,12 +10,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export function initEmscriptenModule( + +// @ts-ignore +self.asm = ''; // lol +// @ts-ignore +self.UTF32ToString = (...v) => console.log("u322s", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +// @ts-ignore +self.stringToUTF32 = (...v) => console.log("s2u32", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +// @ts-ignore +self.lengthBytesUTF32 = (...v) => console.log("lb32", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +// @ts-ignore +self.UTF16ToString = (...v) => console.log("u162s", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +// @ts-ignore +self.stringToUTF16 = (...v) => console.log("s2u16", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +// @ts-ignore +self.lengthBytesUTF16 = (...v) => console.log("lb16", v); //v => [...new Uint32Array(v)].map(v => String.fromCharCode(v)).join("") +export async function initEmscriptenModule( moduleFactory: EmscriptenWasm.ModuleFactory, + wasmUrl: string, + workerUrl?: string, ): Promise { return moduleFactory({ + // @ts-ignore + wasm: await fetch(wasmUrl).then(r => r.arrayBuffer()), // Just to be safe, don't automatically invoke any wasm functions noInitialRun: true, + locateFile: (url: string) => { + // This is probably unused? + console.log("CALL TO LOCATEFILE", url); + if (url.endsWith('.wasm')) return wasmUrl; + if (url.endsWith('.worker.js')) return workerUrl!; + throw Error('Unknown url in locateFile ' + url); + }, }); } diff --git a/src/sw/index.ts b/src/sw/index.ts index 266f2c55..66ca403a 100644 --- a/src/sw/index.ts +++ b/src/sw/index.ts @@ -7,7 +7,6 @@ import { serveShareTarget, } from './util'; import { get } from 'idb-keyval'; -import { shouldCacheDynamically } from './to-cache'; // Give TypeScript the correct global. declare var self: ServiceWorkerGlobalScope; @@ -71,7 +70,7 @@ self.addEventListener('fetch', (event) => { // We only care about GET from here on in. if (event.request.method !== 'GET') return; - if (shouldCacheDynamically(url.pathname)) { + if (url.pathname.startsWith('/c/demo-')) { cacheOrNetworkAndCache(event, dynamicCache); cleanupCache(event, dynamicCache, ASSETS); return; diff --git a/src/sw/to-cache.ts b/src/sw/to-cache.ts index bad10ef0..cbc922f5 100644 --- a/src/sw/to-cache.ts +++ b/src/sw/to-cache.ts @@ -13,46 +13,18 @@ function subtractSets(set1: Set, set2: Set): Set { // Initial app stuff import * as initialApp from 'entry-data:client/initial-app'; -import swUrl from 'service-worker:sw'; import * as compress from 'entry-data:client/lazy-app/Compress'; import * as swBridge from 'entry-data:client/lazy-app/sw-bridge'; import * as blobAnim from 'entry-data:shared/prerendered-app/Intro/blob-anim'; +import logo from 'url:shared/prerendered-app/Intro/imgs/logo.svg'; +import githubLogo from 'url:shared/prerendered-app/Intro/imgs/github-logo.svg'; +import largePhotoIcon from 'url:shared/prerendered-app/Intro/imgs/demos/icon-demo-large-photo.jpg'; +import artworkIcon from 'url:shared/prerendered-app/Intro/imgs/demos/icon-demo-artwork.jpg'; +import deviceScreenIcon from 'url:shared/prerendered-app/Intro/imgs/demos/icon-demo-device-screen.jpg'; +import logoIcon from 'url:shared/prerendered-app/Intro/imgs/demos/icon-demo-logo.png'; +import logoWithText from 'url:shared/prerendered-app/Intro/imgs/logo-with-text.svg'; -// The processors and codecs -// Simple stuff everyone gets: -import * as featuresWorker from 'entry-data:../features-worker'; - -// Decoders (some are feature detected) -import * as avifDec from 'entry-data:codecs/avif/dec/avif_dec'; -import * as webpDec from 'entry-data:codecs/webp/dec/webp_dec'; - -// AVIF -import * as avifEncMt from 'entry-data:codecs/avif/enc/avif_enc_mt'; -import * as avifEnc from 'entry-data:codecs/avif/enc/avif_enc'; - -// JXL -import * as jxlEncMtSimd from 'entry-data:codecs/jxl/enc/jxl_enc_mt_simd'; -import * as jxlEncMt from 'entry-data:codecs/jxl/enc/jxl_enc_mt'; -import * as jxlEnc from 'entry-data:codecs/jxl/enc/jxl_enc'; - -// OXI -import * as oxiMt from 'entry-data:codecs/oxipng/pkg-parallel/squoosh_oxipng'; -import * as oxi from 'entry-data:codecs/oxipng/pkg/squoosh_oxipng'; - -// WebP -import * as webpEncSimd from 'entry-data:codecs/webp/enc/webp_enc_simd'; -import * as webpEnc from 'entry-data:codecs/webp/enc/webp_enc'; - -// WP2 -import * as wp2EncMtSimd from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd'; -import * as wp2EncMt from 'entry-data:codecs/wp2/enc/wp2_enc_mt'; -import * as wp2Enc from 'entry-data:codecs/wp2/enc/wp2_enc'; - -export function shouldCacheDynamically(url: string) { - return url.startsWith('/c/demo-'); -} - -let initialJs = new Set([ +let initalJs = new Set([ compress.main, ...compress.deps, swBridge.main, @@ -60,26 +32,77 @@ let initialJs = new Set([ blobAnim.main, ...blobAnim.deps, ]); -initialJs = subtractSets( - initialJs, - new Set([ - initialApp.main, - ...initialApp.deps.filter( - (item) => - // Exclude JS deps that have been inlined: - item.endsWith('.js') || - // As well as large image deps we want to keep dynamic: - shouldCacheDynamically(item), - ), - // Exclude features Worker itself - it's referenced from the main app, - // but is meant to be cached lazily. - featuresWorker.main, - // Also exclude Service Worker itself (we're inside right now). - swUrl, - ]), +// But initial app and any deps have already been inlined, so we don't need them: +initalJs = subtractSets( + initalJs, + new Set([initialApp.main, ...initialApp.deps]), ); -export const initial = ['/', ...initialJs]; +export const initial = [ + '/', + ...initalJs, + logo, + githubLogo, + largePhotoIcon, + artworkIcon, + deviceScreenIcon, + logoIcon, + logoWithText, +]; + +// The processors and codecs +// Simple stuff everyone gets: +import * as featuresWorker from 'entry-data:../features-worker'; +import rotateWasm from 'url:codecs/rotate/rotate.wasm'; +import quantWasm from 'url:codecs/imagequant/imagequant.wasm'; +import resizeWasm from 'url:codecs/resize/pkg/squoosh_resize_bg.wasm'; +import hqxWasm from 'url:codecs/hqx/pkg/squooshhqx_bg.wasm'; +import mozjpegWasm from 'url:codecs/mozjpeg/enc/mozjpeg_enc.wasm'; + +// Decoders (some are feature detected) +import * as avifDec from 'entry-data:codecs/avif/dec/avif_dec'; +import avifDecWasm from 'url:codecs/avif/dec/avif_dec.wasm'; +import jxlDecWasm from 'url:codecs/jxl/dec/jxl_dec.wasm'; +import * as webpDec from 'entry-data:codecs/webp/dec/webp_dec'; +import webpDecWasm from 'url:codecs/webp/dec/webp_dec.wasm'; +import wp2DecWasm from 'url:codecs/wp2/dec/wp2_dec.wasm'; + +// AVIF +import * as avifEncMtWorker from 'entry-data:codecs/avif/enc/avif_enc_mt.worker.js'; +import * as avifEncMt from 'entry-data:codecs/avif/enc/avif_enc_mt'; +import avifEncMtWasm from 'url:codecs/avif/enc/avif_enc_mt.wasm'; +import avifEncWasm from 'url:codecs/avif/enc/avif_enc.wasm'; +import * as avifEnc from 'entry-data:codecs/avif/enc/avif_enc.js'; + +// JXL +import * as jxlEncMtSimdWorker from 'entry-data:codecs/jxl/enc/jxl_enc_mt_simd.worker.js'; +import * as jxlEncMtSimd from 'entry-data:codecs/jxl/enc/jxl_enc_mt_simd'; +import jxlEncMtSimdWasm from 'url:codecs/jxl/enc/jxl_enc_mt_simd.wasm'; +import * as jxlEncMtWorker from 'entry-data:codecs/jxl/enc/jxl_enc_mt.worker.js'; +import * as jxlEncMt from 'entry-data:codecs/jxl/enc/jxl_enc_mt'; +import jxlEncMtWasm from 'url:codecs/jxl/enc/jxl_enc_mt.wasm'; +import jxlEncWasm from 'url:codecs/jxl/enc/jxl_enc.wasm'; +import * as jxlEnc from 'entry-data:codecs/jxl/enc/jxl_enc'; + +// OXI +import oxiMtWasm from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm'; +import oxiWasm from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm'; + +// WebP +import * as webpEncSimd from 'entry-data:codecs/webp/enc/webp_enc_simd'; +import webpEncSimdWasm from 'url:codecs/webp/enc/webp_enc_simd.wasm'; +import * as webpEnc from 'entry-data:codecs/webp/enc/webp_enc'; +import webpEncWasm from 'url:codecs/webp/enc/webp_enc.wasm'; + +// WP2 +import * as wp2EncMtSimdWorker from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd.worker.js'; +import * as wp2EncMtSimd from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd'; +import wp2EncMtSimdWasm from 'url:codecs/wp2/enc/wp2_enc_mt_simd.wasm'; +import * as wp2EncMtWorker from 'entry-data:codecs/wp2/enc/wp2_enc_mt.worker.js'; +import * as wp2EncMt from 'entry-data:codecs/wp2/enc/wp2_enc_mt'; +import wp2EncMtWasm from 'url:codecs/wp2/enc/wp2_enc_mt.wasm'; +import * as wp2Enc from 'entry-data:codecs/wp2/enc/wp2_enc'; +import wp2EncWasm from 'url:codecs/wp2/enc/wp2_enc.wasm'; export const theRest = (async () => { const [ @@ -101,54 +124,88 @@ export const theRest = (async () => { }), ]); - const items: string[] = []; + const items = [ + featuresWorker.main, + ...featuresWorker.deps, + rotateWasm, + quantWasm, + resizeWasm, + hqxWasm, + mozjpegWasm, + jxlDecWasm, + wp2DecWasm, + ]; - function addWithDeps(entry: typeof import('entry-data:*')) { - items.push(entry.main, ...entry.deps); - } - - addWithDeps(featuresWorker); - - if (!supportsAvif) addWithDeps(avifDec); - if (!supportsWebP) addWithDeps(webpDec); + if (!supportsAvif) items.push(avifDec.main, ...avifDec.deps, avifDecWasm); + if (!supportsWebP) items.push(webpDec.main, ...webpDec.deps, webpDecWasm); // AVIF if (supportsThreads) { - addWithDeps(avifEncMt); + items.push( + avifEncMtWorker.main, + ...avifEncMtWorker.deps, + avifEncMt.main, + ...avifEncMt.deps, + avifEncMtWasm, + ); } else { - addWithDeps(avifEnc); + items.push(avifEnc.main, ...avifEnc.deps, avifEncWasm); } // JXL if (supportsThreads && supportsSimd) { - addWithDeps(jxlEncMtSimd); + items.push( + jxlEncMtSimdWorker.main, + ...jxlEncMtSimdWorker.deps, + jxlEncMtSimd.main, + ...jxlEncMtSimd.deps, + jxlEncMtSimdWasm, + ); } else if (supportsThreads) { - addWithDeps(jxlEncMt); + items.push( + jxlEncMtWorker.main, + ...jxlEncMtWorker.deps, + jxlEncMt.main, + ...jxlEncMt.deps, + jxlEncMtWasm, + ); } else { - addWithDeps(jxlEnc); + items.push(jxlEnc.main, ...jxlEnc.deps, jxlEncWasm); } // OXI if (supportsThreads) { - addWithDeps(oxiMt); + items.push(oxiMtWasm); } else { - addWithDeps(oxi); + items.push(oxiWasm); } // WebP if (supportsSimd) { - addWithDeps(webpEncSimd); + items.push(webpEncSimd.main, ...webpEncSimd.deps, webpEncSimdWasm); } else { - addWithDeps(webpEnc); + items.push(webpEnc.main, ...webpEnc.deps, webpEncWasm); } // WP2 if (supportsThreads && supportsSimd) { - addWithDeps(wp2EncMtSimd); + items.push( + wp2EncMtSimdWorker.main, + ...wp2EncMtSimdWorker.deps, + wp2EncMtSimd.main, + ...wp2EncMtSimd.deps, + wp2EncMtSimdWasm, + ); } else if (supportsThreads) { - addWithDeps(wp2EncMt); + items.push( + wp2EncMtWorker.main, + ...wp2EncMtWorker.deps, + wp2EncMt.main, + ...wp2EncMt.deps, + wp2EncMtWasm, + ); } else { - addWithDeps(wp2Enc); + items.push(wp2Enc.main, ...wp2Enc.deps, wp2EncWasm); } return [...new Set(items)];