react-redux-universal-hot-example icon indicating copy to clipboard operation
react-redux-universal-hot-example copied to clipboard

Webpack incremental builds are slow

Open quicksnap opened this issue 9 years ago • 112 comments

On my machine, incremental builds in dev mode take anywhere from 1.5s - 5s.

I'm going to spend some time toying with webpack to see what's up, but I'd appreciate anyone else's ideas on what's going wrong.

quicksnap avatar Nov 25 '15 21:11 quicksnap

I'm able to drop the rebuild time significantly without bootstrap/font-awesome loaders in the main entry. Going to look into splitting it into a separate chunk.

quicksnap avatar Nov 25 '15 22:11 quicksnap

Sounds great!

trueter avatar Nov 26 '15 00:11 trueter

I'm getting slow build time as well. Looking forward to your split set up.

wwwfreedom avatar Nov 26 '15 02:11 wwwfreedom

I am the same. it happened looks like webpack-hot-middleware didn't work.

luankefei avatar Nov 26 '15 16:11 luankefei

@quicksnap if you set your devtool to inline-eval-cheap-source-map in dev.config.js i've noticed around 75% speed improvement on rebuilds, 10% improvement on initial builds. there's some discussion around why source mapping is expensive in recent versions, and it looks like it might be due to css-loader's implementation of css modules. you may also want to upgrade node-sass to 3.4.x. looks like the example project still has 3.3.3 which @phoenixmatrix identified as having poor performance: https://github.com/jtangelder/sass-loader/issues/176

bdefore avatar Nov 26 '15 16:11 bdefore

If I'm not mistaken, PR #614 upgraded node-sass to ^3.4.2.

cjhveal avatar Nov 26 '15 21:11 cjhveal

Dupes #594

erikras avatar Nov 27 '15 12:11 erikras

Weird.. I thought I commented a reply to @bdefore:

Modifying or even removing the devtool doesn't do much for me. In my case, it's nearly all time due to the bootstrap-loader plugin. When I remove that, my rebuild time drops from ~4000ms to <500ms.

It would be nice to understand exactly what is going on. I tried digging into the plugin itself, but any modifications I made would not yield positive results, other than causing it not to generate the SASS file which @imports all the bootstrap stuff.

I have a feeling it's not properly caching due to its usage of a pitch loader. I'm not sure though, and it's tough to get help or even form an educated question.

Personally, I may just remove bootstrap loader and use a static build of bootstrap. I'm not sure the best route for this project.

Would love it if someone could see why bootstrap-loader isn't caching on rebuilds. Or anything to drop rebuild times <1000ms

quicksnap avatar Dec 01 '15 01:12 quicksnap

Perhaps it's simply that bootstrap generates a ton of CSS, and css-loader chokes on that.

I will try bypassing css-loader for bootstrap and see what happens.

quicksnap avatar Dec 01 '15 01:12 quicksnap

I don't know much on bootstrap-loader, but saw this since i got tagged on it. Its possible what's below is irrelevant, but I'll pitch it in anyway. Though it sounds like its just the loader not caching, as as mentioned.

I dont know what boostrap loader does, but do keep in mind that SASS doesn't get incrementally compiled the same way JS does. If you require(...) SASS, it creates a css "entry point" so to speak, but if inside that SASS, you @import other stuff, that's all part of the same "sass build". Sass builds are not incremental, and all SASS within a single "entry point" will get recompiled every time.

node-sass <3.4 is slow, and css-loader after 0.14.5 is BRUTALLY slow (to the point of being unusable). Since all of your CSS may get recompiled if its all in the same CSS entry point, you can quickly end up in CSS builds that take longer than rebuilding your entire JS from scratch, even though you only added 1 character to 1 CSS file.

Note that splitting your CSS by requiring it from JS isn't always a good answer in SASS because of the lack of @import (reference) like LESS does...you may end up duplicating a lot of stuff if you're not careful.

tl;dr: CSS builds using the @import mechanic are not incremental and cause a full rebuild of that part. You probably want a static bootstrap build, and @import only variables and mixins as need be (but nothing else!)

Phoenixmatrix avatar Dec 01 '15 02:12 Phoenixmatrix

@Phoenixmatrix thanks. The problem with this setup is that whenever we change any of our JS files, it triggers an entire rebuild, including the CSS. I could not figure a way to tell webpack not to rebuild bootstrap-sass every time. It is doing so here: https://github.com/erikras/react-redux-universal-hot-example/blob/master/webpack/dev.config.js#L54

I tried splitting out into a different chunk, but no luck. My webpack chops are mediocre.

I'm tooling around with bootstrap-sass-loader code now, but I still am not entirely sure where the slowness is being generated.

quicksnap avatar Dec 01 '15 02:12 quicksnap

Yeah, i realized that afterward rereading your comment. Whoops! For sure upgrading to node 3.4 should speed that up since compiling bootstrap shouldn't take very long at all, but obviously that only fixes symptoms (did you know node-sass is like 2-3 times faster on Linux than MacOSX? fun stuff).

Will take a look at the bootstrap sass loader when I get the chance.

Phoenixmatrix avatar Dec 01 '15 02:12 Phoenixmatrix

Thanks for helping out! Appreciate it.

Be sure to change the devtool to something fast like inline-eval-cheap-source-map. I forgot to do that and it was screwing up my benchmarks.

quicksnap avatar Dec 01 '15 02:12 quicksnap

Ok! I just changed devtool to inline-eval-cheap-source-map, and then edited bootstrap-sass-loader to this: https://github.com/quicksnap/bootstrap-sass-loader/commit/6e60e0f0bb1e19d727cd53cab5aa6fbc565c4124 (switch out css-loader for raw-loader)

This significantly speeds things up for me.

quicksnap avatar Dec 01 '15 02:12 quicksnap

I think it still would be an even better improvement if we could get webpack to avoid rebuilding bootstrap unless the bootstrap config file changes.

quicksnap avatar Dec 01 '15 02:12 quicksnap

Yeah, so obviously that part is still broken. But also, yet another reason css-loader needs to be fixed. Its so completely broken performance wise right now, as per https://github.com/webpack/css-loader/issues/124

In our codebase its unusable (css build takes minutes, so we have to use raw-loader)

Phoenixmatrix avatar Dec 01 '15 02:12 Phoenixmatrix

I hope it is improved by the time our css grows. I really like CSS Modules...

quicksnap avatar Dec 01 '15 07:12 quicksnap

@quicksnap seems like you're suggesting to avoid bootstrap-sass-loader? That seems to be the bottleneck?

mmahalwy avatar Dec 01 '15 16:12 mmahalwy

i had a chat with the shakacode folks this morning and discovered that bootstrap-sass-loader is being rewritten and will soon be deprecated. the rewritten version is here, though it hasn't been touched in a couple weeks: https://github.com/shakacode/bootstrap-loader/tree/alex/bootstrap-4

bdefore avatar Dec 01 '15 16:12 bdefore

@mmahalwy I'm not recommending avoiding it--I'll try to issue a PR to bootstrap-sass-loader soon. The change is minor. I don't see any problems using raw-loader over css-loader in bootstrap-sass-loader.

quicksnap avatar Dec 01 '15 18:12 quicksnap

Raw loader will not rewrite image and font URLs if you hash them. I don't know if it affects bootstrap in any way.

On Tue, Dec 1, 2015, 1:24 PM Dan Schuman [email protected] wrote:

@mmahalwy https://github.com/mmahalwy I'm not recommending avoiding it--I'll try to issue a PR to bootstrap-sass-loader soon. The change is minor. I don't see any problems using raw-loader over css-loader in bootstrap-sass-loader.

— Reply to this email directly or view it on GitHub https://github.com/erikras/react-redux-universal-hot-example/issues/616#issuecomment-161054432 .

-Francois Ward

Phoenixmatrix avatar Dec 01 '15 18:12 Phoenixmatrix

@Phoenixmatrix good point. I'll check on that, but I have a feeling it could cause issues now.

quicksnap avatar Dec 01 '15 18:12 quicksnap

I'll also look into passing params to css-loader to disable some things, or to downgrade css-loader in that repository.

quicksnap avatar Dec 01 '15 18:12 quicksnap

Or, having css-loader be a peer dependency.

quicksnap avatar Dec 01 '15 18:12 quicksnap

@quicksnap: I tried splitting out into a different chunk, but no luck. My webpack chops are mediocre.

What was the reason you gave up on this route? Having bootstrap outside the main chunk might circumvent the recompile issue.

trueter avatar Dec 02 '15 19:12 trueter

@trueter yes--I couldn't figure how to prevent bootstra-sass-loader from being triggered every rebuild. I did get it into a separate chunk successfully, but it would always rebuild all chunks AFAIK (it would say 'emitted' next to the vendor chunk I created).

quicksnap avatar Dec 02 '15 21:12 quicksnap

@quicksnap any luck on this so far?

mmahalwy avatar Dec 04 '15 08:12 mmahalwy

@mmahalwy I haven't messed with adjusting bootstrap-sass-loader's properties yet. I'm also not sure if bootstrap-sass has any image URLs in it, so it may actually be good with raw-loader, which would be hella faster.

I'm working on stuff right now that doesn't involve dev mode, but next time I get hit with a 4sec rebuild I'll probably dig in.

quicksnap avatar Dec 04 '15 21:12 quicksnap

@quicksnap what's your build time now? I've just launched this example and it takes 3.5-5 sec for me for each build... it really slows down development..

Did you figure out how to speed it up?

sars avatar Dec 12 '15 23:12 sars

@quicksnap could you create a pr with your code split work in progress? stumbled across this: http://tech.trivago.com/2015/12/15/parallel-webpack/

trueter avatar Dec 15 '15 18:12 trueter