The latest versions of Node.js have pretty good ES6 support out of the box, but using a couple of tools, you can get a fully-functioning environment, just like you're used to on the front end. We'll start by initializing our project here using all of our default values.
We'll then go ahead and install our dev dependencies, which is the Babel CLI itself, Babel preset ES2015, and Nodemon, so that our development environment will restart every time we change our files.
Once those are installed, we can go ahead and create a Babel RC file, which we'll use to configure Babel. Then we'll create an Index.js file inside of a source directory. If we now jump over to our editor, we can just set up our Babel RC file and tell it to use that ES2015 preset that we installed.
If we open up Index.js, we're just going to paste in some simple code here that starts up an HTTP server. You'll notice that we're using the import syntax, which is part of ES6 modules, and that is not supported by Node out of the box, so that's something we do need to be using Babel for if we want to use that in our programs.
There's also an error function in here, but that's supported by Node on its own. You can see that all this code's going to do is spit a simple message out to the console letting us know that the server's running, and any time it receives a request, it's going to reply with, "Hello World."
We'll now jump over here to our packaged JSON file. You can see it did add our dev dependencies here. Then we're going to create a NPM run script called dev. In that, we're just going to call Babel Node and point it at our index file.
Now Babel Node is an executable that you get when you install Babel. It's not the compiler itself, but it's essentially a wrapper around Node that will dynamically compile any files that get required when you run it.
It's not meant for production use, but for development, it's perfect. We can now go over to the console and type NPM run dev, and we see that our server starts up. We can go check it out in the browser, and in fact, it is working.
This is great. We've got our simple server running, via the Babel Node executable, but we don't really want to have to go stop and restart the server every time we change a line of code. To fix that, we're going to use the Nodemon dependency that we installed, and we're just going to modify our dev script here and say, "Nodemon dash dash exec," in front of our existing call to Babel Node.
What that essentially says is, "Nodemon, watch my files." Any time one of them changes, execute this command. Now if we go run NPM run dev again, you'll see that Nodemon is the one starting things up. You can see that output.
Then if we go change our code, we can see that that server will restart. We get the updated message to the console, and so we know that our dev environment is up and running. Believe it or not, that's pretty much all we need to do for our development environment.
Since Babel Node isn't meant to be used in production, what we need to do is set our code up so that we compile it ahead of time before running it in production. To do that, we're going to create an NPM run build script.
In that, we're just going to use the regular Babel executable. We're going to point it at our source directory, and we're going to tell it to spit everything out into the dist directory. Now if we run NPM run build, we can see that it does, in fact, compile each file into its own corresponding file in the output directory.
It created the output directory for us, and now, we can go over here and see what exactly got generated. We can see that our import call was converted to require, and then we have a couple of calls here that help Babel work its magic.
We've got our command defined to compile our code, but we also need to add one to run the code, that can be run when this is deployed to production. For that, we're just going to use NPM start. NPM start is just going to use Node to run the file that we have output into the dist directory.
Obviously, before we run the code in the dist directory, we need to make sure that it has been generated, so we're going to add NPM run build as a precursor to the NPM start script. If we now run NPM start, we can see the code gets built. Then it runs the resulting code for us.
Now, the way I prefer to organize these things is we can actually get rid of this preamble part of the start script. If we rename build to prestart, NPM will automatically run that for us. Any time NPM start is run, it will run prestart first.
Now if we go run NPM start, we can see that the code is still built, and then things start up, but we've simplified and streamlined our scripts here. One more thing we'll want to do is to add the dist directory to our get ignore file, so that we're never checking in generated code.
As one last demonstration of the benefits that we're getting from this workflow, we can actually go in here and update our import statement to use destructuring to just directly pull in that create server method, since that's the only thing we're using from the HTTP module.
We can then save that, go run our NPM run dev again, and see that, in fact, everything is still working as expected.