facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.73k stars 26.86k forks source link

Speed up npm run build #913

Closed ivosabev closed 6 years ago

ivosabev commented 8 years ago

This is not a bug, but more like a request to speed up the build times. Even on a clean project it takes a good 15 seconds to build and on a medium-sized project it goes to 3-4 minutes. Any effort in this direction will be greatly appreciated.

Thanks!

gaearon commented 8 years ago

It's most likely due to linting. We should enable cache for ESLint loader because I think it's disabled right now.

If you could supply a larger project reproducing it, that would be helpful for figuring out the root cause.

thien-do commented 8 years ago

@gaearon I can supply a real life large project (a trading app), which takes about 3 minutes to build. However, it uses a fork react-scripts. Can it help?

gaearon commented 7 years ago

@dvkndn Yea it would be helpful.

godmar commented 7 years ago

Would like to second @ivosabev 's request.

On a 2-core, 2GB Digital Ocean instance, npm run build on a null-CRA 0.7.0 project takes 11s. It takes similarly long for the webpack dev server to start.

Adding 15-20 .js files for components, etc. expands this to 20s.

I'm not sure whether CRA is to blame, though - I've seen similarly catastrophic build times in other projects with similar, but indepedently created webpack configurations.

gaearon commented 7 years ago

Can you debug why this happens? I don’t have the time to look into it right now. But if you put a few logs here and there you’ll likely see the overall picture of where the time is being spent.

As I noted above it might help to enable caching for ESLint loader. Have you tried this?

godmar commented 7 years ago

