Setting up our development environment with Node and Babel
Babel is a JavaScript compiler, which is used to transpile JavaScript code from ES6+ to normal ES5 specification. Let's set up Babel in our project so that it automatically compiles our code.
There will be two different JS files in our project after setting up Babel. One is ES6, which we use to develop our app, and another will be the compiled ES5 code, which is going to be used by the browser. So, we need to create two different folders in our project root directory, namely, src
and dist
. Move the scripts.js
file into the src
directory. We are going to use Babel to compile the scripts from the src
directory and store the result in the dist
directory. So, in index.html
, change the reference of scripts.js
into <script src="dist/scripts.js"></script>
so that the browser will always read the compiled code:
To use npm, we need to create
package.json
in our project's root directory. Navigate to the project root directory in your terminal and type:
npm init
First, it will ask your project's name, type in a name. For other questions, either type in some values or just hit Enter to accept default values. These values will be populated in the
package.json
file, which can be changed later.Let's install our development dependencies by running the following command in the terminal:
npm install -D http-server babel-cli babel-preset-es2015 concurrently
- This command will create a
node_modules
folder and install the packages inside it. Now, yourpackage.json
file will have the preceding packages in itsdevDependencies
parameter and your current folder structure should be:
. ├── dist ├── index.html ├── node_modules ├── package.json ├── src └── styles.css
Note
If you are using git or any other version control system in your project, add node_modules
and the dist
folder to .gitignore
or a similar file. These folders need not be committed to version control and must be generated when needed.
Time to write scripts to compile our code. Inside the package.json
file, there will be a parameter called scripts
. By default, it will be the following:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" },
test
is one of the default commands for npm. When you run npm test
in the terminal, it will automatically execute the script inside the test key's value in the terminal. As the name suggests, test
is used for executing automated test cases. Some other default commands are start
, stop
, restart
, shrinkwrap
, and so on. These commands are very useful to run scripts when developing server-side applications with Node.js.
However, during frontend development, we may need more commands like the default commands. npm
also allows us to create our commands to execute arbitrary scripts. However, unlike default commands (such as npm start
), we cannot execute our own commands by running npm <command-name>
; we have to execute npm run <command-name>
in the terminal.
We are going to set up npm scripts so that running npm run build
will generate a working build for our application with the compiled ES5 code and running npm run watch
will spin up a development server, which we are going to use for development.
Change the contents of scripts section into the following:
"scripts": { "watch": "babel src -d dist --presets=es2015 -ws", "build": "rm -rf dist && babel src -d dist --presets=es2015", "serve": "http-server" },
Well, that looks like a lot of scripts! Let's go through them one by one.
First, let's check out the watch
script:
The function of this script is to start
babel
in the watch mode so that every time we make any change in our ES6 code insidesrc
directory, it will automatically be transpiled into ES5 code inside thedist
directory along with source maps, which is useful for debugging the compiled code. The watch mode will keep on continuing the process in the terminal until the execution is terminated (hitting Ctrl+C).Execute
npm run watch
in the terminal from your project's root directory. You can see that Babel has started compiling the code and a newscripts.js
file will be created inside thedist
folder.The
scripts.js
file will contain our code in the ES5 format. Open upindex.html
in Chrome and you should see our application running normally.
Here's how it works. Try running babel src -d dist --presets=es2015 -ws
directly in the terminal. It will throw an error saying babel
is not installed (the error message may vary depending on your operating system). This is because we haven't installed Babel globally. We only installed it within our project. So, when we run npm run watch
, npm will look for the binaries for Babel inside the project's node_modules
folder and execute the command using those binaries.
Delete the dist
directory, and create a new script inside package.json
--"babel": "babel src -d dist"
. We are going to use this script for learning how Babel works:
- This script tells Babel compile all the JS files inside the
src
directory and save the resulting files insidedist
directory. Thedist
directory will be created if it is not present. Here, the-d
flag is used to tell Babel that it needs to compile files inside the entire directory. - Run
npm run babel
in the terminal and open up our newscripts.js
file inside thedist
directory. Well, the file is compiled, but unfortunately, the result is also in ES6 syntax, so the newscripts.js
file is an exact copy of our original file! - Our goal is to compile our code to ES5. For that, we need to instruct Babel to use some presets during compilation. Look at our
npm install
command, we have installed a package calledbabel-preset-es2015
for this purpose. - In our Babel script, add the option
--presets=es2015
and executenpm run babel
again. This time the code will be compiled to ES5 syntax. - Open up our application in the browser, add
debugger
inside our constructor, and reload. We have a new problem; the sources will now contain the code in ES5 syntax, which makes it harder to debug our original code. - For this, we need to enable source maps using the
-s
flag that creates a.map
file, which is used to map the compiled code back to the original source. Also, use the-w
flag to put Babel in the watch mode.
And now our script will be the same as the one used in the watch
command. Reload the application with the debugger and you can see that the sources will contain our original code even though it is using the compiled source.
Wouldn't it be nice if running a single command would also start up our development server using http-server
. We cannot use &&
to concatenate two commands that run simultaneously. Since &&
will execute the second command, only after the first one completes.
We have installed another package called concurrently
for this purpose. It is used for executing multiple commands together. Syntax for using concurrently
is as follows:
concurrently "command1" "command2"
When we execute npm run watch
, we need to run both the current watch
script and the serve
script. Change the watch
script into the following:
"watch": "concurrently \"npm run serve\" \"babel src -d dist --presets=es2015 -ws\"",
Try running npm run watch
again. Now, you have a fully functional development environment, which will automatically serve the files as well as compile the code as you make changes to your JS code.
Shipping the code
Once development is done, for shipping the code if you use version control, add the node_modules
and dist
folder to the ignore list. Otherwise, send your code without the node_modules
or dist
folder. Other developers can simply run npm install
to install dependencies and read the scripts inside the package.json
file to build the project when needed.
Our npm run build
command will remove the dist
folder present inside the project folder and create a new dist
folder with the latest build of JS code.