Use the coolest ES6 features everywhere
Posted on November 2, 2016
If you use JavaScript you probably know that recently a lot of new features
arrived with ES2015 (also known as ES6): classes, const
/let
keywords,
destructuring arrays and objects, modules and imports, etc.
You also probably know that all these features are not currently available in all browsers. A very good way to know how one particular feature is supported in all browsers is this ECMAScript 6 compatibility table. Looking at this table, you can think that it’s probably better not to use certain ES6 features because it can crash on some browsers. And what about Node.js? Are these features implemented? In which version?
That’s where a fantastic tool makes sense: Babel. And I’m gonna show you how to use it both client-side and server-side, so you’ll be able to play with latest JavaScript features right now.
I’ll suppose you have a simple project, with a front-end and a back-end (in Node.js). To keep this example the simplest possible, I’ll try to use only really necessary tools. So no Webpack, no Grunt, only npm scripts to build and start the project.
Our example webapp
Let’s start from a really simple webapp. It’s served from a single file in the backend, src/server/app.js:
// src/server/app.js
var express = require('express')
var app = express()
app.use(express.static(__dirname + '/../../public'))
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
For the front-end part, we'll have an index.html file in the public directory:
<!-- public/index.html -->
<pre id="result"></pre>
<script src="js/app.js"></script>
And a JavaScript file, public/lib/app.js:
// public/js/app.js
var o1 = { a: 1, b: 2 }
var o2 = { b: 3, c: 4 }
var o3 = Object.assign({}, o1, o2) // put o1 and o2 properties into a new object o3
document.getElementById('result').innerHTML = JSON.stringify(o3)
Your directory should look like this:
+ public/
+ js/
+ app.js
+ index.html
+ src/
+ server/
+ app.js
As you can see, this application is very useless. We expect that in the browser
when opening http://localhost:3000/index.html
, we get a webpage that will show
exactly {"a":1,"b":3,"c":4}
.
To run this example, you can first initialize your app with a new package.json
(npm init
), then install express
(npm i --save express
), and add an npm
script to start the app in the package.json:
// ...
"scripts": {
"start": "node src/server/app.js"
}
// ...
Then start the application by running: npm start
Here is why we want to use Babel:
- in the back-end, we want to import express as an ES6 module with:
import express from 'express'
- in the front-end, we want use object spread operator:
var o3 = { ...o1, ...o2 }
Again notice this is not very useful, but we need Babel to use this two ES6 features that are not available by default.
Meet Babel
Although there are several ways to use Babel, we'll use it as a command line tool. Basically, it takes as parameter a JavaScript file, and produces a new file created from the first one, but with all ES6 (and next) features replaced with ES5 (classical JavaScript) equivalent. It's called transpilation (compilation from a language from another).
To install Babel, run:
npm i --save-dev babel-cli babel-preset-latest babel-preset-stage-0
. The first
package is the command line tool, and the second and third ones contain the
language features we want. stage-0
contains the more recent (and potentially
not definitive) features.
Create a .babelrc file, containing: { "presets": ["latest", "stage-0"] }
. It
will say to Babel command line tool that we want to use the features we just
installed.
For the front-end
The first step is to put our front-end JavaScript file (public/js/app.js) in another directory. Let's put this app.js file into src/client directory (and delete the public/js directory), and change its content to:
// src/client/app.js
var o1 = { a: 1, b: 2 }
var o2 = { b: 3, c: 4 }
var o3 = { ...o1, ...o2 } // put o1 and o2 properties into a new object o3
document.getElementById('result').innerHTML = JSON.stringify(o3)
Now we must call Babel command line tool to generate the “not-ES6” version of this file. To make things clean, let's create a new npm script:
"scripts": {
// ...
"build:client": "babel src/client -d dist/client"
}
Let's modify a little our src/server/app.js to make it look for our JavaScript file in the right directory:
// src/server/app.js
// ...
app.use(express.static(__dirname + '/../../public'))
app.use('/js', express.static(__dirname + '/../../dist/client'))
// ...
By running npm run build:client
, you should obtain a new app.js file in
dist/client directory. Notice that it's not that different from out first
version ;)
Then try to run the app with npm start
, it still should work!
For the back-end
In our src/server/app.js file, we want to use ES6 module system. Let's edit our file (the first line):
// src/server/app.js
import express from 'express'
Using Babel for the back-end of our application is not difficult either. Just add a npm script and update the existing start script:
// package.json
"scripts": {
"start": "node dist/server/app.js",
// ...
"build:server": "babel src/server -d dist/server"
}
You guessed it, the command npm run build:server
will create a new
dist/server directory with an app.js file. And the npm start
command still
starts the app correctly :)
Note: it's a good idea to put all generated files into a single directory (here dist). This way you can ignore this directory with the versionning tool you use (put it into ths .gitignore for Git for instance).
You've done it! Now you can write all your JavaScript, both back-end and
front-end, using the last language features: async
/await
(cool article
here),
object destructuring (good introduction
here), and a lot of other
stuff!
By the way, the example app for this article is available on GitHub :)
To go further:
- Using Webpack can really change your life when dealing with large front-end applications with several JavaScript files, and of course using Babel with it is supported.
- Babel website lists all available language features and which preset you must install to use them.
Check my latest articles
- 📄 A better learning path for React with server components (May 26, 2023)What if we took advantage of React Server Components not only to improve how we use React, but also how we help people learn it from the beginning?
- 📄 Display a view counter on your blog with React Server Components (April 24, 2023)A short tutorial with a cool use case for React Server Components, Streaming and Suspense with Next.js: adding a view counter on a blog, calling the Plausible analytics API.
- 📄 Using Zod & TypeScript for more than user input validation (March 8, 2023)If you have ever created an API or a form accepting user input, you know what data validation is, and how tedious it can be. Fortunately, libraries can help us, such as Yup or Zod. But recently, I realized that these libraries allow patterns that go much farther than input validation. In this post, I’ll show you why I now use them in most of my TypeScript projects.