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

change(web): common downcompile helpers 🧩 #8904

Merged

Conversation

jahorton
Copy link
Contributor

@jahorton jahorton commented Jun 1, 2023

Inspection of the results of our esbuild-bundled products indicates that it's pretty cautious with ES5 code... enough so that without a little help, this can result in somewhat significant filesize bloat for us.

By default, TS directly emits down-compilation "helper" functions - essentially, polyfill helpers for ES6+ features - into ES5-targeting compilations. This was "fine" when everything was namespace-based - after all, we had <reference path="..."/> links that essentially compiled all of the relevant code, at once, into a single file. One destination file, one set of "downcompile helpers".

With a little extrapolation, note that now, with modularized code, we instead have over a hundred individual module files. These, in turn, get bundled together for the final build. The problem... is that TS will, by default, directly emit those "downcompile helpers" into each and every one of those "over a hundred" module files that needs it. Only the ones that are needed by each specific file, granted, but it definitely adds up. The one that made me aware of this: the __extends helper (for class inheritance) gets duplicated at least 30 times - which represents several kilobytes of bloat by itself.

Enter the TS compilation option: "importHelpers". The short of it: the developers of TypeScript also publish the library tslib - a centralized package of modules defining the same helpers. Using it tells tsc to instead insert any needed import { ... } from 'tslib'; statements into our compiled modules - with a single, centralized definition. This prevents "downcompile helper" duplication, allowing us to save on filesize.

This does mean:

  • adding 'tslib' as a dependency
  • ensuring that it can be properly used and imported by esbuild
    • ... which took significant effort on my part to resolve.
    • This is why /common/web/tslib is added - it's the workaround that worked. Long story short... another problem arose due to es5 being "allowed", but not exactly first-class "supported", by esbuild.
    • At least esbuild also provides the alias feature, which was necessary to fully implement the workaround.
    • Of course, with the workaround being a package... well, we've got to ensure that build dependencies are appropriately set.

Unfortunately, tree-shaking doesn't appear to be possible for esbuild + tslib with the setup I could get working... at least not built-in. As a result, I believe it's better to leave tslib out of the worker at present; it doesn't have nearly as much "downcompile helper" duplication as the rest of Web's codebase, so it may not win us anything there.

That said, after further experimentation, I believe I've figured out how to use esbuild plugins to handle tslib treeshaking ourselves; this would save more KB and allow use of tslib within the lm-worker. But that'll be a separate PR - #8964.

The last notable change pattern - I'm getting a spurious error for downcompilations involving "array spreading": [...array] scenarios. Fortunately, our uses appear safe to convert to [].concat(array)-style code, which poses no such issue.

@keymanapp-test-bot skip

@jahorton jahorton added this to the A17S14 milestone Jun 1, 2023
common/web/tslib/build.sh Outdated Show resolved Hide resolved
common/web/tslib/package.json Outdated Show resolved Hide resolved
web/src/app/browser/build-bundler.js Outdated Show resolved Hide resolved
Base automatically changed from change/web/filesize-fixes to feature-esmodule-web-engine June 8, 2023 05:59
@jahorton jahorton force-pushed the change/web/common-downcompile-helpers branch from d5975f5 to e318c5c Compare June 8, 2023 06:04
@jahorton jahorton marked this pull request as ready for review June 8, 2023 06:47
@jahorton
Copy link
Contributor Author

jahorton commented Jun 8, 2023

Comparison:

Before:

❌ Oh dear! keymanweb.js is 45925 bytes (11%) larger than 17.0.120, now 438950 bytes

After:

❌ Oh dear! keymanweb.js is 23041 bytes (5%) larger than 17.0.120, now 416066 bytes

That's over 22 KB in savings. The followup (#8964) should increase that by about another 8 KB.

common/web/tslib/build.sh Outdated Show resolved Hide resolved
common/web/tslib/package.json Outdated Show resolved Hide resolved
common/web/tslib/package.json Outdated Show resolved Hide resolved
common/web/tslib/package.json Outdated Show resolved Hide resolved
@jahorton
Copy link
Contributor Author

jahorton commented Jun 9, 2023

As #8964 (based on this) has passed all relevant build checks at this point, and both this one and that are approved, I'm moving ahead with merging now. (The Developer check is pending, admittedly, but that's it.)

@jahorton jahorton merged commit 4ae1677 into feature-esmodule-web-engine Jun 9, 2023
@jahorton jahorton deleted the change/web/common-downcompile-helpers branch June 9, 2023 03:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants