Skip to content

Add modules used to shared global #1396

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

Open
connorjclark opened this issue Mar 5, 2025 · 6 comments
Open

Add modules used to shared global #1396

connorjclark opened this issue Mar 5, 2025 · 6 comments

Comments

@connorjclark
Copy link

I work on Lighthouse, and a few years ago I developed the audit for detecting likely unnecessary polyfills and reporting their cost to developers. The goal of that audit is to inform developers when their website is polyfilling widely-supported JS features; the idea being that very few websites need to support truly legacy browsers (and in fact, many sites that include such polyfills don't even load in legacy browsers due to inconsistent tooling).

This Lighthouse audit has been around for a few years, and recently I updated it (no need to dig into this, it's not related to my proposal).

I'd like to suggest a small change to core-js to greatly improve the accuracy of this audit.

Today the audit detects polyfills in two ways:

  1. grepping the scripts of the website for evidence of polyfils emitted by core-js
  2. if source maps are present, looks for specific module files

Many sites don't deploy source maps, so option 1 is important to do well. However, the grepping solution is clunky, expensive to run, and prone to false positives. It's tough to correctly identify all possible polyfills, as it relies on detecting code that has gone through any arbitrary bundler/minifier/etc.

My proposal is to add to the shared global (window['__core-js_shared__']) - for each versions entry, provide the list of modules that core-js decided to include (as given by core-js-compat). That way, even without source maps, it can easily be determined what polyfills core-js added to the page.

If this sounds good to you, I'm happy to implement this myself.

@zloirock
Copy link
Owner

zloirock commented Mar 6, 2025

Thanks for the proposal. I've been pondering this. It's useful but adds extra overhead as it must be declared in each module. We'll see if this can be added.

@zloirock
Copy link
Owner

zloirock commented Mar 6, 2025

This will increase bundles size by about 10%. I'm not sure if it's worth.

@connorjclark
Copy link
Author

I agree an 10% increase would be not worth it - can you share how you came to that number?

I did a rough guess and came up with more like 3% (here are my notes). also, compression helps - these module names are very compressible.

but that's just considering the raw data of these strings - maybe it gets closer to 10% given the overhead you mentioned in your first comment.

@zloirock
Copy link
Owner

zloirock commented Mar 7, 2025

It should be defined in each module. Entries are not a good place for that since modules can be loaded without them (like preset-env), a module name can't be figured out in modules like internals/export.

At this moment, core-js contains 533 modules. The average length of a module name is 21 symbols. Let's imagine that it will be defined like

var defineModule = require('../internals/define-module');
// ...
defineModule('my.module.name');

that after bundling could be minified to something like

var d=r(123);
// ...
d('my.module.name');

Totally, it's about 40 bytes for a module.

The full core-js minified bundle size is about 250KB. 533 * 40 / 1024 ~ 21KB. About 8.4%.

It's required not for all modules; for example, esnext.regexp.escape relies on es.regexp.escape. In most cases, instead of theoretical internals/define-module can be used something like an extra internals/export parameter. But anyway, it's not less than 6.5-7%.

@connorjclark
Copy link
Author

connorjclark commented Mar 7, 2025

Maybe it'd be just as useful to instead include the resolved browsers target (ex: { "android":"61", "chrome":"61", "edge":"16", "ios":"10.3", "opera":"48", "safari":"10.1" } ... and maybe the caniuse version?) - would that be more feasible?

Then one could roughly tell what browsers core-js targeted for code deployed to a site - the exact polyfills used would vary based on the caniuse/core-js version... but I think it could work at least as a basic check.

@zloirock
Copy link
Owner

zloirock commented Mar 7, 2025

I have no idea where I could get it on core-js side (only core-js-builder which is used quite rarely). I think that it could be done on the Babel / SWC preset-env / runtime side.

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

No branches or pull requests

2 participants