What's the story behind it?
π¨βπ» I was in a search for an all-in-one article to help me get started with Babel without ever reading the whole documentation
but I didn't found any So, after deeply going through the Babel docs
I'm writing this.
I assure you to move you from zero to a little less than advanced in babel but don't worry I'll also tell you important things to become advance in it.
So, if you've heard about babel but never got into knowing what, why, and how about it, you should continue reading this.
Babel is the Middleman
The left one is the user and the right one is the browser.
JavaScript has evolved a lot in the previous years and the all latest features of JavaScript are not supported in many modern browsers but most of them are.
Babel is the middle man(transpiler) between your modern JavaScript code and the browser you're targetting. It makes sure that whatever JavaScript you're writing will be compatible with almost every browser out there even IE11.
E.g. Opera Mini does not support flatMap()
as of now and babel includes an external library for it to make sure it will work on it.
How it works
It uses AST to make it compiler work(that's a part of compiler design), but you don't have to know anything to make use of it to any level just remember it works upon the modern JavaScript to compile it down to ES15 that most browsers support.
- Use Sourcemap to map both codes.
- Does not do static typing as
TypeScript
.
How to setup
Make sure you have these
-
Node.js
(LTS or latest) npm
Setup a folder with index.js
and run:
npm install --save-dev @babel/core @babel/cli @babel/preset-env
Make a babel.config.json
file in the root directory of your app.
For this configuration, Babel will try to find all .js
files in the src
folder so make sure you've all your files set up.
`{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
]
}`
Add this to package.json
"build": "./node_modules/.bin/babel src --out-dir build"
and run npm run build
Voila! you've done it! there will be a build
folder in your main directory that will contain your converted codes from src.
It was just the Start
Now, we'll understand how it all works. Let's start with
Types of Babel configurations
Project-wide configuration (New in Bable 7.x)
It will just take a simple file babel.config.json
as we did above and find the .js
files as specified in search behavior in the babel.config.json
file.
File-relative configuration
The setup is similar but you can use .babelrc.json
for it just to define it with a higher priority and for differentiating than the main config file.
There can be a few edge cases when you might need it like applying babel to only a single package.
Important thing to remember
File-relative configurations are also merged over top of project-wide config values, making them potentially useful for specific overrides, though that can also be accomplished through "overrides".
Let's talk about what we installed with npm
@babel/core
β All the core functionality of Babel resides here.
@babel/cli
β Babel can be used from CLI with this tool, we're able to use npm run build
because of this.
We used the --out-dir
option behind the scenes that is possible because of @babel/cli
. Run npm run build βhelp
for more info.
@babel/preset-env
β This is a new preset that has been amazing, it has replaced most previous presets, It smartly adds the required libraries to ES5 code.
Let's first understand this π.
Plugins
Babel uses Plugins to perform transformations, Plugins are nothing but small JavaScript programs that instructs Babel to perform required transformations to the code.
Important thing
You can write your own plugins or use official plugins like @babel/plugin-transform-arrow-functions
that is just a plugin to convert modern arrow functions to ES5.
It simply does this.
// From this
const fn = () => 1;
// Converted to this
var fn = function fn() {
return 1;
};
Coming Back to @babel/preset-env
It's simply a set of plugins that can handle all the headaches of setting up plugins manually for every feature. It'll take care of your all smart code most of the time.
Polyfill
π¨ Earlier it was part of babel but now we've to import
it directly with this code in your modern JS code.
Polyfills are not used exclusively because of poor functionality and poor performance. Native implementations of APIs can do more and are faster than polyfills. For example, the Object.create polyfill only contains the functionalities that are possible in a non-native implementation of Object.create.
What is Polyfill?
A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.
For example, a polyfill could be used to mimic the functionality of a [text-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow)
in IE7 using proprietary IE filters, or mimic rem units or media queries by using JavaScript to dynamically adjust the styling as appropriate, or whatever else you require.
Read in depth Mozilla Docs Polyfill
What about it in Babel?
The polyfill module includes core-js
and a custom regenerator runtime to emulate a full ES2015+ environment.
As babel has already removed it but just for the sake of knowing you can import it with this
You've to use
// Install via
npm install --save @babel/polyfill
// Add via
import "core-js/stable";
import "regenerator-runtime/runtime";
Types of configuration in babel
Four ways are listed in priority from lowest to highest.
-
babel.config.json
or insidepackage.json
babel.config.js
.babelrc.json
- programmatic options from
@babel/cli
By priority it simply means that babel.config.json
is overwritten by .babelrc
, and .babelrc
is overwritten by programmatic options
.
You can also write babel.config.json
and .babelrc.json
files using JavaScript.
Options
What are babel options?
Babel options are a way to tell babel to do specific things e.g. minifying, ignoring some file, or explicitly tell babel to compile files from a specific directory while disabling everything else.
Don't worry I'll explain everything I said above.
First understand how we can use any option
Options are defined in your chosen config file let's say that is babel.config.json
.
{
"presets":
[
[
"@babel/env",
{
"targets":
{
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
],
}
-
To minify your output code from babel, just add
minified
to true like below.
{ "presets": [ [ "@babel/env", { "targets": { "edge": "17", "firefox": "60", "chrome": "67", "safari": "11.1" }, "useBuiltIns": "usage", "corejs": "3.6.5" } ] ], "minified": true, }
Now, check your output in
build
directory it should be minified, that basically means removing every extra space and line breaks. -
To ignore a file, add
ignore: ["file or directory path"]
.e.g.
// For Files "ignore" : ["./src/some_file.js"], // For Directory "ignore" : ["./src"],
-
To compile only a specific file or folder.
e.g.
// For Files "only" : ["./src/some_file.js"], // For Directory "only" : ["./src"],
How Babel merges conflicting configurations
Sometimes there can be some situations where we have to specify some configurations that may result in to conflict, so to understanding how babel solves it is crucial to work with such issues.
Babel's configuration merging is simple and predictable.
Options will overwrite existing options when they are present and their value is not undefined. There are, however, a few special cases:
For assumptions, parserOpts and generatorOpts, objects are merged, rather than replaced.
For plugins and presets, they are replaced based on the identity of the plugin/preset object/function itself combined with the name of the entry.
Option (except plugin/preset) merging
As an example, consider a config with:
This is a JavaScript config file
{
sourceType: "script",
assumptions: {
setClassFields: true,
iterableIsArray: false
},
env: {
test: {
sourceType: "module",
assumptions: {
iterableIsArray: true,
},
}
}
};
When NODE_ENV
is test, the sourceType option will be replaced and the assumptions option will be merged. The effective config is:
{
sourceType: "module", // sourceType: "script" is overwritten
assumptions: {
setClassFields: true,
iterableIsArray: true, // assumptions are merged by Object.assign
},
}
Conclusion
Yes!, you did it. Just keep in mind, you should read the docs
as well, there's a lot more stuff.
Definitely read this one π Name Normalization
Sometimes you'll not find an article as I didn't found one when I started writing it. So, get reading docs in your habit to really become a good Software Engineer.
π I'll be adding anything new I found to my repo at Github babel-js Repo
Good Bye!
Top comments (0)