1. 21
    Target specific browsers with babel-preset-env and the babel pollyfill
    7m 1s

Target specific browsers with babel-preset-env and the babel pollyfill

Andy Van Slaars
InstructorAndy Van Slaars
Share this video with your friends

Social Share Links

Send Tweet
Published 5 years ago
Updated 3 years ago

Converting all of our modern JavaScript into ES5 compatible syntax is a great way to use modern features while targeting older browsers. What happens when the browsers natively support these language features? Then it no longer makes sense to transform that code or to include polyfills that will go unused. In this lesson, we’ll add the @babel/polyfill package and configure babel-preset-env

Instructor: [00:00] During the course of building our application, there's a good chance we're going to need to use features that not all of our target browsers support. To handle this, we can install polyfills in our application. We're going to start by doing an npm i -s to save this is a runtime dependency, @level/polyfill.

[00:25] With that installed, I'm going to go into my index.js file. I'm going to add an import for that polyfill. With that imported, I'm going to go into the terminal, and I'm going to do an npm run build. We'll see that webpack-bundle-analyzer has saved a report. I'm going to open that.

[00:56] When we take a look at this, we'll notice that our app bundle now has this pretty large section for core.js. This is pulling in a parse size of 70 kilobytes to our bundle. This is going to polyfill features that are not available in older browsers. ES6 Promise, number constructor, WeakMap, things like that, are going to be handled by these polyfills.

[01:18] If we look at the previous build, we'll notice that our entire app bundle is 12k, as opposed to 90k. These polyfills have added quite a bit of size to our app bundle. This is fine if you need all these features, but a lot of newer browsers support a lot of these features.

[01:38] If you know the browsers that you're targeting, it would be nice to be able to pare this down to just the things that you still need, based on target browsers. Let's take a look at how we can do that. If we open up our base webpack config, we can scroll down to the rules section, and we'll see that we're using this preset ENV in our preset section for our Babel configuration.

[02:01] Without any configuration, preset ENV is going to act like the presets for ES2015, 2016, 2017, and 2018. With configuration, we can specify target environments and we can custom tailor our build to the browsers that we expect our application to run in. This configuration will also control the polyfills that are output from Babel polyfill.

[02:24] Let's add some configuration. I'll come over here, and I'm going to start by turning this string into an array, where the first element is our original string and the second element is going to be an options object. In this object, I'm going to create a targets key.

[02:41] That's going to be an object. I'm going to specify that my only target for this is Chrome browsers from versions 68 and up, so recent versions of Chrome. Now, I'm going to add a second key, called use-builtins. I'm going to set that to the string entry. With that done, I'm going to save my configuration.

[03:05] I'm going to go back into the terminal, and I'm going to do an npm run build again. Then I'm going to open that bundle analyzer output. If we look at our overall bundle size, we've gone down to 21k. Previously, with all of core.js added we were at 90k.

[03:31] By targeting a specific browser you'll see that a lot of the polyfills have been removed, and our bundle size has dropped significantly. Right now, we're targeting one specific browser, but this is not a realistic scenario. Usually, we can narrow it down, but we can't pick one specific browser.

[03:50] The way this target setting works is through an integration with a tool called browserslist. Let's take a look at that, and see how we can narrow our focus without being so prescriptive about what browsers our app will run in. I'm going to open up the terminal, and we're going to use NPX to run browserslist. Make sure that's plural, browserslist.

[04:12] Then we're going to pass that a string, and we're going to query for the last two versions of the browsers. When we run this, we're going to get back a list of browsers that represents the last two versions of each of the major browsers.

[04:28] Let's expand our query, and we're going to run that again. We're going to add to the string. In a single string, we'll just make this a comma-separated list, and we're also going to specify that we want browsers that are not considered dead.

[04:43] We'll run that, and we'll see that our list has gotten shorter. If we look, IE no longer has 10 and 11, it's just 11. Let's run one more query, and we're going to add onto that. We're going to say we want browsers that are not less than two percent market share. Now, our list is significantly shorter. We can use these same queries in our Babel configuration.

[05:07] I'm going to go in here to targets, and I'm going to replace this object with an array. This is going to be an array of strings that represent each piece of that query that we just put into the terminal. We're going to do a string for last two versions, and then we'll have another string for not dead, and another string for not less than two percent.

[05:34] We can save that, and now, back in the terminal, I'm going to run npm run build. When that's done, I'm going to open up dist-bundle-sizes.html and we'll see that our core.js module's around 62k. If we look back at the original, where we had the entire thing, we were at 70k.

[06:03] We haven't saved a ton, but we have cut down the size of this when compared to including the whole thing. Let's go back to our settings, and let's add one more piece to our query. The thing that's tripping us up here is that our list still includes IE11. Let's add a string, not IE11, we'll save that.

[06:26] We'll run a build, and then we can open up our new bundle size's report. By dropping that IE11 support, we've dropped our entire bundle down to about 21k, and then core.js is only pulling around 10k of its libraries. Of course, if you still have to support IE11, then you can come back in here, and you can take this part out of your query.

[06:50] This gives you an easy place to control the browsers that you're going to support, and then Babel will intelligently build your bundle and include polyfills, based on those target browsers.

mark connelly
mark connelly
~ 5 years ago

the video shows npm i -S @babel/polyfill but the transcript shows npm i -S @level/polyfill This cought me out for a minute, just use the @babel/polyfill and it all works fine.

Chris
Chris
~ 5 years ago

The setting should be 'not IE 11' (space between IE and 11).

Edwin
Edwin
~ 5 years ago

These series of lectures contain amazing tips!

Thank you Andy!!

Alex
Alex
~ 5 years ago

I am having trouble building:

ERROR in ./src/index.js Module not found: Error: Can't resolve 'core-js/modules/es7.string.trim-left' in '/Users/alex/work/personal/react-biolerplate/src' @ ./src/index.js 2:0-46

Alex
Alex
~ 5 years ago

I am having trouble building:

ERROR in ./src/index.js Module not found: Error: Can't resolve 'core-js/modules/es7.string.trim-left' in '/Users/alex/work/personal/react-biolerplate/src' @ ./src/index.js 2:0-46

npm i -D core-js@2.5.7 resolves this for me. core-js@3.x does not have the module :-(

Fer
Fer
~ 5 years ago

thx @Alex!! =)

Shripada Hebbar
Shripada Hebbar
~ 5 years ago

Looks like @babel/polyfill is deprecated, as of c 7.4.0

npm i -S @babel/polyfill npm WARN deprecated @babel/polyfill@7.4.4: 🚨 As of Babel 7.4.0, this npm WARN deprecated package has been deprecated in favor of directly npm WARN deprecated including core-js/stable (to polyfill ECMAScript npm WARN deprecated features) and regenerator-runtime/runtime npm WARN deprecated (needed to use transpiled generator functions): npm WARN deprecated npm WARN deprecated > import "core-js/stable"; npm WARN deprecated > import "regenerator-runtime/runtime";

core-js@2.6.9 postinstall /Volumes/Development/Learning/React/react-starter/node_modules/core-js node scripts/postinstall || echo "ignore"

Ahmed Soliman
Ahmed Soliman
~ 4 years ago

If we have have babel/polyfill, does babel now still transpile es5+ code or does it only add polyfills or does it do a mix of both ?

Bevin Hernandez
Bevin Hernandez
~ 4 years ago

A few notes, babel/polyfill is now deprecated, so it's useful to still install it, but then you need to:

import "core-js/stable"; import "regenerator-runtime/runtime";

instead of importing @babel/polyfill.

Then, in your config, you need to add: targets: [ "last 2 versions", "not dead", "not < 2%", "not ie 11", ], useBuiltIns: "entry", corejs: "3.0.0",

the last line.

Otherwise it won't trim down your bundle and you'll be very confused as to why it wasn't changing, even though all it was throwing was a warning.

Markdown supported.
Become a member to join the discussionEnroll Today