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

[RFC] Bundle plans #18447

Closed
2 of 6 tasks
eps1lon opened this issue Nov 19, 2019 · 4 comments · Fixed by #22814
Closed
2 of 6 tasks

[RFC] Bundle plans #18447

eps1lon opened this issue Nov 19, 2019 · 4 comments · Fixed by #22814

Comments

@eps1lon
Copy link
Member

eps1lon commented Nov 19, 2019

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
@oliviertassinari
Copy link
Member

oliviertassinari commented Nov 19, 2019

@eps1lon Thanks for putting together this proposal.

/es contains the source files

This description might be confusing. Should we say that it compiled for production, to support the latest official features in the ECMAScript version (2019 as we are speaking)?

https://github.com/mui-org/material-ui/blob/3f42da193b8eb0083a2940ed17499fcea3c24465/babel.config.js#L3-L6

Why

Will developers take the time to look into this concern? How much time do you think that this effort will take? Does Material-UI need to "lead the way"?

I would propose the following

We wait to ear more frustration on this matter from our users. As the pain grows, our incentive to prioritize this effort grows.

Is it accurate that the developers that are facing this problem today, can solve it with the /es folder? That if they are willing to spend time on it (because they evaluate the ROI is positive), they can already find a way? I think that it would be great to add external resources to the RFC. It would help to evaluate the return on investment on such an effort :).

@eps1lon
Copy link
Member Author

eps1lon commented Nov 19, 2019

This description might be confusing. Should we say that it compiled for production, to support the latest official features in the ECMAScript version (2019 as we are speaking)?

We can't support the latest official features of ES. Any JS will always work in later versions of ES. That's the most important feature of ES. That statement is more confusing than using "source files" as a mental model.

Will developers take the time to look into this concern?

They should, yes. I'm not concerned with developers that do not consider their bundle size. No amount of work we're doing regarding bundle size will interest these developers but they are not the ones building production websites.

We wait to ear more frustration on this matter from our users.

As a library we are the ones who should be concerned with these steps not app devs. It's our job to provide an infrastructure that make it easy to do the right thing.

Could you explain what you mean by "we wait"? I didn't say that I want to implement this tomorrow. What and how we build these bundles is totally open and I'd like to hear from users. That is why I added the "discussion" label and requested commentes.

I want to emphasize again what I wrote in the initial sentence of the "Why?":

The "modules and nomodules" pattern is gaining some traction

See nextjs support, recent chrome dev summit, preset-modules release, default support of parcel of such features etc.

@oliviertassinari
Copy link
Member

oliviertassinari commented Nov 19, 2019

That statement is more confusing than using "source files" as a mental model.

@eps1lon It's fair. My concern is with "source files" that might suggest we publish the GitHub sources without any transpilation steps, while we do make our source ready to be consumed Maybe we should say that the /es "distribution" assume all the feature of ECMAScript (of the latest version) are natively available.

No amount of work we're doing regarding bundle size will interest these developers

Yeah, they will probably note care until they find the UI slow on their latest $3,000 MacBook Pro 😁.

they are not the ones building production websites.

I think that it depends on the resources these developers have, and more specifically, the $ impact a 100ms win can have on the business of these developers. Can it recoup the cost of the software developer that works on it?

As a library we are the ones who should be concerned with these steps not app devs. It's our job to provide an infrastructure that make it easy to do the right thing.
Could you explain what you mean by "we wait"?

Yes! So, my main concern is about having the right timing. I think that these types of improvements are better pioneered by lower-level libraries, like Webpack, React or Next.js. I don't think at Material-UI, at its level, should be too much on the edge nor that we should invest too many resources on early exploration. I would propose that, unless there is a proven solution (already successfully deployed in the OSS world by a noticeable project) that have a good ROI, we stay attentive and wait for this event to happen. Nevertheless, it's great that you stay attentive :)!

@NMinhNguyen
Copy link
Contributor

FYI, Create React App (CRA) transpiles node_modules for you so this would be a transparent change for CRA users and automatically bring bundle size reductions 🙂

I haven't used the module/nomodule pattern in Next.js yet so I don't know if this issue is also applicable in that case, but it seems like by default Next.js doesn't transpile node_modules currently: vercel/next.js#706

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

Successfully merging a pull request may close this issue.

3 participants