Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pref(wasm): deduplicate web-worker code in browser.js #3056

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

privatenumber
Copy link
Contributor

Problem

In the WASM distribution, a pretty large Web Worker function was being duplicated and creating bloat.

Changes

Reuse Web Worker code by leveraging toString().

File Size before Size after
lib/browser.js 122 KB 95 KB
lib/browser.min.js 50 KB 40KB
esm/browser.js 118 KB 93 KB
esm/browser.min.js 48 KB 39 KB

@privatenumber privatenumber changed the title pref(wasm): deduplicated web-worker code in browser.js pref(wasm): deduplicate web-worker code in browser.js Apr 13, 2023
@evanw
Copy link
Owner

evanw commented Apr 14, 2023

This used to be how esbuild works. However, it was deliberately changed because esbuild (and likely some other tools too) don't fully support code that uses Function.prototype.toString.

I recommend not using esbuild if you're worried about this level of bloat. This PR saves ~10 kb but the WebAssembly binary for esbuild is currently more than 10,000 kb, so this PR only reduces the size by about 0.1%.

@privatenumber
Copy link
Contributor Author

This used to be how esbuild works. However, it was deliberately changed because esbuild (and likely some other tools too) don't fully support code that uses Function.prototype.toString.

Ah right. I wonder if it could be the other way around then? Keep it as a string, and run it through eval or new Function for the main thread version.

I recommend not using esbuild if you're worried about this level of bloat. This PR saves ~10 kb but the WebAssembly binary for esbuild is currently more than 10,000 kb, so this PR only reduces the size by about 0.1%.

It's true the total size savings are trivial. But in my usage, I'm bundling the JS part in the same chunk as my entry-point, and the WASM binary is loaded separately. So the reduction in the JS files had some notable impact.

@evanw
Copy link
Owner

evanw commented Apr 15, 2023

That also used to be how esbuild works (using new Function to construct the worker function). However, that prevented people from using esbuild in environments where dynamic JavaScript evaluation is forbidden, such as Cloudflare Workers or Deno Deploy: #2081. So esbuild was changed to work the way it does now to enable these use cases.

@privatenumber
Copy link
Contributor Author

Gotcha, sorry to make you revisit this problem. I underestimated how complex this is. I appreciate your patience in explaining this to me.

You may have already thought of this too, but what do you think of separating out the Web Worker/worker_threads versions into another file/entry-point?

"exports": {
	".": {
		"node": {
			"worker": "./lib/node/worker_threads.js",
			"default": "./lib/node/main.js"
		},
		"default": {
			"worker": "./lib/browser/web-worker.js",
			"default": "./lib/browser/main.js"
		}
	},
	"./main": {
		"node": "./lib/node/main.js"
		"default": "./lib/browser/main.js"
	},
	"./worker": {
		"node": "./lib/node/worker_threads.js"
		"default": "./lib/browser/web-worker.js"
	}
}
"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants