Know your Webpack bundle better with visualization

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to swashbuckling with code i am jimmy cleveland and in this episode i'm going to be showing you bundle visualization tools sometimes called bundle analyzers they are really awesome way to get a sort of visual graph of what your packages look like for your final bundle.js main.js whatever your javascript bundle that you're serving up to your client so we'll start off using webpack visualizer which is a nice little drop in web tool that just makes it really easy as long as you have a webpack json output which we'll have at the beginning of the setup and then we're going to dive on into a webpack bundle analyzer which is a little bit more of an industry standard tool as far as i've seen in my experience and i think it's really awesome it's it's my preferred way to do it but we'll kind of compare both of them because i think it's nice to see them both and what we'll do along the way is we will add a couple different packages and we'll look and see how that grows our bundle and how importing them in different ways can drastically affect our bundle size and these visualizers make it a lot easier for us to have you know more visualization and this is so that we can get a representation of the dependencies of our dependencies and all that stuff and we get to watch and and maintain our code and be a little bit better a little bit more diligent about our bundle size growing and then we can kind of surgically change things as they happen rather than having this big surprise at the end of your project or in the middle of your project where your bundle has grown enormous and you don't know why and you have to track it down so even if you are in that position bundle analyzers or visualizers are really useful for tracking that down but i think at this point just showing you will explain the rest so let's get to some visualization [Music] we're going to be starting out with a basic webpack and babel setup it's got babel core preset env loader webpack webpack cli nothing fancy just so that you know let's take a look at the files that we're going to be visualizing first though so in our source directory we have our entry point which is our index.js and you don't need to be concerned with the code that's going on right here right now all we're really looking for is the fact that we are importing get classes and then we call that and then we run some code inside this file and then in get classes we have two destructured imports and it just console logs those as well and if you take a look at those they're just simply exporting a string so this is just to get some import diversity for our bundle which you'll get to see visualized and that's kind of interesting so jumping on over to our browser you can see that we have let's start out with webpack visualizer we have this interesting uh website here that is probably the quickest to start out and so what it tells us to do is to use webpack json and arrow that into stats.json okay so we'll make a script that does that since we're going to be using that for a while here and we can just go into our package json and we'll say let's just make it stats and then here we'll say webpack dash dash json and you actually don't have to use this arrow to send it into a file because the this actually takes another a secondary argument here so we can just do build stats.json and that'll work just fine okay go on over to back to our terminal we'll do npm run stats and you'll see stats are successfully stored as json to build stats json we go back to our code you'll see that we now should have this build stats json file let's take a quick peek at that why don't we we don't want to get too lost in the weeds here but i think it's always good to just get a little bit of exposure and familiarity to things so the things that we're kind of concerned with here is um this assets by chunk name and you can see that we only have one chunk and the chunks are basically webpacks you know kind of version of letting you know that it's split up your bundle into multiple files but we only have this one bundle main.js we're not loading extra chunks or anything like that so that's our only one when we come down here it'll say okay this is our asset it tells us our size and some interesting information and then keep coming down there will be this chunks array of objects and within that there's modules this is the part that i want to point out that's kind of interesting it goes into each module it will tell you the name somewhere here so barbarian js so it's looking like it's doing it alphabetically this barbarian js it will say the issuer which is kind of interesting because it even tells us that in node modules babel loader is the one that handled it and then finally it tells us the file at the very end that was handled with it or we could just look at the issuer name getclasses so this is saying that getclasses is the one in this case that you know went and got the barbarian and used it so yeah barbarian wizard why did i do that just for fun there's nothing special or anything going on there so that's it uh just a quick little dive into what this json file isn't you can imagine that you could do lots of cool scripting stuff with that but what we're going to do is right click i'm going to do reveal in explorer for me i'll bring that back or down here to you since it went to another window let's resize that because we're going to have that around for a little bit here and the reason why i'm doing this is because if i open my browser and then i want to just be able to drag this buildstats.json onto here and it's that easy pretty cool huh so right off the bat we're getting a 6.5 k actual and a 2.8 k raw all right and let's see if that lines up with our numbers since we are pretty concerned with the build size here now i believe that this is going to by default run this at dev since the way that i have it set up so we should see that we're probably okay 1.09 kb and then npm run build dev for our main output so i'm just looking at this main js 1.09 kb and then here it's 6.52 so let's go back to the browser here and you can see it's 6.5 so this is our development bundle and you'd probably normally want to compare it to your production bundle it kind of depends but there there are some hiccups that can happen where it won't quite separate all the files the way that you need so i'm just going to leave it for dev for now and we'll use it to reference those numbers but obviously you could do it in build if you're looking for a real actual what the client's going to download okay so visualizing this we start here with this main js 6.5 k actual i know that's kind of tiny but i can't really zoom too much here or else we'll we'll lose all the information that i need sorry but then it says this ring around it is a hundred percent so it's saying of this main.js file that we output a hundred percent of it was from this source and it's blue as a directory here and then here the index.js that goes around that is saying 87.2 percent of all of that source was uh index.js that's so that's where the bulk of our code is happening here and then each one of these is going to be our wizard our barbarian a tiny percent and then get classes a little bit bigger and that makes sense right we had a bunch of code in index our get classes just brought these two in so let's build upon that by installing a package uuid which is a nice little package that i use a lot and it's got a really good setup and see the benefits of that a little bit later but the main thing here is we just want to install it and then we'll use v4 which is just like a random way to create a unique identifier that's pretty cool and then we'll see what that looks like in our bundle so back over to our terminal here i'm going to npm install and then we'll do uid and then we'll go back over to our code here and in our code i'm just going to use this in the wizard one just to kind of bulk this file up and see what happens there so we'll import and let's start with let's actually start with uuid just straight from it even though this isn't the way i would normally do it and you're going to see why so uuid here let's say what i want to do is append to ravelin so we'll just like concatenate to this and then we'll do uuid v4 and you're going to call that that's a function okay now we'll go back over to our code we will run stats so when we run our stats we're going to be dropping this file in here again and this is kind of annoying at first this is just like the easy quick way to do it oh yeah refresh this browser sorry you have to refresh to get it to reset there but we will do it in an automated script way in just a little bit cool okay wow that bulked up quite a bit right so now we have 38.3 k actual 22 k raw okay so let's look at this what does this say okay so a big portion is node modules now that's that directory and then here's our source directory in proportion so we still have all our usual suspects here but now we have this node modules that's taking up a ton so that's bloated us right a lot right and then if we do this uid here that's taking up 89.7 percent of all of you know is the same same percentage here that node modules is and that's going to be the same moving out so we can see we don't really care it's just a bunch of folders climbing that way there so then in here you can see we have what are the individual packages that are in those folders well we have an md5 we have a v1 we have a sha one we have a stringify parse and we're looking for our v4 and there it is 2.5 so that's what we really want um but then you can see along here we're getting a bunch of stuff for the ride there's a v5 v3 so we we didn't actually want those methods so you know maybe we want to wonder like what's going on here let's go back our code to look okay so when we import uuid this way we're actually importing the whole thing let me show you an interesting little thing here if we do import all as uid and then let's rebuild that run stats back to here reload this and drop that bucko right in here oh that's a little bit different right and now we're down to 13.4k so now it's only 60 node modules and then 40 the rest of our code and then here i mean this is a nice little graph here just to kind of see like oh okay like proportionally my code is actually only this this much but if we go back out to the packages at the end here look at this these are a lot bigger proportion now there's a lot less of them so that's all we really had to do so that is really cool thing that visualizing the bundle can show you obviously you could just look at the output but it's nice to be able to see it and say oh okay so that's why you import it this way all right well what will happen if let well let me actually show you one thing before i convert it over so let's say we don't even use it what happens here right now if the project's set up right webpack should be able to detect that it's not used and not throw it in there okay even though we're importing it all it's gonna be like well you didn't do anything with it okay so npm run stats again boom oh yeah i always forget this refresh and then build stats okay there you go it's back to where we were this uh 6.5 k and then it's just our code it's all in source all right so just to show that the package is working as intended and that's cool to get a little bit of confidence there that that's how that's working so finally what i'm going to do here is instead of importing all this way i want to see if i get the same result destructing v4 off of this to see if it's properly handling es modules when we use this so we'll go all the way over to here and we'll say let's just call it v4 and you could rename this like they do in their docs but i'm not going to for our demo build go back over here reload kick this on over here build stats and that looks the same so 13.4 k if you remember the number and then uh notice we still have the stringify rng v4 etc now you might be wondering at this point why we have these other methods and i'll show that at the end of the video i think it'll be a little more relevant at that point but for now just know that they're dependencies of this v4 okay so we can see that uh when we import it let's go back to our code again we destruct import it this way it works the same as just bringing in uuid star as uuid and then calling that individual function so that's pretty neat now that we have that visualized let's try another visualizer here let's try uh using webpack bundle analyzer which is one that i really like and we'll compare the differences so going back to our terminal here we're going to install npm i and this is a development dependency dev dependency because we're just you know using it for visualization purposes webpack bundle analyzer and actually while that's going let me make a quick note on this one uh it does actually say that they have a plug-in and i tried to set it up before for this video because i'd never used it before but i had some trouble getting it working maybe it's just the latest webpack or whatever so you know if you want to try and get that working uh the same way that we're about to do with bundle analyzer you know feel free but just so you know i'm just using for this quick drop-in because this other tool is my preference and it's what a lot of people use so to set this uh bundle analyzer up now we're gonna go to our webpack config dot json we're gonna go to the top here we're gonna say uh const uh bundle analyzer plug-in is the way that they normally do it and then that's gonna be equal to a require statement and then here we can do webpack bundle yeah that one that's the one and this is a little bit weird but uh they actually make the first thing an import here they do it like this bundle analyzer plug-in and just change it on so that that's the final thing that you get back so that works that's fine that's the way they do it in their stop install actually should try out and see if i can just destruct that since it's clearly a property on this but for now let's just get it working first okay so then um we need to add a plugins array here and in that plugins array we're going to new up a bundle analyzer plugin and we're just going to call that as a function and we need a comma here since this is a property to end that all right and then now the way that this works is this is now in our normal chain so any time that we run a webpack at all it's going to run this analyzer plug-in on every build so just be aware of that so we can still run our build stats.json and that will run because let's go back to our package.json that will run because it runs webpack first all right now i'm going to stick with build dev still so that we have the same like size comparison analysis all right so going back to here just remember that we had 13.4 k in our dev mode and then we'll go to our terminal and we're going to do npm run and let's just do stats again why not build that would work as well you can see that it it shows that it started this server up okay so that's kind of interesting and what i'm going to do is i'm going to copy this because uh it doesn't pop up for me wsl life you know but it might automatically pop up for you just so you know and then what we can do is go over to here paste this in and there we'll get this now this might not be super visually appealing the first time that you see it it wasn't to me but once you kind of get used to it it's pretty nice now i have this zoomed in a bit just so that you can see these numbers a little bit bigger but it tries to keep all of these squares intact so the the idea here is that uh it's showing them as a series of kind of containers instead of that um you know circular graph i'm not sure what that kind of graph is called but this is going to say okay well all of this is under main.js and then you can see on the right here is our source and we can hover over each little thing and see the individual file size of those pretty nicely in the path and all that stuff if we hover the whole thing it says 13.36 which looks like it's in line so it's visualizing the same way and then over here on the left we have all of our node module stuff and within this folder esm browser under uuid we have string of five v4 validate regex all the same culprits so that's pretty nice huh you can actually bring this over here and you can look at some different views which is pretty cool one thing that i really like is let's say i type uuid here it will highlight all of these individually and you can actually pin this which is pretty cool and then normally it's not this big because it's not assumed but you know for recording purposes it is you can actually click on each of these things to go see them and that will be really useful when we have a bunch more packages in here because some of them are going to be like microscopic and hard to see and it lets you zoom in and see them if you ever get in a weird zoom mode you just zoom all the way out and then it'll reset itself so that's pretty cool huh all right so now that we have seen that what we're going to do is we're going to add another package to show how things can be a little bit tricky and how you can use these bundle analyzers or visualizations to catch some problems early this is something that i really wish that i had done early on in my career or known about is it's a really nice way to not just look at the file size but to continually look at where is this file size coming from because it lists some subdependencies too you might add a package and not know how big it actually is so enough of me blabbing let's do this so going over the low dash is what we're going to be using next a really really common library if you're not familiar with it real quick rundown it's essentially a utilities library for javascript that gives you a bunch of methods that some we don't need anymore but a lot of them are just really nice like flat map and all that stuff that we didn't used to have once upon a time now they have a bunch of different ways to install it if you come down here the default they just say install low dash but there's also this low dash core low dash fp you can individually do them so i'm going to show a bunch of these i don't know why they don't show low dash es maybe it's a different team but we're going to be covering all of those in just a moment or at least the ones that are pertinent to us okay so come back over to the terminal here let's close this server down and then what we'll do is we'll say npmi and we'll do low dash oops and let's just do low dash for now and then we'll we'll we'll see the differences of the different ones okay so now we're going to do is go back to our code in barbarian we will come up here and what we're going to do is we're going to import and then let's actually look at their um you know preferred way they have a import script here yeah so they want to do underscore and then require and in our case we can do import right so come on back here we're going to say import we'll do oops underscore and from and then just name it underscore and then we'll do this from low dash all right so what we're going to do with low dash is i'm going to use the lowdash get method which is one that i still haven't been able to get away from and i'll explain it as i can so first we'll make an object this object is just going to be stupid it's going to be a nested object one two three and what lodash get is gonna do one two three four uh one two three four one great so what low dash get is going to do is uh it's going to let us climb into this object and it will actually return undefined if it can't get all the way there all right so if we were to say const you know let's name this get woof equals uh and then we're gonna do underscore right dot get kind of weird and then from here what we'll do is we're going to say okay what do you want to get it from the first thing you pass is the object the second thing is the path but it has a string so you're going to do 1.2.3 so let's not go all the way there let's say we expected uh you know actually let's let's do um all the way there i think this will be a little better example of it but we'll just skip one so this normally would throw an error and what lodash is going to do is it's going to fail safely and return undefined in this case the get method and you can actually pass a third argument just as a little bit of get knowledge here to return something else like let's say you want an empty object instead of undefined to what you get back or an empty string or something like that you can do that too which is pretty cool so it's a very nice utility function i like it a lot so now um we'll just console log get woof and i'll put a thing in front of it i don't know if i'm actually going to print this out but you know i wanna i wanna see if just in case okay so now we're using it and let's run our bundle once again so run stats and then now that we're doing that we'll come back here go to this we just refresh this now that we've started the server up again and this is pretty crazy huh you can see that uh in our node modules there is this like weird sliver here and there's a weird sliver here too but look it's source and then this is our uuid so apparently we've added something monstrously huge to our whole package and underneath node modules which is this low dash and it just says loadash.js it doesn't say the methods or little subdependencies or anything like that pretty crazy huh if we look at our total size we're now up to 545 kb up from like 13 kb it's pretty wild so that doesn't seem right right so we know that there's a problem and we can see it pretty visually right away and let me show you that thing i was talking about before now that we're in this view if you do uuid this is pretty cool it will uh you can do this and unfortunately it doesn't like you know change the the box model or anything like that that probably too hard to do but at least you can zoom in to each one and actually see them so yeah that's pretty cool i like that all right then you just zoom out zoom in zoom out it'll it'll figure itself out okay so that clearly is not what we want so um let's do this because the other way that they recommend setting this up is instead of importing under underscore from low dash maybe what if we did the thing that we did before let's import as okay let's run our stats again from the terminal sorry got lost for a second all right and then from here uh we will do and actually while we're doing this on this mode let's let's try this let's do npm run and i have this watch command to do webpack watch and i'm pretty sure this will work but what it should do is put this in watch mode and then start up our bundle analyzer server and then every time we save it'll it'll allow it to reset i've done this with webpack dev server but i've never done it with watch mode okay so it doesn't look like that did anything at all right let's do a quick sanity check and say all right you know you imported all that stuff but well actually let's just delete it first because you're gonna have an interesting surprise here okay and then come back over here and look uh this automatically updated that's pretty cool huh going back to our normal format and then we're back to 13.45 kb so we know something's up here so maybe let's undo all that and just import this and actually i'm just going to comment these out for simplicity right sorry i'm still on this different keyboard it's kind of throwing me off a little bit i have a split keyboard so i apologize for the high amount of mistakes i'm making moving on we're just going to import all as low dash okay and then see what happens there look at that webpack can't figure it out uh like we could with uuid even though we imported the whole thing you know no matter how we do it like if we go back up here and let's say we just do this throw that back here doesn't care it's still bringing in all low dash so what this is is when a library isn't properly set up to do es modules webpack can't do what's known as tree shaking to throw away like dead code elimination or anything like that uh among some of the other bundle optimizations that it does and so that that's kind of our problem here now what if we were to i'll show you the way that they recommend to do this if we bring these back in here and then what we'll say is we'll go to the directory and do that so we'll say import get from low dash get and then what we want to do down here is just get rid of this call to it and do that what happens when we do that oh that did something now we have a bunch of little things what's our size though 62 kb it was like 500 something right so that's an improvement at least it still seems like a lot of stuff you can see it's pulling in all these things but you might think oh maybe these are just sub dependencies it's a lot of stuff to have sub dependencies of but you know maybe it is here's our get which is pretty cool but at least we're moving in the right direction right so that's a good start so another package uh alternative that we can do here that's commonly recommended is to do low dash oops low dash yes okay and that stands for es modules ecmascript modules not spanish not espanol and when we do npm run watch again what we're going to do is see if we get similar or different results so now we're at 62 kb if you remember that and then we come back to here and then what we're going to do is instead of that we'll do get it from low dash es and well let's try this first let's do it the same way come over to here reload just in case and it looks like it's the same doesn't it now it's 84 kb it's actually a little bit bigger which is kind of crazy but if we do this and let's go back to here and i'm going to wrap this so i want to destruct this like we did with uuid and see what happens there same thing didn't change i mean at least we can destruct and bring it in that way so that's cool and it's not bringing in like the whole library which is great so you can see that i guess the minor advantage here with low dash es is that if we just import from this directory and we pull this off here we at very least are getting uh closer to the smaller sizes not the 500 kb of the whole library or whatever so that's a good direction you know at least we can do this nice syntax here but what i want to show you here is what if we were to go oops what if we were to go back to this instance where we're like hey i just want to do like underscore again okay oops i keep doing that and then come over here oh look at that it actually works now so at least this package is in the right direction sort of because it is making it to where we are getting that dead code elimination we're back to our small 13.5 kb if we just import it unlike the regular lodash which just brought everything in and that's they say it's because of they have backwards uh you know es5 browser support built in to it and i'm kind of curious because a lot of packages do that as well from my understanding and uh you know they just work with imports exports like uuid does so i'm not sure what the full scoop is there but it's not working too great so from here what you could do there are some other options i don't remember if they list them right here oh yeah right here module formats so they do say low dash yes there's a babel plug-in and a low dash webpack plug-in and i've seen some success with those i'm not going to cover those today it'll be a little bit more involved to do that but i just think that's crazy i think it's pretty nutty to have to set up a whole babel and webpack plug-in chain for a single set of packages that's just kind of wild let me show you an alternative if you happen to be using only a few methods in low dash like in my case i'm just trying to use get maybe that's the only one you use i have libraries or i have projects that are like that so what we could do here come back down here and say npm i and then we can just do loadash.get which is nice of them they've actually exported it by name that way pm run watch again so now what we can do is uh we'll go back to that get format where it's loadash and and then this will be dot get like so scroll down here re-enable those and then let's see what happens come over here reload this now look at that so now the whole size is 37.96 kb and you can see that we're only getting this low dash get and it's much smaller than it was before you know our other sizes we got up to like 80 kb with the low dash es all the way to 500 plus with all of low dash so this seems to be the best bang for buck if you're just maybe you just have a couple of these this is pretty nice it's just modularized and it's a lot easier to view so i think that you can see the value of visualization with your bundles right now it just makes it a lot easier to kind of hone in and get a nice little mental model of what's going on under the hood here instead of just size you know raw size output i think this is fantastic but what i want to show you now is the thing that i said that i would address in the beginning of the video where i said okay remember that uuid brings in stringify brings in range.js and all this stuff well where do those come from and do we actually need those is this exported improperly this is something that you can do that's kind of cool if it's a well-made package you can go to their github repository and i invite you to do this early in your career uh or or later you know if you're in my position and you know it's never too late to learn is really what i'm saying but you should go and look at packages and try to dig in and see if they follow some best practices and you can find your way there so what i want to show is if we go to their github for uuid we go to the source folder and that's normally where their code is going to be right we can look down here and we'll see that there is a v4js what i want to point out first is that there's this index.js if we go to that that's the common most entry point that would let you know that you could destruct variables and this might be a little bit weird to you if you've never built this type of library before but this is a pretty normal practice to say each of these files has a default export and then we're saying take that take that default and export it as a named variable so what i want to do is this is a neat little github feature you can click this and see where it's used they have a test for it which is pretty cool and then in this source v4 you know this is probably a little bit small for you i'm sorry i can bump that up a bit um i'm gonna go to the source v4 function jump into here and then we can see the actual function which is really neat it's pretty lean to randomize this but it does rely on two packages rng and stringify let's go back to here stringify rng looking familiar all right what about validate what about regex okay well go back into here we haven't gone into those yet sorry i had a weird browser hiccup there where my highlight wouldn't work i had a hard refresh so if we go to rng or stringify let's start here and then we'll say okay well um i just want to see the source rng right and then if i open that we can see that it imports this crypto package okay and you can kind of just keep going uh you know infinitely here but in this case i want to come back here i want to go to stringify i just want to check this out oops did i go to the source of stringify it might actually be that big yeah it is cool and then up to the top here's this validate okay you can keep going i'm not going to get that crazy but here finally is regex that's where we'll stop so you could follow the trail to see oh well now i know that v4 is actually directly importing these and so that does make sense why they came along for the ride so the last thing i want to show you here before we wrap this up is how you can make it to where your bundle analyzer isn't running every single time because that was pretty annoying for me to figure out the very first time so if you come over here uh to well let's just shut this down for now if we come into our code and we go to our package json what we can do is for this stats function let's say that's the one i want to run it and if you don't understand the problem actually real quick if i do npm run build like say this is what my server runs it's still going to start up that webpack bundle analyzer it doesn't distinguish it which is kind of annoying at first so what i want to do is come over here and say i'm going to make up like an environment variable this is the way i do it there's other ways to do it i'm going to make a stats environment variable i can't talk and that's going to be set to server all right now with server if i come over here to my webpack config what that will allow me to do is this actually takes an object and there is a setting here called analyzer mode oops analyzer mode oh look at the nice descriptions here thank you for whoever built this package and then um from there what i can say is process dot env dot stats and then we'll say let's set it to that but if that doesn't exist we will set it to disabled and that's pretty oh that's cool look at that is this built on typescript anyways nice so they give us all the options here so you can see there's a static server a json and a disabled and so what i that's why here in the package json i'm setting it to server because that's the default you could just do a static and that will put it out to a browser file an html file you can just open if you prefer that sometimes that's nice but here especially for archival purposes here what we're doing is we're saying if that's passed in run it otherwise disable this plugin now if we go back and do npm run build it will not start that server up as you can see that's really cool and then if we do npm run stats it will and come back over here and there we go so yeah i think visualizers are awesome and i hope now that you've seen them you will find some use for them in the near future and hopefully they can level up your game i will see you in the next video
Info
Channel: Swashbuckling with Code
Views: 3,615
Rating: undefined out of 5
Keywords:
Id: oAgHZ9zlmaY
Channel Id: undefined
Length: 35min 57sec (2157 seconds)
Published: Mon Jan 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.