-
-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
Allow analysis of generated bundle and dependencies #1858
Comments
Ideally this wouldn't require any changes to the CRA code, but I don't think that is possible. We'd need to at least get our hands on the Are we able to come up with some way of gaining access to the module stats from the outside, or would it fall under the category of providing configuration and being excluded from CRA? |
I highly recommend the Bundle Buddy tool from @samccone https://twitter.com/franklinjavier/status/931324987654443008?s=17 |
What's the latest thinking on this? Which tools work best? |
I'm biased, naturally, but still think webpack-bundle-analyzer would be the best. I'm still contemplating about the best way to handle outputting stats.json from the build -- this issue webpack-contrib/webpack-bundle-analyzer#119 makes me a bit unsure how much work we'd need to do in CRA to get the stats.json out without issues. I haven't forgotten about this issue here, though. When I've had time with webpack-bundle-amalyzer, I've worked on the next major version PR webpack-contrib/webpack-bundle-analyzer#97 |
OK, let me know if you need something on our side (as long as it doesn't negatively affect build perf). |
Sure, will do |
A "lighter touch" could be to just have an option to output JSON, and then that JSON can be handled however the user sees fit (I prefer to use Chris Bateman's webpack visualizer). I imagine an addition to package.json scripts like this: "scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"build-stats": "react-scripts buildStats",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"build-stats": "react-scripts buildStats",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
+ "analyze": "webpack-bundle-analyzer stats.json"
} I'm happy to work on this as a feature if folks agree this is the direction to go! |
Yeah the Feel free to work on this @joshwcomeau, it would be amazing |
@joshwcomeau you probably want to be aware of this: webpack-contrib/webpack-bundle-analyzer#119 Basically, if a bundle is large enough, I haven't reproduced this error myself, but if you find something, I'd love to hear about it. |
Right, so I was proposing we don't do it as part of the main
Ah, interesting! I've never run into that myself. Do you think it's something we need to be concerned about? It seems like a pretty edge-case thing (otherwise I'm sure I would have run into it by now). My instinct is that we proceed anyway, and hope that a fix is implemented within webpack shortly. I'll spend some time tomorrow looking at this. |
I'm in favor of the separate entry point npm script proposal by @joshwcomeau, #1858 (comment) - the webpack visualizer they're referring to and webpack-bundle-analyzer alike are both great because of their interactivity. I actually made a workaround with a similar approach #3518 that can be used without ejecting. I don't think we need to be that concerned about build performance here because, in my experience, this is not information most users will find very useful on every recompile. Usually, I check these tools every few days to make sure that the bundle size hasn't grown much larger than expected, due to a recently added dependency. |
We should care, one way or the other. If we go the direction of adding a new However, if we were to create the Nevertheless, both approaches could benefit if we'd change
Hmm I'm not so sure about whether webpack would fix it in any short time period. If the |
Did some digging, I have some questions. It turns out the Node API for webpack supplies the stats object as part of the build process. I still need to figure out exactly how to get the stats object to match the options when using the CLI, but one thing's for sure: we will need to For the bug being discussed about stringifying blowing up on huge JSON blobs, I imagine there's some kind of way to stream it? But (I did do some perf checks and it seems like it'll take around 20ms to stringify and write to file, on a 2014 iMac, with a small project. I imagine it could be quite a bit longer on a larger project, but given this is an opt-in thing that won't run automatically, I think that's ok?) So yeah, I think the best approach would be to have a CLI flag for the build script, since it's essentially the same script. For an ejected project: "scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"build:with-stats": "node scripts/build.js --stats",
"test": "node scripts/test.js --env=jsdom"
} I can use the convention established in the test script, and just use const resolveArgs = {
stats,
previousFileSizes,
warnings: messages.warnings,
};
if (buildStats) {
fs.writeFile('bundle-stats.json', JSON.stringify(stats.toJson()), err => {
if (err) {
reject(err);
}
return resolve(resolveArgs);
});
} else {
return resolve(resolveArgs);
} Lemme know if this sounds good (or what ought to be changed) and I'll get a PR submitted! EDIT: Ah, just saw the comment about bfj. Yeah, that works as well! I misunderstood originally and thought the stringification happened within Webpack. Since we have control over it, we may as well use something like bjf. |
Something with streaming probably sounds good to me |
As far as I'm concerned, your thoughts seem good to me, @joshwcomeau 👍 It might be useful to write the The CLI will by default read the bundled files from the same folder as the stats JSON file is in — if the stats JSON file is in a different directory than the bundle contents, CLI will need you to supply the bundle directory as the second argument. |
Sorry for the delay in this. It's a particularly busy week for me, traveling for work. Haven't had the time I expected to work on this! Will try and pick it up over the coming weekend.
Hmm... so my concern with that is that I think of the I suspect it would cause more confusion as folks try and figure out where the stats file is written. Because of how I view the Maybe that's just me, though? Curious to get someone else's take on it, if |
I think you have valid points. We should then figure out how we can help users get the stats reported correctly. I think documenting this will be key :). Users will have to remember to use both CLI arguments with CRA.
|
@joshwcomeau I understand not wanting to include the stats file in the build folder because it's not a production asset, but the |
My 2 cents when it comes to exporting these types of perf/stats from build pipelines TL;DR Add the ability for users to output full source included sourcemaps – making it trivial to use any sourcemap compatible bundle analyzer. less tl;dr My current thinking is that the webpack stats object only gives a small subset of the entire picture and is coupled to the a specific build pipeline :/ which encourages hyper specific tooling that is not portable across other bundle analysis pipelines. What is the most common denominator when it comes to looking and understanding bundles then? I would say it is source-maps. The nice thing about sourcemaps with embedded source From a user's perspective what kind of questions arise when they are looking at a bundle or sets of bundles? Based on my user research these are the questions that continually pop up.
Luckily of all these questions can be answered via source maps introspection except for (why is lib X making it into my bundle). For this reason I think that if CRA wants to make it easy for users to understand their bundle without having to eject their webpack config, outputting debug source maps in dev mode by default and optionally outputting debug source maps for a prod build is a solid approach that will be maximally is portable across tools. As always thanks for your time and everyone's thoughts. |
I think its really valuable to get a better understanding of bundling by looking at the output. If #3145 makes it into 2.0 it will be even more useful. Generating the stats.json seems to be a fair way so that the user can pick the tool of flavour for them self. @valscion are you up for a PR? I can help with docs. |
Which PR are you talking about? I think @joshwcomeau might be the one you should be asking here |
@valscion Even i could manage to get the json file out of webpack going but you seemed to have knowledge about some concerns regarding it. Anyway I will appreciate and be thankful for anyone who wants to make an effort! |
Interesting, @samccone! I've never heard of sourcemaps being used for anything other than understanding stack traces in dev. Of the points you listed, are there any that stats.json can't answer? Of the webpack-specific analyzers/visualizers I've seen, none have tackled finding duplication across bundles, although it feels like it really ought to be possible. I suppose from my perspective, it's about balancing the benefit of a tool-agnostic method vs. supporting what users actually use. I've been meaning to try Bundle Buddy for a while, but I'd also hate to lose the tool I already use, Webpack Visualizer. I'd wager that Webpack Bundle Analyzer is the most popular tool used by folks, and it feels like an incomplete solution if we don't support that. Unless we think tool-agnosticism is important enough to override that? My personal sentiment is that we should support the most common pattern, since ejecting can handle more advanced/niche usecases. Just based on NPM downloads it looks like webpack-bundle-analyzer is leading the pack atm. Can always revisit in the future if that changes (or support both?) For the location of My life continues to be busier than I expect. I spent some time this morning playing with this; I still need to test everything, but I think I should have a PR up in the next day or two. That said, I don't want to make any promises I can't keep! If anyone's getting impatient, don't let me be a blocker on this. |
Based on my comment above I put a design document for understanding bundles via sourcemaps your comments are appreciated! --
It is possible, bundle-buddy does just that https://bundle-buddy.firebaseapp.com/
There is actually no reason that I know of why webpack vis can not gather its info from the sourcemaps vs stats.json :) |
Don't we already do that? |
Cool doc, @samccone!
I know :) I mentioned it earlier. I meant specifically tools that use Webpack's
For sure, but "it's possible" and "it exists" are two very different things. I'd like to support the tools as they are now, not as they could be. Unless I've misunderstood, and you're saying that these tools already support it? I think I'm gonna submit my PR as-is, with support for If someone else wants to add support for sourcemaps, I think it'd be pretty straightforward! I'd imagine we just need to find how they're being generated in dev, hook into it in prod, and write them to the build dir. But yeah, I do think we want both, and I don't have the time to tack on another task. Happy to coordinate with someone else on that though. |
Oh, there's totally already support for sourcemaps, at least according to the README template. Yay solving for both usecases! |
As discussed in facebook#1858, we'd like to make it easy for users to view bundle stats without ejecting. This PR adds a new script that, along with building the site for production, creates a `build-stats.json` file. This file can be used with tools like Webpack Bundle Analyzer or Webpack Visualizer, to help the user optimize their bundles. Conflicts: package.json packages/react-scripts/package.json
If anyone from earlier in the discussion wants to take a gander at the code, PR is here: #3945 |
Yassss #3945 was merged so this issue can be closed, I think! 🎉 💯 👍 work @joshwcomeau |
This issue is a continuation from the Twitter thread discussing usage of webpack-bundle-analyzer with CRA.
webpack-bundle-analyzer
can be used either as a CLI, providing it thestats.json
webpack JSON output and the built files. With these, we are able to:Here's an example I built from a project using
create-react-app
after first having to eject.⏩ report.html.zip ⏪
The changes I had to do after ejecting are in this commit: valscion/arvontakone@fbbc306
EDIT: Here's a GIF of that visualization:
The text was updated successfully, but these errors were encountered: