Have you ever been hooked on ES6 JavaScript for frontend development and wished you could use it for backend Node.js projects too? This article will guide you through setting up a Babel transpiler to bridge the gap between modern JavaScript and older Node.js environments.
While TypeScript offers many benefits, JavaScript remains a valid choice for many developers.
Prerequisites
Here are some requirements you need to follow in this tutorial:
Node.js v14 or above installed on your system.
Code editor or IDE: I recommend VSCode.
Basic knowledge of JavaScript and Express.js.
API client for testing our implementation: I recommend Insomnia.
What is ES6?
ES6 refers to version 6 of the ECMAScript programming language. ECMAScript is the standardized name for JavaScript, and version 6 is the next version after version 5, released in 2011.
It significantly enhances the JavaScript language and adds many more features to simplify large-scale software development.
Find out more here.
What is Babel?
Babel is a toolchain mainly used to convert ECMAScript 2015+ (ES6+) code into a backwards-compatible version of JavaScript in current and older browsers or environments.
This also means you can use Babel to convert our ES6 codes for backward compatibility when writing Node.js applications.
A normal JavaScript code snippet for importing express
will look like this:
var express = require('express')
When using ES6 syntax, all you need to do is just import your package like this:
import express from 'express'
Building a Todo API with Node.js, Express, and ES6 🤸
We will use NPM(comes installed with Node.js) as our package manager, and you can use
yarn
if you prefer.
Project Setup
mkdir todo-api
cd todo-api
npm init -y
This helps to initialize a new node project and install the necessary packages for our application.
To install Babel and its required dependencies, open your terminal and execute the following commands.
Babel is the tool we'll use to convert our modern ES6 code into older ES5 code, which is compatible with older Node.js versions.
npm i @babel/cli @babel/core @babel/node @babel/preset-env --save-dev
npm i @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread --save-dev
npm i rimraf nodemon --save-dev
Once you install all the packages, open the folder using your preferred editor if you have not done that earlier.
We will edit the package.json
file to continue the setup for running our application and build the code for deployment on any hosting platform.
We will update the script's section of our package.json
file to complete the setup.
Here is what it should look like 👇
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rimraf dist && babel src --out-dir dist --copy-files",
"start": "node dist/app.js",
"start:dev": "nodemon --exec babel-node src/app.js"
},
Here's a breakdown of the scripts
property in the package.json
file:
The scripts
property in a package.json
file allows you to define custom commands that can be executed directly from the command line.
This simplifies the process of running common tasks like starting a development server, building the project, running tests, or linting code.
build: This command creates our ES6 codes using Babel and dumps the output inside the dist directory (automatically deleted and recreated on every build). The dist directory contains the duplicate files and folders in our base directory. The only difference is that it includes codes transpiled from ES6 to ES5.
start: This command starts our node.js application after converting it to ES5 codes inside the dist directory.
start:dev: This command starts our application using nodemon (it helps to restart our server automatically when any JavaScript file changes) and converts all ES6 codes in memory to ES5 using babel-node. You do not want to do this in production. That is why we have the build command for more optimized performance.
Next, we create a .babelrc
file in the root directory of our application; this file is used to add configurations for our Babel package in order to work correctly.
Copy the code below into the file.
{
"presets": [
["@babel/env", {
"targets": {
"node": "current"
}
}]
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread"
]
}
Follow this link to learn more about using Babel.
Install Express.js:
npm install express cors
Express: A popular web framework for Node.js.
Cors: Middleware for enabling CORS (Cross-Origin Resource Sharing).
Create the src
folder and required files:
mkdir src
touch app.js
touch store.js
Run each line in your terminal.
Finally, your project structure should look like this:
todo-api/
├── src/
│ ├── app.js # API entry point
│ ├── store.js # In-memory data store
├── .babelrc # Babel configuration
├── package.json # Project metadata and dependencies
└── README.md # Project documentation
Updating the store.js
file
We are using in-memory storage to store our data because it is ideal for development and testing.
let todos = [];
let idCounter = 1;
export const getTodos = () => todos;
export const addTodo = (title) => {
const todo = { id: idCounter++, title, completed: false };
todos.push(todo);
return todo;
};
export const updateTodo = (id, updates) => {
const todo = todos.find((t) => t.id === id);
if (!todo) return null;
Object.assign(todo, updates);
return todo;
};
export const deleteTodo = (id) => {
const index = todos.findIndex((t) => t.id === id);
if (index !== -1) {
todos.splice(index, 1);
return true;
}
return false;
};
getTodos: Retrieve all to-do items as an array.
addTodo: Create a new to-do item and append it to the to-do list.
updateTodo: Update an existing to-do item by ID.
deleteTodo: Remove a record from the to-do items by ID.
Updating the app.js file
import express from 'express';
import { getTodos, addTodo, updateTodo, deleteTodo } from './store.js';
const app = express();
app.use(json())
const PORT = process.env.PORT || 3000;
// Routes
app.get('/todos', (req, res) => {
res.json(getTodos());
});
app.post('/todos', (req, res) => {
const { title } = req.body;
if (!title) {
return res.status(400).json({ error: 'Title is required' });
}
const todo = addTodo(title);
res.status(201).json(todo);
});
app.put('/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const updates = req.body;
const updatedTodo = updateTodo(id, updates);
if (!updatedTodo) {
return res.status(404).json({ error: 'Todo not found' });
}
res.json(updatedTodo);
});
app.delete('/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const success = deleteTodo(id);
if (!success) {
return res.status(404).json({ error: 'Todo not found' });
}
res.status(204).end();
});
// Start server
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Running the Server
npm run start:dev
You should have something similar to this.
Testing our implementation on Insomnia
The base URL would be http://localhost:3000
based on my project configuration.
Create a New Todo
Get All Todos
Update a Todo
Delete a Todo
If you encounter any problems, please ensure you've followed all the steps accurately. If you're still facing issues, feel free to comment below, and I'll be happy to assist.
You can expand this project using any architecture or web framework you prefer, like Fastify. Adding a database is also an option. It's entirely up to you.
Key Benefits of ES6 Features 🎯
- Arrow Functions: Concise syntax for defining functions.
- Destructuring: Used to extract values from objects and arrays.
- Template Literals: Used for creating strings with embedded expressions.
- Async/Await: Used for asynchronous operations, making code more readable.
Thanks for coming this far. 🫡
- Please share your ES6 experience with me, and let’s engage in the comment section.
- Share this article with those you believe would benefit from my experience. Cheers 🎉.
You can find the codebase for this article on GitHub.
Top comments (14)
Good and easy to follow content. I think it would be useful to just include for users, how to make a
post
route. Odds are some people would be confused about that.Thanks for the feedback, I will work on that, great idea.
we can just add "type": "module" in the package.json and it will work, or am i wrong?
Hi Diya, you won't enjoy the full benefits of ES6 if you use
"type":"module"
in yourpackage.json
file, that is why Babel was used in this tutorial :)Nice
Thanks for the feedback :)
Nice write up! It's really helpful 👏
Thanks for the feedback :)
Much appreciated
This is 🔥
Well written 🚀
Thanks so much boss. Always an honour 🙇♂️🙇♂️
Great article. Simple and straightforward.
Thanks for this
Thanks for the feedback.
Much appreciated
Thanks for shedding light on this 🤲🏽
Thanks for the feedback boss 🙇♂️🙇♂️