facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
227.76k stars 46.48k forks source link

Feature request: Add a "module" entry in package.json to export ES2015 version of React #10021

Open misterfresh opened 7 years ago

misterfresh commented 7 years ago

Do you want to request a feature or report a bug? Request a feature

What is the current behavior? React ecosystem was promoting ES6 classes and modules since 2014 and many packages like react-router, redux and so on, have an "es" folder in the npm package with source code in ES2015 modules. Unless I am missing something, it is strange that React itself does not offer that option.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/84v837e9/). Install react and try to import it in a browser with native modules enabled.

What is the expected behavior? Have an "es" folder in the npm package with ES2015 modules source code, like most React ecosystem projects do. Allow to import react from ES2015 native modules to make developer workflow more simple.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React? All versions

Haroenv commented 7 years ago

The source code of react is still using a custom module system that is close to CommonJS and not using es2015 modules AFAICT. I assume this is why they also aren’t exposed.

misterfresh commented 7 years ago

For anyone bumping into this, it is possible to bundle CommonJS modules as native modules using the config in this file

lukastaegert commented 6 years ago

At rollup, we were made aware of this issue because you exposed a bug in rollup-plugin-commonjs. in a way, thanks for that 😉. But this would not have happened if react had had a module entry/ES6 export.

Given the recent improvements to rollup's tree-shaking algorithm (and there are more in the pipeline), at least for rollup users, exposing an ES6 bundle might have some positive effects on the bundle size depending on what react features are used. If you want to go there, such a bundle should ideally

as this makes it easier for the tree-shaking algorithm to do it's work.

Even though I must admit I do no understand every aspect of react's build script, I would expect this could basically be solved by adding another build target with the correct format + possibly an entry point that has the right exports.

Btw. I noticed you are using a rather old version of rollup. If there is anything preventing you from updating, please file an issue! There is an interesting TODO comment here–is this still current 😜?

Andarist commented 6 years ago

@lukastaegert are named exports and default ones different in any sense? default is just a named export AFAIK, only treated differently when imported.

TrySound commented 6 years ago

@Andarist default export can not be changed in runtime. Named exports are bindings, so with let can be changed from file with them.

lukastaegert commented 6 years ago

Maybe my comment about named exports was a little cryptic, so I will elaborate. I was referring to the not uncommon practice of exporting things twice from a file–once as a named export and once as a member of the default export. The latter is what often prevents tree-shaking for the named export even though the default export is not used. The reason is that in the exporting file, the default export still needs to be assembled and if this assembled object is included in the bundle–which can happen easily for various reasons–all its members will be included in the bundle.

This practice probably stems from the fact that bundlers like webpack and indeed rollup's CommonJS plugin do this themselves when converting CommonJS files. Other libraries that do this include lodash-es. When you remove the default export from node_modules, bundle size after tree-shaking can currently be nearly halved (more would be possible with future improvements).

What does this mean for react? If you make it possible that this

import {Component} from 'react'

can be interchanged with

import React from 'react'
const Component = React.Component

then you always need to assemble the React object which in most likelihood will break most of tree-shaking for the whole package. However I understand that for these decisions, ease of use should always be preferred to premature optimisation. But it is a point to consider especially if you plan to move to a native ES6 modules in the future (which in my opinion you should).

Andarist commented 6 years ago

Ah, sure - this I understand and I'm aware of. I don't like though recommending only named exports as some kind of the rule of thumb. Way better is to just educate people about consequences of attaching things to the default one (hint hint your eslint plugin ;) )

However I understand that for these decisions, ease of use should always be preferred to premature optimisation. But it is a point to consider especially if you plan to move to a native ES6 modules in the future (which in my opinion you should).

Personally I do not see import {Component} from 'react' any harder to use, assuming it would be exported purely as named export (no attachment to the default one).

Migration to the newer export style could be easily run with a codemod and also a babel plugin could be created to allow people using class MyComponent extends React.Component {} syntax.

Jessidhia commented 6 years ago

@TrySound just a note: a default export is like any other export and can be changed at runtime. It's the export default statement that is the complicated one.

An export default of named function declaration or named class can be reassigned by reassigning to the function/class name, but otherwise it appears non-reassignable. But you can always do a mutable default export by declaring let Identifier and doing export { Identifier as default }.

Not that I recommend doing it as immutability is good for you.

misterfresh commented 6 years ago

For now I can make it work by manually re exporting the named exports in a separate file, then bundling that file with Rollup.

alt text

gaearon commented 6 years ago

I want to make it clear you're not going to get awesome benefits by "tree shaking" React. Most of the code is in the internals that is always used. You might at most shave off one or two kB, and only if your code never uses React.Children.

So this is not a high priority optimization for us for that reason.

misterfresh commented 6 years ago

For me, the main benefit of having an ES module option for React is to be able to use native modules during development, to avoid rebundling on every change to the code.

Andarist commented 6 years ago

Also with es modules in place webpack could scope hoist react, at the moment it simply bails out on react because it treats it as commonjs.

gaearon commented 6 years ago

There's not much you'll gain from scope hoisting React, except for maybe a 1 KB of Children helpers.

gaearon commented 6 years ago

For me, the main benefit of having an ES module option for React is to be able to use native modules during development, to avoid rebundling on every change to the code.

Why can't you use the regular UMD build in this case? It would also avoid rebundling.

gaearon commented 6 years ago

This is blocked on deciding what we actually want to export from each package, and in which form: https://github.com/facebook/react/issues/11503 Feel free to comment with proposals there.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

TrySound commented 4 years ago

not stale

stale[bot] commented 4 years ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

just-boris commented 4 years ago

If this issue is still affecting you, please leave any comment

any comment

luxp commented 4 years ago

Really want ESModule export, cause there is some cool things like vite, snowpack, etc need the esmodule support.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

dominic-p commented 4 years ago

any comment

stale[bot] commented 3 years ago

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

petersolopov commented 3 years ago

any comment

beginor commented 3 years ago

Waiting for ESModule export of react!

iMakedonsky commented 3 years ago

One more to that, waiting es modules

anumthapa commented 3 years ago

Es module, server error

On Sun, Feb 21, 2021, 22:54 Oleksander Mashianov notifications@github.com wrote:

One more to that, waiting es modules

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/facebook/react/issues/10021#issuecomment-782924432, or unsubscribe https://github.com/notifications/unsubscribe-auth/AED3A7VBMFLIOV6XZMA22FDTAFXHJANCNFSM4DQGC45A .

samwightt commented 3 years ago

Really could use this being a thing. CDNs like JSDelivr's new ESM CDN are really cool, but they're not able to load React. As far as I know the only ESM CDN I know of that's able to work properly with React is the Skypack. Every other view library I know of works properly across the major CDN providers except for React :(

jollytoad commented 3 years ago

I've been experimenting recently with import-maps aided by the JSPM CDN and import-map generator, and am surprised and disappointed to find that react doesn't have a pure ESM build in its package (just cjs and umd). This is not about tree-shaking, bundling, or optimisation ... it's about choice, the choice to progress the state of JS in the browser, the choice to experiment with and embrace these new technologies such as import-maps, that have the very real potential to bring an end to the bundling madness. Please, please, please, add a simple ESM build, along with appropriate 'module' & 'exports' fields into the package.json.

steve-taylor commented 2 years ago

Hybrid (CommonJS and ESM) packages are too much hassle, e.g. dual package hazard which can easily break React, Styled Components, etc.

It's time to let CommonJS die and go all in on ESM. A number of packages have gone pure ESM and if React did too, it would be a huge signal to the ecosystem that CommonJS is on its last legs.

kungfooman commented 1 year ago

@steve-taylor Totally agree, but it's now 2023 and the issue has been open since 2017. I think we have to wait a few more years?

GabrielDelepine commented 1 year ago

the issue has been open since 2017

Sorry but this is not a constructive comment. We all know for how long this issue is opened, it is not even an argument. Please be patient or fix the issue by opening a PR