Skip to content

[RFC] Bundle plans #18447

@eps1lon

Description

@eps1lon

Current Situation

We ship 3 bundles:

  • main entry points to a bundle using CommonJS modules supporting legacy browsers[1]
  • module entry points to a bundle using ESModules supporting legacy browsers
  • /es contains the source files

Proposal

Ship the following bundles that are coupled to their target environment and not to a generic preset:

  • "modules"-bundle: uses ESModules and supports browsers that support ESModules aka "modern" browsers (this will include node 14)
  • "nomodules"-bundle: uses ESModules (for tree-shaking) and supports legacy browsers
  • "commonjs"-bundle: uses CommonJS and supports node 10 (current LTS version at the time of release)
  • "modern"-bundle (TBD): See [RFC] Support only last n browser versions #15496
  • "esnext"-bundle (TBD): source files that only uses features part of the latest ES spec i.e. stage-x proposals are transpiled.

As far as I know the current main entry isn't all that meaningful since it mixes module concerns with target environment concerns. We don't need to support ie11 with commonJS. If you target IE11 you have to use a bundler anyway since IE11 supports neither CommonJS nor ESModules.

Why

The "modules and nomodules" pattern is gaining some traction and by mapping this directly to our bundle it's easier for users to decide which bundle to use.
With this change it's no longer required to transpile our files to get a "modules" bundle (an alias is easier than configuring the babel-loader).

Implementation details

Plenty of unanswered questions. I'd like to put the files next to each other leveraging .(js|mjs) extensions (mjs for esmodules and .js for commonjs). It's not as important whether bundlers support this (I guess any old bundler supports this one way or another with manual work) but whether they support this by default. The "modules" build would go into a separate folder.

For v5 we might flip this default ("modules" by default, "nomodules" in /legacy). While I'm not a big fan of it popular bundle size pages are pressuring libraries to use the smallest bundle as the default.

Adding this would make more sense after we switched to next 9 and reintroduced page size tracking. This way we can compare the bundles better.

The "nomodules" and "commonjs" bundles are not as important right now. Though I didn't check how a less transpiled bundle would affect ssr. The "nomodules" bundle is basically our module entry right now. The "modules" bundle can be shipped in a minor release.9

Concerns

What are the drawbacks of publishing that much code to the registry? What services penalize that metric? CodeSandbox is definitely an issue here. We should find out if CSB users download the full package or only the parts needed.

Plan

  • [ ] .node extension with webpack 2,3,4
  • [ ] .node extension with rollup
  • [ ] .node extension with parcel 1,2
  • participate in conversation about modern bundle entry point (talk to authors of bundle compare sites how we can communicate different bundles)
  • finish [docs] Upgrade to next 9 #18441
  • Upgrade babel deps to latest to reduce size diff noise
  • Leverage babel 7.8 (simpler build task thanks to Add --out-file-extension option to babel-cli babel/babel#9144)
  • Include /modules folder in build transpiled with @babel/preset-modules
    What about size tracking? A simple markdown table is less usable with this number of entries. A separate app might make sense. The data is available as json
  • Are npm release tags a valid alternative to bundle aliases?
    No. They point to a specific version and SemVer has no ability to communicate different variants for versions

notes

[1] legacy browsers

ie 11
edge 14
firefox 52
chrome 49
safari 10
node 8
-- https://material-ui.com/getting-started/supported-platforms/#browser

Updates

  • remove .node. Node will use .js files while the "modules" build uses .mjs. "nomodules" will go into /legacy

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions