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: Webpack Performance Budgets #3216

Closed
addyosmani opened this issue Oct 31, 2016 · 83 comments
Closed

RFC: Webpack Performance Budgets #3216

addyosmani opened this issue Oct 31, 2016 · 83 comments

Comments

@addyosmani
Copy link

@addyosmani addyosmani commented Oct 31, 2016

Webpack version:
1.10.x and 2.x

Please tell us about your environment:
OSX 10.x / Linux / Windows 10 [all]

Expected/desired behavior:

Highlight at build-time any JavaScript chunks or bundles that are over a size threshold and can negatively impact web performance load times, parse/compile and interactivity. A default performance budget could indicate if total chunk sizes for a page are over a limit (e.g 250KB).

main-proposal

I'd love to see if we could make this a default and offer a config option for opting out 🏃‍♀️ Concern with an opt-in is the folks with the worst perf issues may not know to enable it or use this via a plugin if this suggestion was deferred to one. These folks may also not be testing on mobile devices.

Optionally, highlight where better performance patterns might be helpful:

second-proposal

Current behaviour:

Many of the apps bundled with Webpack that we trace ship a large, single bundle that ends up pegging the main thread and taking longer that it should for webapps to be interactive:

screen shot 2016-10-28 at 1 38 32 pm

This isn't Webpack's fault, just the culture around shipping large monolithic bundles. This situation gets particularly bad on mobile when trying these apps out on real devices.

If we could fix this, it would also make it way more feasible for the Webpack + React (or Angular) stacks to be good candidates for building fast web apps and Progressive Web Apps 🔥

What is the motivation / use case for changing the behavior?

I recently dove into profiling a large set (180+) React apps in the wild, based on 470 responses we got from a developer survey. This included a mix of small to large scale apps.

I noted a few common characteristics:

  • 83+% of them use Webpack for module bundling (17% are on Webpack 2)
  • Many ship large monolithic JS bundles down to their users (0.5-1MB+). In most cases, this makes apps interactive in well over 12.4 seconds on real mobile devices (see table 1) compared to the 4 seconds we see for apps properly using code-splitting and keeping their chunks small. They’re also far slower on desktop than they should be - more JS = more parse/execution time spent at a JS engine level.
  • Developers either don’t use code-splitting or use it while still shipping down large chunks of JS in many cases. More on this soon.

Table 1: Summary of time-to-interactive scoring (individual TTI was computed by Lighthouse)

Condition Network latency Download Throughput Upload Throughput TTI average React+Webpack app TTI smaller bundles + code-splitting
Regular 2G 150ms 450kbps 150kbps 14.7s 5.1s
Regular 3G 150ms 1.6MBPs 750kbps 12.4s 4s
Regular 4G 20ms 4MBPs 3MBPs 8.8s 3.8s
Wifi 2ms 30MBPs 15MBPs 6s 3.4s

We generally believe that splitting up your work into smaller chunks can get you closer to being interactive sooner, in particular when using HTTP/2. Only serving down the code a user needs for a route is just one pattern here (e.g PRPL) that we’ve seen helps a great deal.

Examples of this include the great work done by Housing.com and Flipkart.com. They use Webpack and are getting those real nice numbers in the last column thanks to diligence with perf budgets and code-splitting 👍.

What impacts a user's ability to interact with an app?

A slow time to being interactive can be attributed to a few things:

  1. Client is slow i.e keeping the main thread busy 😓 Large JS bundles will take longer to compile and run. There may be other issues at play, but large JS bundles will definitely peg the main thread. Staying fast by shipping the smallest amount of JS needed to get a route/page interactive is a good pattern, especially on mobile where large bundles will take even longer to load/parse/execute/run
  2. Server/backend may be slow to respond
  3. Suboptimal back and forth between the server and client (lots of waterfall requests) that are a sequence of network busy -> CPU idle -> CPU busy -> network idle and so on.

If we looked at tools like performancebudget.io, targeting loading in RAIL’s <3s on 3G would place our total JS budget at a far more conservative 106KB once you factor in other resources a typical page might include (like stylesheets and images). The less conservative number of 250KB is an upper bound estimate.

Code-splitting and confusion

A surprising 58%+ of responders said they were using code-splitting. We also profiled just this subset and found that their average time to being interactive was 12.3 seconds (remember that overall, the average TTI we saw was 12.4 with or without splitting). So, what happened?

Digging into this data further, we discovered two things.

  • Either folks that thought they were code-splitting actually weren't and there was a terminology break-down somewhere (e.g maybe they thought using CommonsChunkPlugin to 'split' vendor code from main chunks was code-splitting?) 🤔
  • Folks that definitely were code-splitting had zero insight into chunk size impact on web performance. We saw lots of people with chunk sizes of 400, 500...all the way up to 1200KB of script who were then also lazy-loading in even more script 😢

image

Keep in mind: it's entirely possible to ship fast apps using JS that are interactive quickly with Webpack - if Flipkart can hit it in under 5 seconds, we can definitely bring this number down for the average Webpack user too.

Note: if you absolutely need a large bundle of JS for a route/page to be useful at all, our advice is to just serve it in one bundle rather than code-split. At an engine level this is cheaper to parse. In most cases, devs aren't going to need all that JS for just one page/view/route so splitting helps.

What device was used in our lab profiling?

A Nexus 5X with a real network connection. We also ran tests on emulated setups with throttled CPU and network (2G, 3G, 4G, Wifi). One key thing to note is if this proposal was implemented, it could benefit load times for webapps on all hardware, regardless of whether it's Android or iOS. Fewer bytes shipped down the line = a little more ❤️ for users data plans.

The time-to-interactive definition we use in Lighthouse is the moment after DOMContentLoaded where the main thread is available enough to handle user input . We look for the first 500ms window where estimated input latency is <50ms at the 90th percentile.

Suppressing the feature

Users could opt-out of the feature through their Webpack configuration (we can 🚲 🏠 over that). If a problem is that most devs don't run their dev configs optimized for production, it may be worth considering this feature be enabled when the -p production flag is enabled, however I'm unsure how often that is used. Right now it's unclear if we just want to define a top-level performanceHints config vs a performance object:

performance: {
   hints: true,
   maxBundleSize: 250,
   warnAtPercent: 80
}

Optional additions to proposal

Going further, we could also consider informing you if:

  • You weren’t taking advantage of patterns like code-splitting (e.g not using require.ensure() or System.import()). This could be expanded to also provide suggestions on other perf plugins (like CommonChunksPlugin)
  • What if Webpack opted for code-splitting by default as long as you were using System.import() or require.ensure()? The minimum config is just the minimum requirements aka the entry ouput today.
  • What if it could guide you through setting up code-splitting and patterns like PRPL if it detected perf issues? i.e at least install the right Webpack plugins and get your config setup or point you to the docs to finish getting setup?

Thanks to Sean Larkin, Shubhie Panicker, Gray Norton and Rob Wormald for reviewing this RFC before I submitted it.

@rryter
Copy link

@rryter rryter commented Oct 31, 2016

I like the idea very much. And I would like to stress that depending on the situation the performance budget could be 500KB or maybe just 100KB. This way people can set their perfomance budget and they will be notified as soon as they come close to the limit. Maybe already notify them when they are at about 80% of the budget.

@mxstbr
Copy link
Contributor

@mxstbr mxstbr commented Oct 31, 2016

Love it!

Just wanted to note a nitpick: I'm red-green colorblind, and have a really hard time seeing the difference between the green and the yellow above. Would be great to have some more-different colors there!

@addyosmani
Copy link
Author

@addyosmani addyosmani commented Oct 31, 2016

Just wanted to note a nitpick: I'm red-green colorblind, and have a really hard time seeing the difference between the green and the yellow above. Would be great to have some more-different colors there!

More than happy for us to figure out an alternative color scheme :) Also, glad you like the proposal!

@NekR
Copy link

@NekR NekR commented Oct 31, 2016

Great work @addyosmani (and your team)!

@rryter I can imagine people setting 5MB perf budget, this just doesn't change anything from what it's now. People just assume "this is okay". Performance is the same for everyone and we should be hard about pointing into it, instead of allowing incremental escapes: "Oh, I'll add another 100KB budget because I need this lib right now." -- three months later -- "Oh, it's 3MB bundle know 😱".

@kostasmanionis
Copy link
Contributor

@kostasmanionis kostasmanionis commented Oct 31, 2016

Great initiative! A few thoughts.

Ideally I would like to get feedback on my bundle sizes when in development mode, but like Addy stated - most of us probably don't really do development in production mode. For e.g. I don't use a minifier when in development mode, because it does slow down builds and I like them to be as fast as possible.

But a minfier can shed a lot of code off your bundle, especially with webpack 2 tree-shaking feature. AFAIK webpack creates dead code, that's removed during the minfication process. So if I wan't to get an accurate idea of what my bundle size is, I need to minify my code.

Oh and there's gzip too...

@kenwheeler
Copy link

@kenwheeler kenwheeler commented Oct 31, 2016

👍

This is awesome. I would love to see more optimization warnings like this, things like how much savings you're getting from tree shaking and how much more you could save, so that devs would have a path for reducing those bundle sizes. Projected production metrics while in dev mode would be dope too.

@asolove
Copy link
Contributor

@asolove asolove commented Oct 31, 2016

Lots of excellent ideas here and I'm excited for the possibilities.

I just want to remind everyone that for the 1% of people who have super-advanced configs, and the 19% of people who have done the config themselves, there's a much more important 80% of people who hardly think about webpack at all and are shipping apps with the default settings they found in some blog post. Tree-shaking and code-splitting might eventually help them, but they have other work to do first.

I would therefore ponder what are the simplest, easiest-to-get-wrong things we could warn them about. These are probably things people remotely familiar with webpack would never do, and so they likely aren't on the top of our minds. Some examples:

  • Inline source maps in production build
  • Doesn't use uglifyjs in production build
  • Doesn't create a DefinePlugin for process.env==='production'

Unlike tree-shaking and code-splitting, which may require difficult code changes to work well, these are very simple changes anyone can make and get an immediately benefit. And helping non-experts get easy wins ("Wow, I paid attention to this and reduced my load time by half!") might be a great way to get them excited about worrying about performance more regularly. (I can see a future where, after webpack sees them respond to these initial problems and get a win, it links them to lighthouse or some other tool where they can learn more about performance practices.)

A lot of the biggest-impact checks should only run in a production build. Which raises another question: since production builds may only run in CI or on a build server, where people rarely look at the logs, should obvious problems like this return an exit code? It could prompt the developer to either fix the problem or modify their performance options to accept the issue.

@rryter
Copy link

@rryter rryter commented Oct 31, 2016

@NekR It depends on what the target audience is. Also if you want to achieve a goal lower than the 250KB, let's say 100KB, that should be configurable. Having a 250KB performance budget or no budget at all isn't going to cut it. I do agree that this is a solid default value though.

@NekR
Copy link

@NekR NekR commented Oct 31, 2016

@kostasmanionis

Oh and there's gzip too...

While download time is important, most of the problems is executing/parsing the script which is used in a full size regardless how hard you compress it with gzip.

But yeah, I agree to it should be measured against production builds but somehow visible in dev builds too..

@asolove that sounds good, but problem is that it's hard to know if it's a production build or not, i.e. I rarely see people use -p CLI option and there is actually no way to tell about production intentions when you use webpack's Node API.

@YurySolovyov
Copy link

@YurySolovyov YurySolovyov commented Oct 31, 2016

Any tips for configuring/integrating with popular routing solutions like react-router ?

@peter-mouland
Copy link

@peter-mouland peter-mouland commented Oct 31, 2016

Hi great idea and discussion started here.

Does it sound like and idea to try and get prod and Dev configs into a single file?

Const config = {
  ...common,
 Dev:{ 
     ....overrides
 },
 Production : {
    ...overrides
 }

Where Dev and production match node_env?

These configs could still be split into separate files to help readability if needed.

Just an idea of the top of my head to try and solve the 'webpack is unaware of pros vs Dev bike config' problem.

@kennetpostigo
Copy link

@kennetpostigo kennetpostigo commented Oct 31, 2016

It may be good to add a "How to implement PRPL Pattern in Webpack 2" guide in the webpack docs. Mostly so that those messages from oversized chunks can link to it.

@TheLarkInn
Copy link
Member

@TheLarkInn TheLarkInn commented Oct 31, 2016

It may be good to add a "How to implement PRPL Pattern in Webpack 2" guide in the webpack docs. Mostly so that those messages from oversized chunks can link to it.

@kennetpostigo, we are in need of, and would openly welcome any PR's on our new docs repo for an article like this.

@MarkPieszak
Copy link

@MarkPieszak MarkPieszak commented Oct 31, 2016

👍 Love the idea Addy, especially the ability to opt-out, but I can imagine most performance junkies would want every bit of info to get them "chunking" in the right direction.

@bebraw
Copy link
Contributor

@bebraw bebraw commented Oct 31, 2016

Does it sound like and idea to try and get prod and Dev configs into a single file?

You can already achieve that using an external solution. I wrote webpack-merge to cover that need and you can find a plenty of other flavors with a bit of digging. I'm not sure if something like this belongs to webpack core, though. Maybe better leave to user space. 👍

@jouni-kantola
Copy link

@jouni-kantola jouni-kantola commented Oct 31, 2016

If the goal here is to create tooling for making it easier for developers to understand when they affect the end-user in a negative way, I'd say it would help and be informative to clearly display when a chunk will be (and therefor should be) cache busted. This would hopefully make developers think one moment extra before pulling that nice to have lib into the vendor bundle.

@TheLarkInn
Copy link
Member

@TheLarkInn TheLarkInn commented Oct 31, 2016

@jouni-kantola I believe that indicate warnings when a vendors chunk hash has changed its actually a great idea. Secondary to the aforementioned. But extrenely beneficial in my opinion.

@addyosmani
Copy link
Author

@addyosmani addyosmani commented Oct 31, 2016

@kostasmanionis There are a few ideas we could tease out here.

During production, once tree-shaking/minification/other optimizations have been applied, I think that’s a good point to enforce a performance budget and provide insight into chunk and bundle sizes. (I’ve seen few folks use -p however so we might want to think about dev some more)

During dev is a good time to be reminded if you’re on the right path, but I imagine we would want to do this in a way that’s useful but not annoying. E.g we could inform you if you’re not code-splitting, but could also just do it once or provide a way to dismiss the tip if it’s intentional.

@asolove

What did you think of the idea of informing users about bundle sizes and trying to think about getting them smaller?

I just want to remind everyone that for the 1% of people who have super-advanced configs, and the 19% of people who have done the config themselves, there's a much more important 80% of people who hardly think about webpack at all and are shipping apps with the default settings they found in some blog post. Tree-shaking and code-splitting might eventually help them, but they have other work to do first.

For sure. I think you’re right that for the long tail there’s going to be a complexity trade-off to consider and lower hanging fruit is always good. I would love for us to consider code-splitting be mentioned in warnings just to increase awareness as it is pretty core to the slowness problems we’re seeing (even if they do look at inline source maps and uglify in prod builds earlier on, which are great things to call out). Maybe we could come up with some nice UX that presents suggestions in terms of effort? e.g [easy, medium, hard].

A lot of the biggest-impact checks should only run in a production build. Which raises another question: since production builds may only run in CI or on a build server, where people rarely look at the logs, should obvious problems like this return an exit code? It could prompt the developer to either fix the problem or modify their performance options to accept the issue.

Imo, defaulting to an exit code with perhaps an option to switch off would be flexible enough for folks?

@YurySolovyov

Any tips for configuring/integrating with popular routing solutions like react-router

I tried walking through Webpack perf patterns with React router in part 2 of this PWA series, but there’s been lots of write-ups about code-splitting with React Router by others.

With respect to performance insights with Webpack + the router, I haven’t personally seen anything like that just yet. I’ve had to use a source map analyzer to get useful insights on that in the past.

@leecade
Copy link

@leecade leecade commented Nov 1, 2016

I am planning a new project to separate the source code and build environment to keep optimization strategy ongoing.

https://github.com/leecade/fe

@vigneshshanmugam
Copy link
Contributor

@vigneshshanmugam vigneshshanmugam commented Nov 1, 2016

Trying out some of the idea expressed here as a plugin - https://github.com/vigneshshanmugam/perf-hints-plugin/... Just set it up, but would be easy to get to integrate lighthouse and suggest all the endless possibilities in Performance tuning.

/cc @addyosmani @TheLarkInn

@mauricedb
Copy link

@mauricedb mauricedb commented Nov 1, 2016

Great suggestion from @addyosmani 👍

In my experience developers rarely do production builds. These production build are typically done on the CI server where developers don't look at the log unless there is an issue. So I would enable this for all builds even though for development builds the artifacts will be larger. Maybe the threshold should be increased there before producing warnings. In a production build on the CI server I would like this by default fail the build. If we just print a warning to the log this will mostly go unobserved.

@peter-mouland
Copy link

@peter-mouland peter-mouland commented Nov 1, 2016

I'm a bit concerned a few people are saying dev's rarely do production builds. As a rule I always run e2e tests on production code on a pre-push hook. If the argument is that e2e tests take too long, then run a sub-set just to at least make sure the app can be run at least... but i digress!

This does highlight use cases though. Using webpack to :

  • Build and test prod locally
  • Build and test prod in CI
  • (and possibly) do a first build of prod code in prod(!)

I wouldn't like to see these hints on dev code, unless they are accurately adjusted to take the dev vs prod config into account. But, I can't see how this could be accurately achieved; and if it is not accurate, it will get ignored. (e.g. is the budget on dev is 1.2mb instead of 200k??)

How do we want webpack to behave:

  • Will performance hints always be invoked or only for prod builds (i.e. -p)?
  • Should the build fail if the hints config and the performance budget is breached?

Considering writing hints against dev code will be an inaccurate comparison for prod, I think we can ignore non-prod setup. All webpack can do is highlight in the docs how important testing prod code is and how great -p for improving prod code. Applying this to the use-cases mentioned above means that I (with my local e2e tests) and @mauricedb (with prod built in CI) are both informed as soon as possible with failing tests. People with their first prod build in prod can the change the hint from error to warn behaviour if they wish.

So tl;dr: Ignore dev-builds and only use the hint config for production (-p). By default, the build should fail with errors if the performance budget rules aren't met. This fail/warn behaviour should also be configurable.

@mauricedb
Copy link

@mauricedb mauricedb commented Nov 1, 2016

While I agree with @peter-mouland that developers should test locally against production build I am afraid that this is not the reality for quite a number of developers.

Yes there are plenty of developers doing the right thing. They have CI servers set up and think about these things. However with the Angular CLI, Create-React-App and similar you will see plenty of developers using Webpack who are not as good and don't follow best practices. IMHO these are far more common and are the category that need far more guidance.

Personally I would consider these developers as a far more important audience for a automatic performance budget.

@grgur
Copy link

@grgur grgur commented Nov 1, 2016

This is spectacular! Looking forward to giving it a spin. 🙌

Just as food for thought, I see performance in two ways:

  • perf affecting end users, and
  • perf affecting developers

I'm thinking developers should also be able get insight into build speed performance. E.g.

  • How much time it took to build a chunk
  • How fast are plugins, loaders, devtool, etc. performing
  • Possibly (omg, this sounds like rocket science) calculate code overlap (e.g. bundled style duplications, common code that should be chunked out, etc)

I understand that some of this can be obtained with a bit more digging, but now that we're talking... 😉

@addyosmani
Copy link
Author

@addyosmani addyosmani commented Dec 19, 2016

Thanks for the continued feedback, folks. It's a relief to see mostly positive feelings about the feature :) I think you're right that there may be more we can do to improve the UX/noise during dev mode. Let's keep kicking around ideas. @TheLarkInn and I have started thinking about this too.

One challenge that might be interesting to brainstorm for is how to reliably detect dev mode. Most folks rarely seem to use -d. As Sean's pointed out on another thread, other than checking for use of webpack dev server or HMR, inferences are going to be tricky. Do folks have other suggestions for how we might go about doing that?

@Southpaw17
Copy link

@Southpaw17 Southpaw17 commented Dec 21, 2016

Is this a problem that can just be solved by documentation? The -p flag implies certain meaning (e.g. enables minification, enforce performance budget, etc) and the -d flag implies similar things (no minification, disable performance budget). Both of these can be mimicked by writing your configuration in a certain way, just like performance.hints = true/false.

Having clear documentation about how to enable/disable the feature should go much further (and cause fewer Issues) than trying to intelligently determine if the feature should be enabled or not based on whether webpack-dev-server/HMR/whatever is enabled.

It might be beneficial to add a line in the output explaining how to disable the feature if it's enabled by default or a line about how to enable the feature if it's disabled by default so that when someone does eventually copy/paste from an online tutorial there is at least an advertisement about the feature

@cesarandreu
Copy link
Contributor

@cesarandreu cesarandreu commented Dec 21, 2016

I don't think this having this enabled for the development environment is constructive. I'm using unminified source files, so it's obvious the size will be huge. I literally can't do anything about it, except disable it. The warning isn't actionable. If warnings are not immediately actionable they'll just end up being ignored. That makes me think it's not a good default.

Just pulling in react and react-dom will push you up to ~750KB. Pulling in one of webpack user's most popular libraries is enough to push you almost three times over the limit. Using ace editor? If I recall correctly, pulling in brace will bump your bundle size by 600KB.

I'm worried this is going to be very demotivational for people picking up webpack for the first time. They'll use create-react-app and immediately get a bunch of warnings without having done anything. That's not doing webpack's UX any favors.

I think the 250KB default is unrealistic for many teams and developers, considering the current state of the ecosystem. This seems to assume that everyone is targeting mobile, which I'd wager is not the case for many web developers. Many complex web apps don't target mobile at all. What if I'm just creating a test bundle? There's many situations in which generating a larger bundle is okay.

My preference would be to have this disabled completely until there's better documentation and examples available. I'm not aware of any examples that showcase a fully-featured production setup. Getting everything setup and working correctly across environments (dev, testing, building) while combining the use of multiple common libraries is very tricky to get right.

@addyosmani
Copy link
Author

@addyosmani addyosmani commented Dec 21, 2016

I don't think this having this enabled for the development environment is constructive. I'm using unminified source files, so it's obvious the size will be huge. I literally can't do anything about it, except disable it. The warning isn't actionable. If warnings are not immediately actionable they'll just end up being ignored. That makes me think it's not a good default.

👍 I think there's general agreement that having the feature enabled during the dev lifecycle offers less value than production (unless you're increasing budgets specifically for dev). I'm strongly in favor of exploring whether we can improve this UX while maintaining the feature as a default for production. Definitely want to ensure folks get the most use out of budgets rather than it being unactionable.

I think the 250KB default is unrealistic for many teams and developers, considering the current state of the ecosystem. This seems to assume that everyone is targeting mobile, which I'd wager is not the case for many web developers. Many complex web apps don't target mobile at all. What if I'm just creating a test bundle?

I think there's room to increase the default budget and we're conducting performance research studies right now to establish what a better baseline is. It may end up being 300-400KB (MBs generally = taking multiple seconds before you're interactive, even on desktop :/). Although the default budget is always going to be lower, I'd like to see if we can make it even easier (via docs or otherwise) to configure the budget for your own needs. There's never going to be a single number that captures both desktop and mobile for all of Webpack's users, but I think you know best what:

  • Devices
  • Network conditions

your users have and can adjust those accordingly (the feature is configurable). In the future, we might build out budgets so that they're device specific (e.g targeting desktop? Have a wayyy large budget. targeting mobile? smaller).

There's many situations in which generating a larger bundle is okay.

Definitely. You might be building a POC of something and aren't going to care as much about production budgets. That's where I'd just manually disable the feature and not look at it again until I was trying to properly do a version that'll be deployed to real users.

My preference would be to have this disabled completely until there's better documentation and examples available.

Respectfully, I'd like to see if we can provide a way to hint or deterministically guess whether a configuration is dev or prod and enable/disable the feature accordingly without disabling the feature. The biggest perf offenders on the web today (desktop and mobile) are folks that have no insight into their bundles being too large at all. It's not their fault, but these folks need help and aren't going to go reading docs if they aren't aware their bundles are a problem.

I know it's going to take a bit to get the UX for this improved.

We've profiled 1000s of apps using Webpack in production. The latest numbers suggest folks are shipping well over 800KB (gzipped) of script for their bundles and I often see folks shipping well over 2-3MBs without realizing this is an issue. It's really not a mobile-only thing. If you're shipping multiple megs of script on desktop, that's going to keep the main thread busy parsing and evaluating code far longer than it likely needs to be.

If we can get to a good place where 1. this feature is less noisy/not active during dev, 2. budgets are a little better tweaked and 3. docs on usage are where they need to be we'll hopefully have a feature that does fit in more naturally into folks workflows.

@cecilemuller
Copy link

@cecilemuller cecilemuller commented Dec 21, 2016

About the phrasing itself, how about using the resulting filesize to show how long it would take to download on a slow connection ? Like "X Mb would take Y minutes to download on a 3G connection" is a straightforward way to onboard developers to reduce the filesize.

@TheLarkInn
Copy link
Member

@TheLarkInn TheLarkInn commented Dec 21, 2016

This is causing such a tumultuous inner turmoil (over-exaggerating) for me in the direction of this featurex. I have a few conflicting views/opinions.

It really is spammy and not accurate for dev env

This makes sense to me, even working on it myself, and even though it could help me catch size bloat early on in bundles, I can only imagine what this is like jumping in a legacy application etc.

We should really be advocating for better web performance.

We as an organization are really gravitating to the center of 80-90% of tooling for web application development. Stats like "50% of people bounce a mobile page when it takes longer than 3 seconds to load" make me think, "OMG such a great opportunity to increase the awareness across the board and really help people".

Can we do both, but create a really easy path to turn off the feature?

What if we provided very clear and easy steps (terminal command), or URL to docs page showing exactly how to turn off feature for development environments?

I really really want people to at least know and see the warning at least once, and if they never want to see it again, then we can at least have the assurance that we did what we could to better advocate pushing web performance and awareness together.

And then we can give a direct link to https://webpack.js.org/configuration/performance/#performance-hints with even a specific hint.

@bjornstar
Copy link

@bjornstar bjornstar commented Dec 22, 2016

I'd much rather have this as a tool I can use to optimize my builds for performance when I am ready to do that.

To get an app booting and functioning is frustrating enough without getting constant warnings about your app being suboptimal. I already know my app is suboptimal, I just started making it. It doesn't have to be optimal, it has to work.

The first time I saw this warning, I didn't want to optimize my build, I just wanted to make the warning go away. I'm sure it's going to be useful when I want to optimize my build, but I just need my app to work and for Webpack to get out of the way.

This feels like the Webpack equivalent of Clippy:

I see you're trying to build without code-splitting, did you know that code-splitting is great? You should totally do it!

@ZenSoftware
Copy link

@ZenSoftware ZenSoftware commented Dec 28, 2016

I think all of us see the value that this feature is trying to bring to the table and will find it very useful for production configurations. Although, it would be much better if it was opt in, instead of opt out.

Really I think what the community is shouting about, is our concern for the cleanliness of the output of webpack. Some of us have very strong feelings about manner in which webpack outputs information by default. It is after all, our most important tool in our tool chains. Many of us believe that the only thing that should be spit out by default, is clean, legible, statistics only. These types of tools are already crowded enough as it is. We just want to reason over clean output… that’s all. Can you imagine if we were the only bundler who managed to get that right?!

The current incarnation of this feature takes up the bottom of the output where far more relevant information could be given to the developer. If we were to treat the developer as a user, the user experience is poor in it's current incarnation.

We should remember that defaults only exist to accommodate for an overwhelmingly commonly used scenario. Just look at the issues related to this topic... The community is making it clear, that in many cases, this is simply unwanted spam.

Fortunately, the solution is simple from here. Turn it off by default. If proponents of this feature are so concerned about advocating this particular max size… they should submit a pull request that implements a complete and robust tree-shaker instead. The truth is that they are not understanding the larger nature of the problem we are trying to solve. It might be worth taking into consideration that this recommendation will become irrelevant as the industry progresses. Computational power will inevitably progress. Why would we ever want to bake all of this irrelevant spam into this magnificent tool by default? History will remember us. But that’s just our opinion ^_^

@ZenSoftware
Copy link

@ZenSoftware ZenSoftware commented Dec 28, 2016

For those that don't realize how nasty the current incarnation of this feature can get... please note that the following only has one offending bundle that goes over the presumptuous max size. It seems that chunks that come after the offending bundle, cascade a whole bunch more warnings for some reason.

We are really not making things up when we say this is spammy. Our company is so sad that this is how our favorite tool behaves by default... >,<

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (250 kB).
This can impact web performance.
Assets:
  vendor.bundle.js (2.93 MB)

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (250 kB). This can impact web performance.
Entrypoints:
  vendor (3.06 MB)
      polyfills.bundle.js
      vendor.bundle.js

  angularjs (3.08 MB)
      polyfills.bundle.js
      vendor.bundle.js
      angularjs.bundle.js

  zen (3.1 MB)
      polyfills.bundle.js
      vendor.bundle.js
      angularjs.bundle.js
      zen.bundle.js

  zenexamples (3.15 MB)
      polyfills.bundle.js
      vendor.bundle.js
      angularjs.bundle.js
      zen.bundle.js
      zenexamples.bundle.js

  signalrmonitor (3.16 MB)
      polyfills.bundle.js
      vendor.bundle.js
      angularjs.bundle.js
      zen.bundle.js
      zenexamples.bundle.js
      signalrmonitor.bundle.js

  zenangularjsexamples (3.16 MB)
      polyfills.bundle.js
      vendor.bundle.js
      angularjs.bundle.js
      zen.bundle.js
      zenexamples.bundle.js
      signalrmonitor.bundle.js
      zenangularjsexamples.bundle.js


WARNING in webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
@TheLarkInn
Copy link
Member

@TheLarkInn TheLarkInn commented Dec 28, 2016

@ZenSoftware we listened as you can see we have turned it off by default. #3604

But as an aside, those warnings are not coming up for no reason. I do not know your business case or user base or device or load time requirements, and I am not responsible for your apps page speed, but FWIW, shipping 3MB of JavaScript is massive and should probably be addressed anyways (if possible). Keep in mind that we originally intended to show these values unminified because it's the parse and eval cost of 3MB (after decompressed) that causes slowdown just as much as download and network speed when it comes to web perf cost, and should be taken seriously.

But as you all have made a great point: none of this is our business and we should be better at making it easy for these things to appear when "you want them to" regardless of the potential impact.

That being said the long term goal is to enable this feature by default in prod (if we can eventually determine this) so we would love great ideas and input on how to implement. For now the only default feature you will see is [big] next to [emitted] indicator

Ref: #3611

@ZenSoftware
Copy link

@ZenSoftware ZenSoftware commented Dec 29, 2016

Alright!!! We are so happy to see that the project is molding itself for the betterment of the community.

@TheLarkInn Yes, it really is an enormous vendor bundle isn’t it? We are effectively trying to build what is an operating system, that runs in a web browser. So you could say we need a couple of 3rd party libraries, haha. When no tree-shaking is done, that’s what ends up happening. It’s really not unique to my project. We all know what's going on here, it's not a secret. The industry has been struggling with this problem since the inception. So that's why we find it strange that the warning is so... obtrusive.

On a side note, can you imagine if GCC v0.9 output something like:

RAM FOR CURRENT COMPUTERS IN THIS ERA ONLY HAVE A LIMIT OF 4096KB
YOUR BINARY IS SO BIG – WOW – REALLY BIG
WE RECOMMEND YOU FIGURE OUT HOW TO REDUCE THE SIZE OF YOUR BUILD
THANKS – GCC – PLEASE CHECK OUT OUR WEBSITE AT www.linuxfoundation.org

It would be so weird if that’s what the original developer of this famous compiler chose to spit out by default. It would make using this legacy compiler… feel dirty. All we are saying is that we are just concerned about the long-term quality of webpack, that’s all. We are so happy that it is moving in the right direction again.

@TheLarkInn
Copy link
Member

@TheLarkInn TheLarkInn commented Dec 29, 2016

Okay that is not only a great point but pretty funny as well. We will keep this thread open for now in case additional feedback is given. Thank you for the support and feedback.

@cecilemuller
Copy link

@cecilemuller cecilemuller commented Dec 29, 2016

Would it also be useful to have a warning for HTML files larger than 14Kb?

@mc-zone
Copy link
Member

@mc-zone mc-zone commented Feb 22, 2018

Hi, @TheLarkInn ! I see your code about the target checking for performance.hints in #3604 and only web and webworker would show size warnings. But looks like it was rewritten and now in master is it WebpackOptionsDefaulter.js#L159, not sure when or for what.

Actually now in my target:node projects using webpack@next I often receive size warning messages but it seems useless. And I prefer to pack all my modules into one bundle than split it separately. Because I think the file size has less effect about some backend target, in other words, using one bundle even reduce I/O times.

If I was not wrong, should we add the target checking back to performance.hints to avoid this? Or should add a new option to performance/SizeLimitPlugin such as includeTarget (in case there are some other places are using performance.hints too)?

I'd like to make a PR if it needed. Just want to make sure which way is right at first.

@lili21
Copy link

@lili21 lili21 commented Aug 17, 2018

is it minified size or compressed size ? Can I configure it to compressed size like gzip ?

@vio vio mentioned this issue Oct 11, 2019
0 of 4 tasks complete
@nilanjansiromani
Copy link

@nilanjansiromani nilanjansiromani commented Nov 2, 2019

@TheLarkInn @addyosmani
Great feature, but is there a way to set budgets for for more than one bundle.
The problem that we faced was we set the budget at 1.5 mb for the biggest bundle,

meanwhile, the two smaller bundles that we had crept on from 350 to 600kb and had no error (because: < 1.5mb)
I understands its a developer's responsibility to to keep an eye, but it would be a great feature to have. (assuming its not there and i am not aware how to implement it.)

@grgur
Copy link

@grgur grgur commented Nov 7, 2019

@nilanjansiromani Give Gimbal a try: https://github.com/ModusCreateOrg/gimbal/
We've had a lot of success using it for performance budgeting. It expands on what Webpack budgets support by utilizing Lighthouse, Axe accessibility checks, memory and CPU budgeting, sourcemap checks, etc.

@Sshuichi
Copy link

@Sshuichi Sshuichi commented Jul 9, 2020

This didn't age well for Flipkart and Housing.com :)

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

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.