A big contributor is UglifyJSPlugin. Disabling it reduces the build time for an empty project from 11.9s to 6.7s on my machine (that's 44%).

Removing eslint from preloaders, by contrast, reduces the build time from 11.9s to 10.5s (that's 11%).

godmar commented 7 years ago

I tried your idea by setting 'cache: true' in the eslint config. This shaved about .5s of subsequent runs (provided no files were changed.) Only src/index.js and src/App.js made it into the cache (for an empty project).

For non-empty project (2,249 lines of JavaScript in 45 files) Build time: 66s Build time without UglifyJS plugin: 27s Build time without eslint: 62s Build time on 2nd and subsequent builds when eslint cache turned on: 61s Time between npm start and development server reporting ready: 16s

This is what the early 1990s were like when we waited for our TurboPascal or TurboC project to compile on our 80386 33 MHz desktops. It kind of takes the fun out of development, especially considering that we're using a language that fundamentally shouldn't need any compilation.

The only redeeming fact here is that a hot rebuild (touching a .js file) takes "only" 4-5 seconds - as long as HMR doesn't get stuck. Although even that is hampered by the fact that I usually make changes to multiple .js files when developing (2-3 files), and each file save triggers a separate rebuild, so a total of 12-15s.

I'm seeing similarly abysmal performance with webpack 1.x on a project that doesn't use CRA, so I don't think CRA is to blame. Are you not seeing that?

gaearon commented 7 years ago

It kind of takes the fun out of development, especially considering that we're using a language that fundamentally shouldn't need any compilation.

Do you perform production builds often? What is your use case for this?

godmar commented 7 years ago

Production builds I generally don't do often, although I did find myself having to do it frequently when I debugged issues related to the PUBLIC_URL setting (in development empty string "" but a path in "production"). I also had to frequently rebuild to debug websocket related issues (since there development and production use different settings; although I understand that 0.8.0 can proxy websockets.)

For websockets, it was an issue of debugging the right combination of { path : }, nginx forwarding rules, etc. which required frequent production builds.

Having to wait 5-8s in development is however still an order of magnitude more than in other work flows. For instance, a static HTML page takes generally under 1s to update and reflect a new version of the code.

I would love to have a solution for the "multiple file" update problem. Something that tells webpack: "I'm about to update multiple files", followed by "I have updated multiple files, please rebuild"

gaearon commented 7 years ago

Tagging this so I remember to get back to it.

godmar commented 7 years ago

PS: also remember pure development use cases where hot reloading doesn't work, for one reason or another (frequently having to run 'npm start' for development is slow too.)

gaearon commented 7 years ago

Not sure what you mean by hot reloading in this case and when it doesn't work. Whenever you save a file development server should rebuild. If not it's a bug and you should file it along with any details. The "reloading" part of this triggers a reload via web sockets but it's non-essential. You can still refresh and get a fresh development build. If not it's a bug and you should file it with any details. You are not supposed to ever have to restart npm start once it's running..

godmar commented 7 years ago

I mean that not everyone is able or willing to let their development server running all the time.

For instance, I work in an environment where the development server runs on a cloud instance (using stdout), but I work on a laptop. Whenever I change rooms, lose my network connection, I log on again and restart the development server. Every time I incur the penalty of having to wait for the entire project, usually multiple times a day.

godmar commented 7 years ago

If you expect that npm start is long running, make it a system service.

gaearon commented 7 years ago

Whenever I change rooms, lose my network connection, I log on again and restart the development server.

Can you use something like tmux to keep session alive? I think that's how people usually approach this with any other servers.

godmar commented 7 years ago

I could, but generally don't like to have sessions hanging around on machines I'm not present on (just a personal preference).

BTW, another use case are impromptu demonstrations and teaching.

gaearon commented 7 years ago

Got it. Thanks for sharing, sorry it's not great right now. One thing at a time. :-)

themre commented 7 years ago

just came across this https://github.com/amireh/happypack if it helps anything in the future.

gaearon commented 7 years ago

Unfortunately too many caveats (especially windows support).

viankakrisna commented 7 years ago

How about enabling DLL plugin? I've heard people waiting 15 minutes for webpack's prod build (they are not using CRA). I think if CRA can create a sane default with this plugin, it can be the example config for those people.

The alternative are using http://fuse-box.org/. And use https://github.com/fuse-box/react-example If you care about build speed.

In my experience, porting CRA with custom NODE_PATH to it kinda consuming, they use ~ for absolute imports.

gaearon commented 7 years ago

How about enabling DLL plugin?

In my experience it's super complicated to configure, but if you can get it working well, send a PR.

crobinson42 commented 7 years ago

Wonder if this is going to help things speed up a bit? https://groups.google.com/forum/?utm_source=javascriptweekly&utm_medium=email#!msg/v8-dev/YXpjhVeHlbI/iiYlrF8vCgAJ

kylehotchkiss commented 7 years ago

Hi, Just saw this ticket today along with Pinterests newly open-sourced multithreaded eslint and thought it might be relevant here:

https://medium.com/@Pinterest_Engineering/introducing-esprint-a-fast-open-source-eslint-cli-19a470cd1c7d

alex-pex commented 7 years ago

The alternative are using http://fuse-box.org/. And use https://github.com/fuse-box/react-example If you care about build speed.

I know create-react-app doesn't expose Webpack to allow tool switching. Do you plan to experiment FuseBox any time soon?

viankakrisna commented 7 years ago

@alex-pex I think I've put a link to a CRA fork ( / rewrite?) using fuse box somewhere in this repo. Curious how much improvements they have made right now.

alonbardavid commented 7 years ago

Trying to find a solution (or at least the problem) for this. So far for anyone interested:

I've managed to easily replicate it by using the https://github.com/marmelab/admin-on-rest-demo repository - it takes me about 30 seconds to build on an dell xps 15 (Intel Core i7-6700HQ 4-core 2.6 ghz) on windows- I'm guessing it will be the same on linux/macOS.

By using V8-profiler, I've created a cpu-profile file for the webpack build phase (which takes 99% of the time of the build script). It's attached here cra-build-webpack-compile.zip .

It can be loaded into chrome's profiler to show a flame-tree and such.

I'm putting this here for posterity, but looking at the flamechart it doesn't seem to me like there is an obvious candidate that can be optimized, maybe someone else would have a different insight.

Not sure how to move further here, it seems the only reasonable way forward is to start removing plugins/loaders and see if anything causes a massive reduction in build time.

Just an aside, the build time makes it impossible for me to run CRA build script on azure's kudu build system since it consistently hits the timeout, I'm sure this happens in other CI and CD systems.

ivosabev commented 7 years ago

It takes about 48 seconds on my Mac with 2.3 GHz Intel Core i7 + 16 GB 1600 MHz DDR3.

p3nGu1nZz commented 7 years ago

running your code and builds on a separate partition with SSD helps alot. Especially within windows environments. Your partition you use for your code set a very large block size. This helps speed up caching when you have lots of files. Disabling virtual memory, and shadow copies in windows helps alot.

as for the build process itself, webpack i found is slower then when i run within gulp and browserify. only lint and pretty your code when you go to stage it. Disable this for when you are doing local dev builds.

another thing i do is having a terminal open that is always building a production dist when im runing hot deployment in dev mode. i have this process hooked into certain workflow events, like after i do a new dev build or after it finished building.

Anyways these suggestion may or may not work for you. This is just stuff i found that helps speed up my commit turn around time.

GLHF;

gaearon commented 6 years ago

I'm going to close this as there's not much we can do on our side. Webpack has been doing some improvements to the build time so we will pick them up as we update. If you have specific traces you want to share, please file them with webpack instead.