Babel is the most widely used tool to compile code
that contains newer syntax into code that different browsers and environments
(such as Node) can understand. This guide assumes you are using Babel, so you
need to follow the setup instructions to
include it into your application if you haven't already. Select
Build Systems if you are using webpack as the module bundler in your app.
Fun fact: Lebab is a separate library that does the opposite of what Babel does. It converts older code into newer syntax.
To use Babel to only transpile what is needed for your users, you need to:
- Identify which browsers you want to target.
@babel/preset-envwith appropriate browser targets.
<script type="module">to stop sending transpiled code to browsers that don't need it.
Identify which browsers you want to target
Before you begin to modify how the code in your application is transpiled, you need to identify which browsers access your application. Analyze which browsers your users are currently using as well as those that you plan to target to make an informed decision.
Transpiling code usually results in a file that is larger than the original larger file sizes than their original forms. By minimizing the amount of compilation that you do you can reduce the size of your bundles to improve the performance of a web page.
Instead of including specific plugins to selectively compile certain language features you are using, Babel provides a number of presets that bundles plugins together. Use @babel/preset-env to only include the transforms and polyfills needed for the browsers you plan on targeting.
@babel/preset-env within the
presets array in your Babel
targets field to specify which browser versions you want to include
by adding an appropriate query to the
integrates with browserslist, an open-source configuration shared between different
tools for targeting browsers. A full list of compatible queries is in the
Another option is to use a
.browserslistrc file to list the environments
you wish to target.
">0.25%" value tells Babel to only include the transforms
needed to support browsers that make up more than 0.25% of global
usage. This ensures your bundle does not contain unnecessary transpiled
code for browsers that are used by a very small percentage of users.
In most cases, this is a better approach than using the following configuration:
"targets": "last 2 versions"
"last 2 versions" value transpiles your code for the
last two versions of every browser,
which means support is provided for discontinued browsers such as Internet Explorer.
This can unnecessarily increase the size of your bundle if you do not expect these
browsers to be used to access your application.
Ultimately, you should select the appropriate combination of queries to only target browsers that fit your needs.
Enable modern bugfixes
them based on the target browsers specified. Although this works well, an entire collection of
syntax features is transformed when a targeted browser contains a bug with just a single feature.
This often results in more transformed code than is necessary.
Originally developed as a separate preset, the
bugfixes option in
solves this problem by converting modern syntax that is broken in some browsers to the closest
equivalent syntax that is not broken in those browsers. The result is nearly identical modern code
with a few small syntax tweaks that guarantee compatibility in all target browsers. To use this
optimization, make sure you have
@babel/preset-env 7.10 or later installed, then set the
bugfixes property to
In Babel 8, the
bugfixes option will be enabled by default.
all major browsers. You can use modules
to create scripts that can import and export from other modules, but you can
also use them with
@babel/preset-env to only target browsers that support
Instead of querying for specific browser versions or market share, consider
"esmodules" : true inside your
Browsers that support modules ignore scripts with a
Conversely, browsers that do not support modules ignore script elements with
type="module". This means you can include a module as well as a compiled fallback.
Ideally, the two version scripts of an application are included like this:
<script type="module" src="main.mjs"></script>
<script nomodule src="compiled.js" defer></script>
Browsers that support modules fetch and execute
main.mjs and ignore
The browsers that do not support modules do the opposite.
Module scripts are deferred by default. The
defer attribute is added to the
nomodule script for the same behavior.
If you use webpack, you can set different targets in your configurations for two separate versions of your application:
- A version only for browsers that support modules.
- A version that includes a compiled script which works in any legacy browser. This has a larger file size, since transpilation needs to support a wider range of browsers.
Although this HTML approach can provide performance benefits, certain browsers have been found to double-fetch when specifying both module and nomodule scripts. Jason Miller's Modern Script Loading explains this in more detail and covers a few options that can be used to circumvent this.
With thanks to Connor Clark and Jason Miller for their reviews.