How to get polyfills with Babel 7 and Webpack

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to swashbuckling with code i am jimmy cleveland and today we are going to uncover the arcane mystery that is polyfills now you may have run into a situation where older browsers are throwing errors for newish javascript methods such as object.values or array.includes and you're wondering why isn't babel preset env taking care of this like i expect it to or you may be unaware that this is even happening in your code base and that you need to take extra steps in order to transpile old methods and that's what polyfills essentially are it's a community written code that's written to an older spec of javascript for older browsers that is made to support newer and upcoming features that those browsers do not yet support now just know that this is a little bit more complicated of a setup and it took me a fair amount of time when i was researching it to figure out the proper ways to do it so i'm just hoping to pass on some of that knowledge to people that are in the same position that i was i'm going to be starting from a basic webpack setup with babel and preset env if you're less familiar with that i have a video going into more detail on how to set that up that you can check out the notification or in the description i'm going to show you some different options for polyfills and at the end i'll show you a cheat code once you understand what's going on a little bit better but otherwise i think it'll be worthwhile to you to stick around and check out the video so you can end up with a better understanding of how to accomplish babel polyfills in webpack let's start out with a quick overview of the project now i'm going to have a link in the description for some reference code on github in case you want to check that out but to start into here just so that you know we have in our dev dependencies webpack webpack cli we've got our babel core babel preset and babel loader the standard culprits now i've also got some scripts and the main ones that we're going to look at right now is just build and build dev probably just build but we'll see and that's just going to in production mode run webpack and do a minified version of it because we're going to take a look at our bundle size all the way through since that is an important habit to be getting into okay so next uh webpack config pretty straightforward you might have seen from my other videos we have the mode being dynamically set since to the node env and then we're looking at all our javascript files we're excluding node modules and we're running babel loader on them and we have some source maps nothing crazy there okay then you have an index.js that's pretty simple i've kept it lean just for this demo purpose what we're doing is we're creating an object of a recipe and then i'm going to show an object spread syntax that is not supported in ie 11 just to show this whole process kicking off and this is not a method so normally this will polyfill but i'm going to show you a little gotcha that happens without a browsers list right now but the last file before getting into that is just the index.html and all it's doing is loading in our script main.js and running that okay now if we jump over to our terminal uh we can do npm run build and you'll see that it builds successfully just so that you know and the 881 bytes is what we want to pay attention to we want to keep an eye on this just so we can see that size is going to be a factor as this process continues and it's a good habit to always be looking at that if you're on linux or mac you can do ls-lh for long list human readable and then look at the disk folder since that's our output folder here and you can see this 881 bytes if you're on windows i think you can use the dur command but i'm not positive about that so kicking on over here to ie i've already loaded this once but if i reload you can see that we're getting a syntax error on main js one comma four all right well um you know let's take a quick look at our code here and look at the main js and you can see you know one somewhere around here four it's uh at the bottom here it'll say line one comma four i don't know if you can see that very well but uh we're actually getting tripped up on an arrow function and that's interesting because babel preset env should be taking care of that but this is the gotcha that i was talking about what you want to do is make a new file called.browserslist.rc and then you can just put defaults in here this is pretty weird because if you're using babel alone and not webpack i don't have this problem it uses the browsers list defaults without having a browser's list file there but it doesn't do that in webpack and i'm not sure why but okay so no big deal let's just put that there and then if we run our build again we're going to see a slightly different build size 886 here versus 881 okay and then if we were to go back to ie here we reload we will see that the code actually runs here and just a quick note on this you can see it running but if you if you do have access to ie 11 there's a weird little thing that they do where if you go um i went to emulation here in this little drop down menu and it defaults to seven which are ie versions and i do not know why that is it confused me so much because i'm not transpiling to ie7 and i don't want to support that but that's what it starts out as so just a quick note there now if we go back over to our code here if we go to main.js and let's actually format that just so that you can see it lists it out you'll see there's a bunch of code that's been put in here pretty much to cover this function let's put down here there's this r function that we're doing for our object spread and this is all minified and mangled and that's why it only says r but that's essentially what this is doing for us and that's why that's allowing it to run so that's just that gotcha for you real quick and nothing crazy it's just um yeah it threw me for a loop the first time i thought you should know about it and we're going to need a browser's list moving forward so there you go now a pretty cool little trick here is that you can go into your terminal and do npx browsers list and if you do that it will actually read your config and tell you all the browsers you're supporting so if you want a little sanity check there now there's there is another little gotcha here that if you do this in just like a random directory or whatever it's going to list out the browser's list defaults so if you want to make sure that your browsers list config is working try doing something like this you know ie 11 or whatever and where that's all we're targeting and you'll see that that's all it prints out cool okay so that's all there is to that just wanted to show you that so we're just going to leave defaults we don't we don't need anything custom for this one but you know that's a whole other topic so next what i'm going to do here i am going to add a method that i know is not going to be supported here so what i'll do is i will make another console.log okay and i'm just going to put es 8 object dot values example i just happen to know that comes from es8 here and then we'll just do object dot values run that method on our uh our newly created thing the gauntlets recipe here okay and so now when i run npm build where's that you'll see that we get uh 994 bytes so it's going up a little bit in size just because we added those files but then if we kick on over to ie i have these windows split it's really annoying but it's it's a nightmare to deal with their inspector otherwise so if i reload this we're going to get a new error and it says object doesn't support property or method values and that's unfortunate and that's because this is actually a method that requires a polyfill so let me show you the first way to fix that and then i'll kind of explain why you need to do this so if we jump back over to our terminal what you're going to want to do is npm i s for save we don't want a development save dependencies we want regular dependencies here and then we're going to do core dash js and we can just do the newest version that's what i'm going to do here okay and then what we can do is pop on over to our code and at the top here we know that we need this specific method so we can actually just import it from core.js so we can do core js and it's going to be slash modules and then it's going to be es and there's even es next in here if you're using some future proposal stuff just so you know but you can do es and then we're looking for the object it's really nice how they've written this out and then from there what object are we looking for well it's the the values method right okay so we're just straight up importing that and then we will npm run build and you can see we now have 9.13 kb we went from 944 bytes to 913 kb it's a pretty significant jump for something so small you you might be surprised at that so then we go back over here to ie and from here i will reload and our code should work i don't know why it takes a while but it does cool so there it is working great you know if you're curious about chrome it's also working and you can see this 9.3 kb so yeah we were getting close to a thousand bytes uh and now we're at you know over 9000 bytes so hopefully that illustrates to you a little bit of the why or clues you into that is a lot of people when they set up uh preset env i know that i was one of them from babel or babel whatever your preference of pronunciation it seems like it should just do all the things right like it targets the the default browsers that it decides it's going to and then it transpiles all your code to old js and you know you then you go to run it and it doesn't work and it's very confusing and that's because they are opting out of that as the default because there is a lot of file size increase that's going to happen this is just one method you know imagine if you're using a bunch of methods it can get pretty crazy and you're going to see that so the the reason is the one of the reasons at least i think it's the main one is that the size can get nuts and they want you to have to opt into that so you aren't just exploding you know your users download sizes all right so that was the leanest way to accomplish what we want let me show you another example to kind of build on this though now if you happen to want to do some async await for example this is kind of a strange one it's different than a lot of the other things that you have to do because normally you just import you know whatever method that you need from core js modules and you'll be good to go but in this case what i'm going to show you is that i just taken the example from mdn where they just wrote a quick async function here it's going to await this resolve that creates a promise does a set timeout and all that nonsense and then it calls a sink call okay so we're just trying to get some async await funness in here now let's pop back over to the terminal once again we're always popping i don't know why it's pop i just like it and then we're gonna run a build and you know 9.84 kb not not a huge increase um for what we're doing but then let's reload this so yeah regenerator runtime is undefined what a weird error i've gotten this uh in the past just like trying to do npm installs and like what on earth is that um you know once upon a time when i didn't know what it is and now i do so let me show you that so what you're going to want to do here is you're going to want to install and this is going to be save as well and the reason is because these are actually getting bundled into your final output that's why these are save and not dev dependencies so you're going to want to do regenerator runtime all right while that's installing well it's already done it's pretty fast uh we'll go back over to our code here and at the top here you're going to import regenerator runtime and it's slash runtime here it's kind of weird all right one more time run a build let's go back to ie we'll reload this here and this time it should work oh no it doesn't work that's right because we need promise as well i'll add that and i'll then i'll show you the code so in this case we actually already have the package we need all we need to do is say import and then we're going to do core js modules es es.promise it's pretty straightforward right and notice that uh our i almost forgot our bytes here 16kb we are up and climbing with all these things that we're importing now we're all the way up to 26 kb so you can see how adding one feature after another is uh starting to to blow up our builds and that's just something you have to be aware of you know uh you want to start early paying attention to that because it'll sneak up on you okay there you go boom calling and resolved isn't that awesome so we've got it working now and let's take a look at our code the output code here so if we go to our main.js this is getting nutty i might have to build dev on this one i don't know if this is going to work quite right otherwise yeah let's do that let's do that so i'm going to do npm run build dev just so it's a little more readable and that's you can see the difference here between uh running production minified if you've never never looked at that and running a development build big old difference there all right so go back to main js and uh i i guess i need to close that because i formatted it so wants to save me for myself i guess and here's what's interesting there should be a async generator right here and you we don't need to get two nuts into this it's just um from what i've learned is that async weight is not itself i don't know i'm saying async a sync await you could say it either way i guess a single way is not built on generators like in the actual way that it is in the modern javascript versions but the way that they transpile it is through generators actually and so that's why you need that regenerator runtime because that adds all of the generator fallback code and you need that and then it's still using promises so you need the promises as well and that's why we need all that stuff okay so yeah so this is great and it's kind of cool that it's lean um you know we just have them at our entry point right here um we could if we only use it in one file we could import them there or we could import whatever ones we want here at the root uh but it's going to get pretty hard to maintain this and really annoying to constantly do that back and forth and so we've got some other options for accomplishing this so the first thing that we could do is if we we want to keep our regenerator runtime but let's say we're not worried about um all of the different methods that we don't want to import them individually we're just going to import all of core js let's see what that looks like doing a real naive move here 176 kb yeah and that was you know uh 120 was from the dev this is this is minified so 26 kb we've jumped all the way up to 176 kb that's a pretty good jump there so that doesn't seem like the option that we want because we don't want to be super lazy i guess we could um and just fill all the things but that's getting a bit wild and i think we should be a little more respectful to our users this is where babel can start having our back so if we go to the babelrc file and this is going to be a little bit weird but you actually want to put a another set of array brackets here this is just how the syntax works because we want to add a config object here now and so this config object is going to have what i'm going to do is i'm going to throw debug true on because i think this is a cool little hack you can do to get some nice output but the thing that we're wanting here is use built ins and we're wanting the entry property this time okay so let's run that npm run build we got a bunch of output and we got some errors okay so this is a lot of stuff let me actually [Music] okay so coming up to the top they actually give us a clue here at the top of what our error is going to be caused by in this situation let's say we notice that you're using use built-ins option without declaring a core js version now they assume so if i didn't install core ijs this would work at two because they assumed to but three is a little bit better for various reasons it's a little more modularized modularized as far as uh i've read um and we're we're using that newer version okay and so what we need to do is go back to our code and put this simple little change and say okay core js is at three and this is uh json so oh i forgot i don't have that anymore core js there you go so we just need to set it to whatever version that we have installed and if you don't know you just go into your dependencies here and here you go so you can just set it to all of three i think you can set it to the exact version as well but i just do it as three there okay let's try and run that again and then we'll look at our output again but uh the uh run build you can see as we're doing this that's why it's getting all of these errors here because it couldn't resolve uh from two so 153 kb well that's not as small as we had before unfortunately um but it is a little bit smaller then let's see if we can find that old one here's before that error 176 kb that we had before and what's essentially happened here as far as i understand uh because this is not my preferred way of doing this but when you use the entry what it's going to do is it's going to look at your your browser's list setup or whatever your target configs are and it's going to polyfill for all of the things that it would need from that so it's taking that core js import that we had and then it's going to output all of that all the different various polyfills for well let's look npx browsers list for every one of these browsers that it needs to support but there is a better way that we can do this with this really cool cheat code feature that i'm going to show you here this is what i usually use in my setups and uh if you've uh if you're used to this in the past or you come up in the docs with it let me actually show you this before where i get into this um it used to be called babel polyfill there was this plugin at mabel slash polyfill and that was the way that uh you used to do it and that's what i'm used to but now as of babel 740 it says this package has been deprecated in favor of directly including core js stable regenerator runtime etc as needed and then it shows that so you could you know do just core js or slash stable here okay so just just so that you know this is the new best practice and i think that it was mostly because they do not support proposals anymore and i think they used to and uh core js3 did some cool stuff when they upgraded from two and the upgrade path wasn't straightforward so uh they they decided to just do it this way for support so coming back over to here uh in our config what we can do is go to our people rc um and here's our little cheat code here we're gonna do is change this to usage and now when you do usage you actually do not want to import over here in index.js you don't want to import any of these things anymore okay and then if we go back and do npm run build boom pretty cool so now look at that we're back down to 27 4 kb all right so that's pretty awesome so what this is done this is the reason that i'm doing debug here is that this really nice thing will tell you um this is the plugins that are just being used you can kind of skip that for now but it's nice to know um the main part that i'm looking at here is using polyfills with usage option i don't know why that was hard to say usage option uh and then here it tells you the file that it found uh some methods added following core js polyfills and then here you can see define property to string values and got our promise and then some web timers so it found all the things that it felt like it needed and it polyfilled them so yeah we're still down uh quite a bit uh especially compared to the 170 kb so i think that this is a pretty reasonable approach and it's pretty cool that it just does it for you so why it's called usage is it actually looks at your usage of each thing pretty straightforward but it was a bit confusing to me when i first read it at the entry is saying hey where's my where's the entry point here or we're going to import them there and i'm going to look for that um but usage is a fancy one that will go and look at each of your things well actually let me show you uh this pretty cool little thing real quick so if i were to create a new file and we'll call it uh includes example.js not the greatest name we're going to export default includes or actually we'll do a function includes example that is going to take in two arguments it's going to take an array and then like a target that you're looking for all right and then we'll just console.log pretty straightforward r dot includes since that is a newer method and we'll say does it include the target all right come back over to here under index.js and let's import that so we're going to import and then we can call it whatever we want but we'll call it includes example just to stick with it from uh dot slash includes example and then we're just gonna run that immediately so we'll say uh let's call includes example and we're going to write an array on the fly here and i'll just uh pass it you know like a b c pretty boring stuff and then we'll say uh does this contain b all right so uh then we'll go back to here and we'll run it you're going to see something pretty sweet now when we look at the using polyfills with usage option you can see that it looked in the index.js and found the same things and then it went over here and it said oh well i added these polyfills ray.includes and string.includes here pretty cool right so it's going into each file and it's telling you hey i found this method in this file so i went ahead and i added that for you pretty cool so let's see if that runs an ie now so if we have backward support we should see that at the top here true it did include it all right and this whole usage thing uh i believe that this is uh might be specific to webpack or bundlers but i'm not sure but they say in their docs that it takes advantage of the fact that a bundler is not going to load the same polyfill multiple times and so that's why they can do that and it's pretty sweet because otherwise you know if you had the same method in a bunch of different files those might get duplicated every time it needs to polyfill them so this is neat and it's a really cool little cheat code here i like to call it where you just throw that in and it goes and it looks for old polyfills and it bundles them all together all right and did we check our size on that last one yeah 29 kb so we're up and climbing so i hope that one i just wanted to instill that habit of like looking at your bundle size is really good really valuable and i i wish i was a lot more focused on that when i was newer as a developer but it also is really good to understand why polyfills aren't included because we started out in the bytes range of our code and now we're up to 29 kb that's pretty insane uh and and we're only using a few methods even with this awesome cheat code usage you could see it could get pretty big pretty fast now if you just a little note if you want to use like super cutting edge new features that aren't stable and their proposal javascript features there are some additional steps that you'll need to do you can look that up in the babel docs but i'm not going to cover that today all right well i think that covers it pretty well uh hopefully this is a little bit less magic to you it's still going to be magic of course there's there's a lot going on here but um you can kind of get a glimpse into what's going on and i think that's kind of fun for me it gives me a little bit less anxiety especially when i see these errors like cannot find regenerator runtime and i'm like what in the world is that and i have to go search about it and now i know what it is and what it's used for and i know that it's involved with a single weight and maybe other things and that's cool and so just little by little we start to kind of get do delving under the hood we can see that core js if you ever see that pop up you now know what that's used for um for these polyfills and all that type of stuff and how babel uses it and i think that's pretty awesome so i hope you walked away with some sweet learnings from all that and i will catch you on the next video hopefully you
Info
Channel: Swashbuckling with Code
Views: 5,994
Rating: undefined out of 5
Keywords:
Id: YXtQms2msZQ
Channel Id: undefined
Length: 25min 57sec (1557 seconds)
Published: Mon Jan 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.