Skip to content

BabelJs - Project Setup Using Babel 7

Babel 7 (and subsequent versions) introduced significant improvements and changes, primarily namespacing packages under @babel. For example, babel-core became @babel/core, and babel-cli became @babel/cli. This chapter guides you through setting up a basic project using modern Babel.

Let’s create a new project and configure Babel.

First, create a project directory and initialize it with npm (Node Package Manager):

mkdir my-babel-project
cd my-babel-project
npm init -y

This creates a package.json file with default settings.

Install the core Babel packages as development dependencies:

npm install --save-dev @babel/core @babel/cli @babel/preset-env

Let’s break down these packages:

  • @babel/core: The main Babel engine. Required for any Babel transformation.
  • @babel/cli: The command-line interface to run Babel from your terminal.
  • @babel/preset-env: A smart preset that allows you to use the latest JavaScript without needing to micromanage syntax transforms (or polyfills!) for your target environment(s). It automatically determines the Babel plugins and polyfills you need based on your supported environments.

After installation, your package.json’s devDependencies section will look something like this (versions might differ):

{
// ... other package.json content ...
"devDependencies": {
"@babel/cli": "^7.x.x",
"@babel/core": "^7.x.x",
"@babel/preset-env": "^7.x.x"
}
}

Create a Babel configuration file. You can use babel.config.json (recommended for project-wide configuration) or .babelrc.json in your project root. Let’s use babel.config.json:

babel.config.json
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1",
"node": "current" // Or a specific version like "12"
}
}
]
]
}

In this configuration:

  • We specify @babel/preset-env.
  • The targets option tells @babel/preset-env which environments you are targeting. Babel will then only transpile features not supported by these environments, potentially resulting in smaller output and faster builds. You can find more about targets here: https://babeljs.io/docs/babel-preset-env#targets

Create a src directory for your source JavaScript files. Let’s add a main.js file with some modern JavaScript:

src/main.js
const add = (a, b) => a + b;
const name = "Babel User";
console.log(`Hello, ${name}! The sum of 5 and 10 is ${add(5, 10)}.`);
class Greeter {
constructor(greeting) {
this.greeting = greeting;
}
greet(person) {
return `${this.greeting}, ${person}!`;
}
}
const greeter = new Greeter("Hi there");
console.log(greeter.greet("Developer"));

You can now use the Babel CLI to transpile your code. It’s good practice to add a script to your package.json:

// package.json - add to "scripts" section
"scripts": {
"build": "babel src --out-dir lib",
"test": "echo \"Error: no test specified\" && exit 1"
}

Now, run the build script:

npm run build

This command tells Babel to take all files from the src directory, transpile them, and output them to a lib directory, maintaining the original file structure.

After running, you’ll find a lib/main.js file. Its content will be the ES5-compatible version of your src/main.js:

// lib/main.js (Example output, may vary slightly)
"use strict";
function _classCallCheck(instance, Constructor) { /* ... helper ... */ }
function _defineProperties(target, props) { /* ... helper ... */ }
function _createClass(Constructor, protoProps, staticProps) { /* ... helper ... */ }
var add = function add(a, b) {
return a + b;
};
var name = "Babel User";
console.log("Hello, ".concat(name, "! The sum of 5 and 10 is ").concat(add(5, 10), "."));
var Greeter = /*#__PURE__*/function () {
function Greeter(greeting) {
_classCallCheck(this, Greeter);
this.greeting = greeting;
}
_createClass(Greeter, [{
key: "greet",
value: function greet(person) {
return "".concat(this.greeting, ", ").concat(person, "!");
}
}]);
return Greeter;
}();
var greeter = new Greeter("Hi there");
console.log(greeter.greet("Developer"));

The core functionality remains the same, but syntax like arrow functions and classes has been converted to older equivalents. Babel also adds helper functions (like _classCallCheck) if needed for the transformations.

Babel can also transpile TypeScript. First, install the TypeScript preset:

npm install --save-dev @babel/preset-typescript

Then, add it to your babel.config.json (before @babel/preset-env if you want env to process its output):

babel.config.json
{
"presets": [
"@babel/preset-typescript", // Add this
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}

Create a TypeScript file, e.g., src/person.ts:

src/person.ts
interface Person {
firstName: string;
lastName: string;
}
function getFullName(person: Person): string {
return `Hello, ${person.firstName} ${person.lastName}`;
}
const user: Person = { firstName: "Ada", lastName: "Lovelace" };
console.log(getFullName(user));

Update your package.json build script to include .ts files (if your CLI command doesn’t handle it automatically, though modern Babel CLI often does if extensions are configured):

// package.json - "scripts" section
"scripts": {
"build": "babel src --out-dir lib --extensions \".ts,.js\"",
// ...
}

Run npm run build. Babel will strip TypeScript types and transpile the remaining JavaScript. The output in lib/person.js will be standard JavaScript:

// lib/person.js (Example output)
"use strict";
function getFullName(person) {
return "Hello, ".concat(person.firstName, " ").concat(person.lastName);
}
var user = {
firstName: "Ada",
lastName: "Lovelace"
};
console.log(getFullName(user));

Note: @babel/preset-typescript only performs transpilation (removing types). It does not perform type checking. For type checking, you’ll still need to use the TypeScript compiler (tsc). Many projects use tsc for type checking and Babel for transpilation.

With Babel 7+, older presets like babel-preset-es2015, babel-preset-es2016, etc., and babel-preset-latest are deprecated in favor of @babel/preset-env.

Stage presets (e.g., babel-preset-stage-0) for experimental features were also removed. If you need experimental features, you’ll typically include their specific proposal plugins directly. For more information, refer to: https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets

Plugin names also changed. For example, babel-plugin-transform-es2015-classes became @babel/plugin-transform-classes. @babel/preset-env manages these for you based on your targets.