Completion roadmap for react-scripts@2.0
Timer opened this issue · 35 comments
Hey everyone! We know progress on react-scripts@2.0
has been stagnating for a while.
We put together a lofty set of goals when we first started v2.
The scope of these changes have proven themselves to be too large to effectively polish everything and create a stable build.
To remediate this, we're going to reduce the scope of v2, polish completed features, and release v2 as stable within the next two (2) weeks.
Action Plan
Our proposed plan of action is as follows (in no particular order):
-
✅ Fix vendor chunking (#4977, #4769, #4633, #4632)
- Vendor chunking exhibits undesirable behavior when used in combination with code splitting. The application dependencies used by every application chunk end up in a single vendor bundle, effectively nullifying the value of code splitting.
- We would like to create a vendor chunk per application chunk. If this behavior cannot be achieved, we will revert vendoring and place dependencies in the application chunks.
- As an alternative to the former, we may only enable the vendor chunk when no code splitting is used in your application (if possible).
-
✅ Switch to Terser (#4948, #4902, #4711, #4692, #4683, #4665, #4329, #4116, #4100)
- Uglify-ES has been the source of a lot of problems, and is no longer maintained. We should switch to Terser (the more maintained fork of Uglify-ES) to fix obscure bugs resulting from production builds.
-
✅ Revert monoreport support (#3741, #3997, #4001) because there's too many issues (#4569, #4410, #4249, #4092, #4570, #3031, #3967)
- We would've loved to figure out all of the ergonomics around monorepo support, but it turns out it's just too difficult.
- We're going to revert monorepo support in favor of consuming library packages via
nwb
and provide excellent documentation on how to do so. This is arguably the best way.
-
✅ Fix edge-cases for compiling
node_modules
and polish Babel 7 upgrade- Compiling
node_modules
has surfaced some issues, particularly aroundasync
/await
andregenerator
. - We also need to make sure all of our Babel configuration tricks are valid for v7.
- Compiling
-
✅ Remove
mjs
support- The ecosystem is not ready for
mjs
support and we're going to remove support to fix complex edge cases with resolving modules. There are alternative resolve orders based on source file and supported features which are concepts Jest does not have support for yet. - This will be added back in the future.
- The ecosystem is not ready for
-
✅ Drop advanced proxy configuration and replace it with
express
middleware- Allowing users to configure their proxy in package json has been a pain-point and source of configuration, going against our values of convention.
- We will remove the ability to configure the proxy and replace it with exposing the
express
app instance. You can attach any middleware or routes to thisexpress
app that you'd like. - A recipe for proxying requests will be provided in the documentation.
-
✅ Remove support for targeting newer browsers
- We added support for targeting specific sets of browsers and there has been multiple issues that cropped up about this. We are going to remove the ability to target browsers and compile everything down to ES5 -- this is in line with v1 behavior.
- The difference now is that we compile
node_modules
, so you can consume any package using newer syntax without worry. - In a follow up release, (potentially v2.1) we will explore adding a "modern"/evergreen browser mode which outputs modern, (nearly) uncompiled ESnext. This should give users the best of both worlds, and is in line with what we see in the community. A proposal going into more detail will be put together after the release of v2.
How can I help?
Please let us know your thoughts and if we missed anything.
We'll be more than happy to explain our rationale around these decisions if there's any further questions.
If there's anything you (and the community) feel strongly about but is not found on this list, please make an effort to send a PR!
We'll be more than happy to accept contributions.
Cheers, everyone!
To summarize the existing changes and the above proposed changes:
v2 Features
- Babel 7
- Jest 23
- webpack 4
- Babel Macros
- Compiling
node_modules
to support packages using newer language features - Parallelization of webpack builds to speed up compilation
- Opt-in support for CSS Modules
- Opt-in support for Sass
- Targeted CSS support via
browserslist
package.json key - SVG as React components
- Remove
propTypes
definitions in the production build - Service workers are now opt-in
- Long-term webpack caching via consistent hashing and vendor bundles
Features removed from v2
- Monorepo support (supplanted via documentation)
- Advanced proxy configuration in
package.json
(moving tosrc/setupProxy.js
instead) - Specifying newer target browsers: all code will be compiled down to ES5 (in line with v1 behavior)
mjs
extension support
This list looks good! One ask I have, with "Compiling node_modules to support packages using newer language features", can we get support for dynamic imports in node_modules
included in 2.0? CRA supports dynamic imports for "app code". Would like to extend that support for dynamic imports used in dependencies.
I am curious about the Monorepo support via nwb
? I always understood nwb
is something similar to create-react-app
? Are you talking about a different package? I am interested in this because I would like to do some code sharing between two CRA projects and looking for a good solution to do without publish a package to npm
The plan (@Timer correct me if I'm wrong) is that we'll support putting CRA in a monorepo but we won't attempt to compile any code outside the project folder (e.g. JSX). You can compile it with tools like nwb
though.
I've got a working monorepo with a react-scripts@2.0.0-next.3e165448
project inside. I also documented some of the gotchas I encountered along the way. Most of them tended to be that I have to use the same version of certain packages in my other sibling projects due to react-scripts@2's feature of tooling version validation and a bit of yarn's version resolution system.
I'd be happy to share what I've discovered with someone if they wanted to reach out to me. Unfortunately, I don't have the time to directly contribute on documentation at this time, but I do have time for a quick chat and knowledge share.
"Parallelization of webpack builds to speed up compilation" What does this mean? That a single build will have webpack tasks spread across the various CPU cores? Or that multiple build configurations will run in parallel?
"Parallelization of webpack builds to speed up compilation" What does this mean? That a single build will have webpack tasks spread across the various CPU cores? Or that multiple build configurations will run in parallel?
That a single build will have webpack tasks spread across the various CPU cores.
re @bjankord: Dan and I spoke, we will support dynamic import (import()
) in node_modules
!
@Timer I'm asking ya'll what you mean by that statement. I don't know what it means, and I'm asking for clarification. I proposed some speculations.
Sorry @tbranyen, I didn't mean to leave the question mark -- your speculation was correct. I edited my comment to reflect this.
Processing files through ESLint, Babel, and Minification all happen in worker processes. It'll use all but 1 available cores.
I would love to see CRA v2 consider referencing create-react-library as a mature sister project for solving the monorepo use case of defining reusable component libraries, especially if this is just going to be a docs update.
Nothing against nwb
-- CRL
just seems more similar in spirit and simplicity to CRA
.
(note that I am the maintainer of create-react-library
)
Nice that v2 will finally be released!
Sad about the drop of monorepo support.
Uglify has been the source of a lot of problems, and is no longer maintained. We should switch to Terser (the more maintained fork of Uglify) to fix obscure bugs resulting from production builds.
Just adding 2 cents on this. UglifyJS itself is still maintained (from what I know), it is UglifyES that got discontinued and it's the one that is now maintained by Fabio as Terser. UglifyJS should still be a good enough choice for CRA (at this point in time) as from what I read you plan to output es5 for now and that is exactly what is supported by UglifyJS.
UglifyJS should still be a good enough choice for CRA (at this point in time) as from what I read you plan to output es5 for now and that is exactly what is supported by UglifyJS.
We only plan on outputting es5 for the short term. We want to add a modern mode that outputs ESNext.
Sorry I didn't get the semantics quite right, I'll edit for clarity!
is there any possibility to also make it Server side rendered app?
Sorry I didn't get the semantics quite right, I'll edit for clarity!
No problem, that is an easy mistake to make. I'm not involved in those projects, but felt that this could be clarified in the post. Cheers!
Maybe we could land support for modern browsers (#4964) in v2? I would do whatever it takes to make it happen.
Great!
Re: modern browsers please don't miss this in the original post:
In a follow up release, (potentially v2.1) we will explore adding a "modern"/evergreen browser mode which outputs modern, (nearly) uncompiled ESnext. This should give users the best of both worlds, and is in line with what we see in the community. A proposal going into more detail will be put together after the release of v2.
Does #4772 not give the desired vendor chunking behavior?
I don't think creating a vendor chunk per application chunk should be the goal. The point for the vendor chunk is to contain a lot of the commonly-used dependencies so each application chunk does not have to load them (things like react etc).
is there any possibility to also make it Server side rendered app?
@rawris
Sorry, but this is out of scope at this time. Please consider something like Next.js in the meantime.
Does #4772 not give the desired vendor chunking behavior?
@TLadd
Sorry, I didn't see that PR -- but that PR uses the default behavior which names chunks via what's included (instead of numbering them) causing unnecessary cache invalidations.
Using { name: false }
is recommended for production.
No worries; glad to have it fixed!
While I've downgraded to 1.x, my issue with 2.x beta was that it's memory exploded and it couldn't build a project that 1.x could build without issues.
The app had the following dependencies:
"dependencies": {
"aws-sdk": "^2.287.0",
"d3": "^5.5.0",
"firebase": "^5.3.1",
"immutable": "^3.8.2",
"lunr": "^2.3.1",
"mapbox-gl": "^0.47.0",
"mousetrap": "^1.6.2",
"numeraljs": "^1.5.6",
"pandas-js": "^0.2.4",
"plotly.js": "^1.39.4",
"qs": "^6.5.2",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-offline": "^0.1.0",
"react-plotly.js": "^2.2.0",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"react-semantic-ui-range": "^0.6.2",
"react-spinners": "^0.3.3",
"react-tap-event-plugin": "^3.0.3",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0",
"semantic-ui-css": "^2.3.3",
"semantic-ui-react": "^0.82.1"
},
I understand that these imports could be optimised and separated or partially loaded from CDN, like plotly.js, but just wanted to show a use case where 2.x couldn't build something what 1.x could.
Can you please share a reproducing project of something that can't build but built with v1 please, @hyperknot?
@Timer I cannot share the project I'm working on, but maybe I can just create a new app and import these ones to repro.
That'd be helpful! I'm not sure if it requires some to be dynamic imports, etc. Please make it as close to your app as possible. :-)
Understandable that the monorepo support was dropped for now, any chance it will be considered for a future 2.x release?
Adding another tooling layer to compile internal monorepo packages that do not need to be published is less than ideal.
We might consider it but it needs to be a more concrete proposal and ideally there would be some consensus between different tools on how to do it.
Hey, sorry if this is already documented, I can't find it:
Monorepo support (supplanted via documentation)
Can you point me to the documentation on how to import transpiled JS that is outside the CRA /src folder? Or am I misunderstanding?
@mdavid88 that is under the "removed features" section. It did not ship with v2, maybe with v3!
@Timer Hey thanks. I was unclear. I get that it's been removed, but it sounds like the functionality still exists to do what I want:
We're going to revert monorepo support in favor of consuming library packages via nwb and provide excellent documentation on how to do so. This is arguably the best way.
I have a shared-components directory as a sibling to the CRA directory, with built components using nwb. Is there a way to import ComponentName from 'shared-components'
in my CRA app, or am I misunderstanding?
Sure, that behavior should "just work" assuming your package.json is configured correctly to point at compiled sources and not original source. Can we file a new issue for continued discussion? I don't want to make more noise on this closed issue. Thanks!